Skip to content

gh-156049: Add support for building with HWASAN - #156721

Open
StanFromIreland wants to merge 4 commits into
python:mainfrom
StanFromIreland:hwasan-support
Open

StanFromIreland wants to merge 4 commits into
python:mainfrom
StanFromIreland:hwasan-support

Conversation

@StanFromIreland

@StanFromIreland StanFromIreland commented Aug 31, 2026

Copy link
Copy Markdown
Member

This supersedes GH-149166 and GH-156050, pulling in their changes and adding a --with-hwaddress-sanitizer configure option as well as a few little miscellaneous changes for better support. Note that x86-64 has to use clang's page aliasing
mode, which shares the heap across fork(), so the test suite is only reliable
on AArch64.

@AnnaAr321 and @fmayer I'd appreciate your reviews :-)

Co-authored-by: Florian Mayer <fmayer@google.com>
Co-authored-by: Anna <araslanova.anna.a@gmail.com>
@read-the-docs-community

read-the-docs-community Bot commented Aug 31, 2026

Copy link
Copy Markdown

Comment thread Doc/using/configure.rst
@fmayer

fmayer commented Sep 1, 2026

Copy link
Copy Markdown

lgtm

@vstinner

Copy link
Copy Markdown
Member

Hi. You asked me to review this change, but I don't know how to test it manually. Can you provide a way to introduce a bug on purpose and explain how to test that HWASAN detects it properly?

Comment thread Lib/test/support/__init__.py Outdated
Comment thread Doc/using/configure.rst Outdated
Comment thread Doc/using/configure.rst
Comment thread configure.ac Outdated
Comment thread Doc/using/configure.rst
Note that on x86-64 this uses `page aliasing
<https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html#supported-architectures>`_,
which only tags heap allocations and is unsafe for programs that ``fork()``,
including much of the test suite.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you know which GCC and clang versions added support for this sanitizer?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LLVM (the reference implementation) supports it on AArch64, and additionally on x86-64 since LLVM 13 with page aliasing. GCC supports it only on AArch64, since GCC 11.

@StanFromIreland

StanFromIreland commented Sep 22, 2026

Copy link
Copy Markdown
Member Author

Can you provide a way to introduce a bug on purpose and explain how to test that HWASAN detects it properly?

Hi, thanks for the review! If you mean just a trivial example, try for example applying this patch which adds a little heap-use-after-free:

diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c
index a7fefb1fec5..e7fe3131052 100644
--- a/Modules/zlibmodule.c
+++ b/Modules/zlibmodule.c
@@ -1987,6 +1987,9 @@ static unsigned int
 zlib_crc32_impl(PyObject *module, Py_buffer *data, unsigned int value)
 /*[clinic end generated code: output=b217562e4fe6d6a6 input=1229cb2fb5ea948a]*/
 {
+    volatile char *probe = PyMem_RawMalloc(1);
+    PyMem_RawFree((void *)probe);
+    *probe = '\0';
     /* Releasing the GIL for very small buffers is inefficient
        and may lower performance */
     if (data->len > 1024*5) {

Then compile Python with the flag:

./configure --with-hwaddress-sanitizer
make -j16

And run:

$ ./python -c 'import zlib; zlib.crc32(b"x")'

Which for me results in:

==129189==ERROR: HWAddressSanitizer: tag-mismatch on address 0x6802000005c0 at pc 0x000000404d5a
WRITE of size 1 at 0x6802000005c0 tags: 05/1f (ptr/mem) in thread T0
    #0 0x000000404d5a in __hwasan_store1 (/home/stan/dev/cpython/python+0x404d5a) (BuildId: 0e0c51a83d94ef2780e0f8f6b3eb3cebacd90b1d)
    #1 0x7fdd1072f973 in zlib_crc32_impl /home/stan/dev/cpython/./Modules/zlibmodule.c:1992:12
    #2 0x7fdd1072f973 in zlib_crc32 /home/stan/dev/cpython/./Modules/clinic/zlibmodule.c.h:1285:21
    #3 0x0000004e3573 in _PyObject_VectorcallTstate /home/stan/dev/cpython/./Include/internal/pycore_call.h:144:11
    #4 0x0000004e3573 in PyObject_Vectorcall /home/stan/dev/cpython/Objects/call.c:327:12
    #5 0x0000006a51ff in _Py_VectorCallInstrumentation_StackRefSteal /home/stan/dev/cpython/Python/ceval.c:768:11
    #6 0x0000006aa214 in _PyEval_EvalFrameDefault /home/stan/dev/cpython/Python/generated_cases.c.h:1906:35
    #7 0x0000006a4248 in _PyEval_EvalFrame /home/stan/dev/cpython/./Include/internal/pycore_ceval.h:122:16
    #8 0x0000006a4248 in _PyEval_Vector /home/stan/dev/cpython/Python/ceval.c:2172:12
    #9 0x0000006a4248 in PyEval_EvalCode /home/stan/dev/cpython/Python/ceval.c:679:21
    #10 0x0000007642ac in run_mod /home/stan/dev/cpython/Python/pythonrun.c:1509:19
    #11 0x000000762316 in _PyRun_String /home/stan/dev/cpython/Python/pythonrun.c:1292:15
    #12 0x0000007621a6 in _PyRun_SimpleString /home/stan/dev/cpython/Python/pythonrun.c:590:21
    #13 0x00000079a3d9 in pymain_run_command /home/stan/dev/cpython/Modules/main.c:308:18
    #14 0x00000079a3d9 in pymain_run_python /home/stan/dev/cpython/Modules/main.c:795:21
    #15 0x00000079a3d9 in Py_RunMain /home/stan/dev/cpython/Modules/main.c:891:5
    #16 0x00000079a7cc in pymain_main /home/stan/dev/cpython/Modules/main.c:921:12
    #17 0x00000079a8fb in Py_BytesMain /home/stan/dev/cpython/Modules/main.c:945:12
    #18 0x7fdd10bfb5b4 in __libc_start_call_main (/lib64/libc.so.6+0x35b4) (BuildId: 4586895ddf125800fcd0df1f77ad693eac681450)
    #19 0x7fdd10bfb667 in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x3667) (BuildId: 4586895ddf125800fcd0df1f77ad693eac681450)
    #20 0x000000402c54 in _start (/home/stan/dev/cpython/python+0x402c54) (BuildId: 0e0c51a83d94ef2780e0f8f6b3eb3cebacd90b1d)

[0x6802000005c0,0x6802000005d0) is a small unallocated heap chunk; size: 16 offset: 0

Cause: use-after-free
0x6802000005c0 is located 0 bytes inside a 1-byte region [0x6802000005c0,0x6802000005c1)
freed by thread T0 here:
    #0 0x00000040c16b in free (/home/stan/dev/cpython/python+0x40c16b) (BuildId: 0e0c51a83d94ef2780e0f8f6b3eb3cebacd90b1d)
    #1 0x7fdd1072f96b in zlib_crc32_impl /home/stan/dev/cpython/./Modules/zlibmodule.c:1991:5
    #2 0x7fdd1072f96b in zlib_crc32 /home/stan/dev/cpython/./Modules/clinic/zlibmodule.c.h:1285:21
    #3 0x0000004e3573 in _PyObject_VectorcallTstate /home/stan/dev/cpython/./Include/internal/pycore_call.h:144:11
    #4 0x0000004e3573 in PyObject_Vectorcall /home/stan/dev/cpython/Objects/call.c:327:12
    #5 0x0000006a51ff in _Py_VectorCallInstrumentation_StackRefSteal /home/stan/dev/cpython/Python/ceval.c:768:11
    #6 0x0000006aa214 in _PyEval_EvalFrameDefault /home/stan/dev/cpython/Python/generated_cases.c.h:1906:35
    #7 0x0000006a4248 in _PyEval_EvalFrame /home/stan/dev/cpython/./Include/internal/pycore_ceval.h:122:16
    #8 0x0000006a4248 in _PyEval_Vector /home/stan/dev/cpython/Python/ceval.c:2172:12
    #9 0x0000006a4248 in PyEval_EvalCode /home/stan/dev/cpython/Python/ceval.c:679:21
    #10 0x0000007642ac in run_mod /home/stan/dev/cpython/Python/pythonrun.c:1509:19
    #11 0x000000762316 in _PyRun_String /home/stan/dev/cpython/Python/pythonrun.c:1292:15
    #12 0x0000007621a6 in _PyRun_SimpleString /home/stan/dev/cpython/Python/pythonrun.c:590:21
    #13 0x00000079a3d9 in pymain_run_command /home/stan/dev/cpython/Modules/main.c:308:18
    #14 0x00000079a3d9 in pymain_run_python /home/stan/dev/cpython/Modules/main.c:795:21
    #15 0x00000079a3d9 in Py_RunMain /home/stan/dev/cpython/Modules/main.c:891:5
    #16 0x00000079a7cc in pymain_main /home/stan/dev/cpython/Modules/main.c:921:12
    #17 0x00000079a8fb in Py_BytesMain /home/stan/dev/cpython/Modules/main.c:945:12
    #18 0x7fdd10bfb5b4 in __libc_start_call_main (/lib64/libc.so.6+0x35b4) (BuildId: 4586895ddf125800fcd0df1f77ad693eac681450)
    #19 0x7fdd10bfb667 in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x3667) (BuildId: 4586895ddf125800fcd0df1f77ad693eac681450)
    #20 0x000000402c54 in _start (/home/stan/dev/cpython/python+0x402c54) (BuildId: 0e0c51a83d94ef2780e0f8f6b3eb3cebacd90b1d)

previously allocated by thread T0 here:
    #0 0x00000040c888 in malloc (/home/stan/dev/cpython/python+0x40c888) (BuildId: 0e0c51a83d94ef2780e0f8f6b3eb3cebacd90b1d)
    #1 0x7fdd1072f960 in zlib_crc32_impl /home/stan/dev/cpython/./Modules/zlibmodule.c:1990:28
    #2 0x7fdd1072f960 in zlib_crc32 /home/stan/dev/cpython/./Modules/clinic/zlibmodule.c.h:1285:21
    #3 0x0000004e3573 in _PyObject_VectorcallTstate /home/stan/dev/cpython/./Include/internal/pycore_call.h:144:11
    #4 0x0000004e3573 in PyObject_Vectorcall /home/stan/dev/cpython/Objects/call.c:327:12
    #5 0x0000006a51ff in _Py_VectorCallInstrumentation_StackRefSteal /home/stan/dev/cpython/Python/ceval.c:768:11
    #6 0x0000006aa214 in _PyEval_EvalFrameDefault /home/stan/dev/cpython/Python/generated_cases.c.h:1906:35
    #7 0x0000006a4248 in _PyEval_EvalFrame /home/stan/dev/cpython/./Include/internal/pycore_ceval.h:122:16
    #8 0x0000006a4248 in _PyEval_Vector /home/stan/dev/cpython/Python/ceval.c:2172:12
    #9 0x0000006a4248 in PyEval_EvalCode /home/stan/dev/cpython/Python/ceval.c:679:21
    #10 0x0000007642ac in run_mod /home/stan/dev/cpython/Python/pythonrun.c:1509:19
    #11 0x000000762316 in _PyRun_String /home/stan/dev/cpython/Python/pythonrun.c:1292:15
    #12 0x0000007621a6 in _PyRun_SimpleString /home/stan/dev/cpython/Python/pythonrun.c:590:21
    #13 0x00000079a3d9 in pymain_run_command /home/stan/dev/cpython/Modules/main.c:308:18
    #14 0x00000079a3d9 in pymain_run_python /home/stan/dev/cpython/Modules/main.c:795:21
    #15 0x00000079a3d9 in Py_RunMain /home/stan/dev/cpython/Modules/main.c:891:5
    #16 0x00000079a7cc in pymain_main /home/stan/dev/cpython/Modules/main.c:921:12
    #17 0x00000079a8fb in Py_BytesMain /home/stan/dev/cpython/Modules/main.c:945:12
    #18 0x7fdd10bfb5b4 in __libc_start_call_main (/lib64/libc.so.6+0x35b4) (BuildId: 4586895ddf125800fcd0df1f77ad693eac681450)
    #19 0x7fdd10bfb667 in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x3667) (BuildId: 4586895ddf125800fcd0df1f77ad693eac681450)
    #20 0x000000402c54 in _start (/home/stan/dev/cpython/python+0x402c54) (BuildId: 0e0c51a83d94ef2780e0f8f6b3eb3cebacd90b1d)

hwasan_dev_note_heap_rb_distance: 1 1023
hwasan_dev_note_num_matching_addrs: 0
hwasan_dev_note_num_matching_addrs_4b: 0
Thread: T0 0x5fff00002000 stack: [0x7ffc35499000,0x7ffc35c99000) sz: 8388608 tls: [0x7fdd10bf6c00,0x7fdd10bf7d00)


Memory tags around the buggy address (one tag corresponds to 16 bytes):
  0x6801fffffd00: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00 
  0x6801fffffe00: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00 
  0x6801ffffff00: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00 
  0x680200000000: 01  0c  06  06  0c  0c  01  08  08  0c  0f  0f  08  07  01  0d 
  0x680200000100: 0e  0f  01  01  0f  07  0c  0c  0c  0b  0d  01  01  0f  0f  08 
  0x680200000200: 08  04  0f  04  02  08  08  05  06  09  05  05  06  04  04  03 
  0x680200000300: 04  04  05  08  04  04  04  07  07  06  07  07  09  07  04  05 
  0x680200000400: 05  03  06  03  04  03  04  03  06  03  06  01  08  03  01  06 
=>0x680200000500: 05  01  03  0f  01  04  01  04  07  77  04  0e [1f] 00  00  00 
  0x680200000600: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00 
  0x680200000700: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00 
  0x680200000800: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00 
  0x680200000900: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00 
  0x680200000a00: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00 
  0x680200000b00: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00 
  0x680200000c00: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00 
  0x680200000d00: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00 
Tags for short granules around the buggy address (one tag corresponds to 16 bytes):
  0x680200000400: 03  01  06  07  07  06  01  07  02  02  05  02  06  00  05  04 
=>0x680200000500: 00  03  00  04  01  00  06  00  00  ..  01  06 [..] ..  ..  .. 
  0x680200000600: ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  .. 
See https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html#short-granules for a description of short granule tags
SUMMARY: HWAddressSanitizer: tag-mismatch (/home/stan/dev/cpython/python+0x404d5a) (BuildId: 0e0c51a83d94ef2780e0f8f6b3eb3cebacd90b1d) in __hwasan_store1

Co-authored-by: Victor Stinner <vstinner@python.org>
@StanFromIreland

Copy link
Copy Markdown
Member Author

I pushed a commit which incorporates the fix in #157934 for MSan/ASan.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants