Skip to content

Address sanitizer build (1312) #766

Open
@GalacticEmperor1

Description

@GalacticEmperor1

Issue №1312 opened by illume at 2019-09-17 09:16:06

Doing a test run with an address sanitizer apparently helps to detect various types of bugs.

AddressSanitizer is a fast memory error detector. It consists of a compiler instrumentation module and a run-time library. The tool can detect the following types of bugs:

  • Out-of-bounds accesses to heap, stack and globals
  • Use-after-free
  • Use-after-return (runtime flag ASAN_OPTIONS=detect_stack_use_after_return=1)
  • Use-after-scope (clang flag -fsanitize-address-use-after-scope)
  • Double-free, invalid free
  • Memory leaks (experimental)

How to compile a python C extension with clang on MacOS:

LDFLAGS="-g -fsanitize=address" CFLAGS="-g -fsanitize=address -fno-omit-frame-pointer" python3 setup.py install

Comments

# # illume commented at 2019-09-28 21:22:17

Here's one issue it found running the tests...

DYLD_INSERT_LIBRARIES=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/10.0.0/lib/darwin/libclang_rt.asan_osx_dynamic.dylib \
/usr/local/Cellar/python/3.7.4_1/Frameworks/Python.framework/Versions/3.7/Resources/Python.app/Contents/MacOS/Python \
test/mask_test.py -v
AddressSanitizer: heap-buffer-overflow bitmask.c:882 in bitmask_draw mask_test.py:test_draw__bit_boundaries

