Open
Description
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.