test_draw__bit_boundaries (__main__.MaskTypeTest)
Ensures draw handles masks of different sizes correctly. ... =================================================================
==75420==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x603000031c50 at pc 0x00010d735a80 bp 0x7ffee6c5e630 sp 0x7ffee6c5e628
READ of size 8 at 0x603000031c50 thread T0
    # 0 0x10d735a7f in bitmask_draw bitmask.c:882
    # 1 0x10d729d32 in mask_draw mask.c:313
    # 2 0x10a031abb in _PyMethodDef_RawFastCallKeywords (Python:x86_64+0x1aabb)
    # 3 0x10a036555 in _PyMethodDescr_FastCallKeywords (Python:x86_64+0x1f555)
    # 4 0x10a0c7150 in call_function (Python:x86_64+0xb0150)
    # 5 0x10a0bfce3 in _PyEval_EvalFrameDefault (Python:x86_64+0xa8ce3)
    # 6 0x10a031515 in function_code_fastcall (Python:x86_64+0x1a515)
    # 7 0x10a0c7120 in call_function (Python:x86_64+0xb0120)
    # 8 0x10a0bfd9a in _PyEval_EvalFrameDefault (Python:x86_64+0xa8d9a)
    # 9 0x10a0c79b5 in _PyEval_EvalCodeWithName (Python:x86_64+0xb09b5)
    # 10 0x10a030d68 in _PyFunction_FastCallDict (Python:x86_64+0x19d68)
    # 11 0x10a031ebc in _PyObject_Call_Prepend (Python:x86_64+0x1aebc)
    # 12 0x10a031248 in PyObject_Call (Python:x86_64+0x1a248)
    # 13 0x10a0c0013 in _PyEval_EvalFrameDefault (Python:x86_64+0xa9013)
    # 14 0x10a0c79b5 in _PyEval_EvalCodeWithName (Python:x86_64+0xb09b5)
    # 15 0x10a030d68 in _PyFunction_FastCallDict (Python:x86_64+0x19d68)
    # 16 0x10a031ebc in _PyObject_Call_Prepend (Python:x86_64+0x1aebc)
    # 17 0x10a06efa3 in slot_tp_call (Python:x86_64+0x57fa3)
    # 18 0x10a030fa0 in _PyObject_FastCallKeywords (Python:x86_64+0x19fa0)
    # 19 0x10a0c7119 in call_function (Python:x86_64+0xb0119)
    # 20 0x10a0bfd9a in _PyEval_EvalFrameDefault (Python:x86_64+0xa8d9a)
    # 21 0x10a0c79b5 in _PyEval_EvalCodeWithName (Python:x86_64+0xb09b5)
    # 22 0x10a030d68 in _PyFunction_FastCallDict (Python:x86_64+0x19d68)
    # 23 0x10a031ebc in _PyObject_Call_Prepend (Python:x86_64+0x1aebc)
    # 24 0x10a031248 in PyObject_Call (Python:x86_64+0x1a248)
    # 25 0x10a0c0013 in _PyEval_EvalFrameDefault (Python:x86_64+0xa9013)
    # 26 0x10a0c79b5 in _PyEval_EvalCodeWithName (Python:x86_64+0xb09b5)
    # 27 0x10a030d68 in _PyFunction_FastCallDict (Python:x86_64+0x19d68)
    # 28 0x10a031ebc in _PyObject_Call_Prepend (Python:x86_64+0x1aebc)
    # 29 0x10a06efa3 in slot_tp_call (Python:x86_64+0x57fa3)
    # 30 0x10a030fa0 in _PyObject_FastCallKeywords (Python:x86_64+0x19fa0)
    # 31 0x10a0c7119 in call_function (Python:x86_64+0xb0119)
    # 32 0x10a0bfd9a in _PyEval_EvalFrameDefault (Python:x86_64+0xa8d9a)
    # 33 0x10a0c79b5 in _PyEval_EvalCodeWithName (Python:x86_64+0xb09b5)
    # 34 0x10a030d68 in _PyFunction_FastCallDict (Python:x86_64+0x19d68)
    # 35 0x10a031ebc in _PyObject_Call_Prepend (Python:x86_64+0x1aebc)
    # 36 0x10a031248 in PyObject_Call (Python:x86_64+0x1a248)
    # 37 0x10a0c0013 in _PyEval_EvalFrameDefault (Python:x86_64+0xa9013)
    # 38 0x10a0c79b5 in _PyEval_EvalCodeWithName (Python:x86_64+0xb09b5)
    # 39 0x10a030d68 in _PyFunction_FastCallDict (Python:x86_64+0x19d68)
    # 40 0x10a031ebc in _PyObject_Call_Prepend (Python:x86_64+0x1aebc)
    # 41 0x10a06efa3 in slot_tp_call (Python:x86_64+0x57fa3)
    # 42 0x10a030fa0 in _PyObject_FastCallKeywords (Python:x86_64+0x19fa0)
    # 43 0x10a0c7119 in call_function (Python:x86_64+0xb0119)
    # 44 0x10a0bfd9a in _PyEval_EvalFrameDefault (Python:x86_64+0xa8d9a)
    # 45 0x10a031515 in function_code_fastcall (Python:x86_64+0x1a515)
    # 46 0x10a0c7120 in call_function (Python:x86_64+0xb0120)
    # 47 0x10a0bfce3 in _PyEval_EvalFrameDefault (Python:x86_64+0xa8ce3)
    # 48 0x10a031515 in function_code_fastcall (Python:x86_64+0x1a515)
    # 49 0x10a0c7120 in call_function (Python:x86_64+0xb0120)
    # 50 0x10a0bfce3 in _PyEval_EvalFrameDefault (Python:x86_64+0xa8ce3)
    # 51 0x10a0c79b5 in _PyEval_EvalCodeWithName (Python:x86_64+0xb09b5)
    # 52 0x10a030d68 in _PyFunction_FastCallDict (Python:x86_64+0x19d68)
    # 53 0x10a031ebc in _PyObject_Call_Prepend (Python:x86_64+0x1aebc)
    # 54 0x10a06f99e in slot_tp_init (Python:x86_64+0x5899e)
    # 55 0x10a06c66a in type_call (Python:x86_64+0x5566a)
    # 56 0x10a030fa0 in _PyObject_FastCallKeywords (Python:x86_64+0x19fa0)
    # 57 0x10a0c7119 in call_function (Python:x86_64+0xb0119)
    # 58 0x10a0bfcfc in _PyEval_EvalFrameDefault (Python:x86_64+0xa8cfc)
    # 59 0x10a0c79b5 in _PyEval_EvalCodeWithName (Python:x86_64+0xb09b5)
    # 60 0x10a0be10c in PyEval_EvalCode (Python:x86_64+0xa710c)
    # 61 0x10a0ecfa4 in run_mod (Python:x86_64+0xd5fa4)
    # 62 0x10a0ebfbf in PyRun_FileExFlags (Python:x86_64+0xd4fbf)
    # 63 0x10a0eb679 in PyRun_SimpleFileExFlags (Python:x86_64+0xd4679)
    # 64 0x10a104016 in pymain_main (Python:x86_64+0xed016)
    # 65 0x10a1048a6 in _Py_UnixMain (Python:x86_64+0xed8a6)
    # 66 0x7fff64333014 in start (libdyld.dylib:x86_64+0x1014)

0x603000031c50 is located 8 bytes to the right of 24-byte region [0x603000031c30,0x603000031c48)
allocated by thread T0 here:
    # 0 0x108ffef53 in wrap_malloc (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x56f53)
    # 1 0x10d7321a8 in bitmask_create bitmask.c:119
    # 2 0x10d72780f in mask_init mask.c:2359
    # 3 0x10a06c66a in type_call (Python:x86_64+0x5566a)
    # 4 0x10a030fa0 in _PyObject_FastCallKeywords (Python:x86_64+0x19fa0)
    # 5 0x10a0c7119 in call_function (Python:x86_64+0xb0119)
    # 6 0x10a0bfcfc in _PyEval_EvalFrameDefault (Python:x86_64+0xa8cfc)
    # 7 0x10a031515 in function_code_fastcall (Python:x86_64+0x1a515)
    # 8 0x10a0c7120 in call_function (Python:x86_64+0xb0120)
    # 9 0x10a0bfd9a in _PyEval_EvalFrameDefault (Python:x86_64+0xa8d9a)
    # 10 0x10a0c79b5 in _PyEval_EvalCodeWithName (Python:x86_64+0xb09b5)
    # 11 0x10a030d68 in _PyFunction_FastCallDict (Python:x86_64+0x19d68)
    # 12 0x10a031ebc in _PyObject_Call_Prepend (Python:x86_64+0x1aebc)
    # 13 0x10a031248 in PyObject_Call (Python:x86_64+0x1a248)
    # 14 0x10a0c0013 in _PyEval_EvalFrameDefault (Python:x86_64+0xa9013)
    # 15 0x10a0c79b5 in _PyEval_EvalCodeWithName (Python:x86_64+0xb09b5)
    # 16 0x10a030d68 in _PyFunction_FastCallDict (Python:x86_64+0x19d68)
    # 17 0x10a031ebc in _PyObject_Call_Prepend (Python:x86_64+0x1aebc)
    # 18 0x10a06efa3 in slot_tp_call (Python:x86_64+0x57fa3)
    # 19 0x10a030fa0 in _PyObject_FastCallKeywords (Python:x86_64+0x19fa0)
    # 20 0x10a0c7119 in call_function (Python:x86_64+0xb0119)
    # 21 0x10a0bfd9a in _PyEval_EvalFrameDefault (Python:x86_64+0xa8d9a)
    # 22 0x10a0c79b5 in _PyEval_EvalCodeWithName (Python:x86_64+0xb09b5)
    # 23 0x10a030d68 in _PyFunction_FastCallDict (Python:x86_64+0x19d68)
    # 24 0x10a031ebc in _PyObject_Call_Prepend (Python:x86_64+0x1aebc)
    # 25 0x10a031248 in PyObject_Call (Python:x86_64+0x1a248)
    # 26 0x10a0c0013 in _PyEval_EvalFrameDefault (Python:x86_64+0xa9013)
    # 27 0x10a0c79b5 in _PyEval_EvalCodeWithName (Python:x86_64+0xb09b5)
    # 28 0x10a030d68 in _PyFunction_FastCallDict (Python:x86_64+0x19d68)
    # 29 0x10a031ebc in _PyObject_Call_Prepend (Python:x86_64+0x1aebc)

SUMMARY: AddressSanitizer: heap-buffer-overflow bitmask.c:882 in bitmask_draw
Shadow bytes around the buggy address:
  0x1c0600006330: fa fa fd fd fd fa fa fa fd fd fd fa fa fa fd fd
  0x1c0600006340: fd fa fa fa fd fd fd fa fa fa fd fd fd fa fa fa
  0x1c0600006350: fd fd fd fa fa fa fd fd fd fa fa fa fd fd fd fa
  0x1c0600006360: fa fa fd fd fd fa fa fa fd fd fd fa fa fa fd fd
  0x1c0600006370: fd fa fa fa fd fd fd fa fa fa fd fd fd fa fa fa
=>0x1c0600006380: fd fd fd fa fa fa 00 00 00 fa[fa]fa 00 00 00 fa
  0x1c0600006390: fa fa 00 00 00 fa fa fa fa fa fa fa fa fa fa fa
  0x1c06000063a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x1c06000063b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x1c06000063c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x1c06000063d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==75420==ABORTING
Abort trap: 6


# # illume commented at 2019-09-28 21:26:57

Note, to get best results all the dependencies including SDL and python should also be instrumented with asan.

Metadata

Metadata

Assignees

No one assigned

    Labels

    CIIssue with the Continuous Integration (CI), the actions/bots that test thingsCode quality/robustnessCode quality and resilience to changes

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions