This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: UBSAN: test_ctypes, test_faulthandler and test_hashlib are failing
Type: Stage: patch review
Components: Tests Versions: Python 3.11
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: christian.heimes, gregory.p.smith, martin.panter, miss-islington, pablogsal, vstinner
Priority: normal Keywords: patch

Created on 2022-03-03 16:19 by vstinner, last changed 2022-04-11 14:59 by admin.

Pull Requests
URL Status Linked Edit
PR 31662 merged vstinner, 2022-03-03 16:59
PR 31665 closed miss-islington, 2022-03-03 20:45
PR 31666 closed miss-islington, 2022-03-03 20:45
PR 31672 merged vstinner, 2022-03-03 22:56
PR 31673 merged vstinner, 2022-03-03 23:16
PR 31674 merged vstinner, 2022-03-03 23:20
PR 31675 merged vstinner, 2022-03-03 23:47
PR 31676 merged vstinner, 2022-03-04 00:15
Messages (20)
msg414455 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2022-03-03 16:19
I recently changed how tests are skipped in ASAN, MSAN and UBSAN CIs (buildbot workers and GitHub Action jobs):

* bpo-46633
* https://github.com/python/buildmaster-config/commit/0fd1e3e49e4b688d5767501484cccea5fa35d3fc

3 tests are now failing on "AMD64 Arch Linux Usan 3.x":

* test_ctypes
* test_faulthandler
* test_hashlib

First failed build:
https://buildbot.python.org/all/#/builders/719/builds/632
msg414456 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2022-03-03 16:20
test_ctypes: test_shorts() of ctypes.test.test_bitfields.C_Test is failing with:

---
test_shorts (ctypes.test.test_bitfields.C_Test) ... /home/vstinner/python/main/Modules/_ctypes/cfield.c:554:5: runtime error: shift exponent 18446744073709551614 is too large for 16-bit type 'short'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /home/vstinner/python/main/Modules/_ctypes/cfield.c:554:5 in 
---

It's a test on the "h" format code:
----
#define LOW_BIT(x)  ((x) & 0xFFFF)
#define NUM_BITS(x) ((x) >> 16)

#define GET_BITFIELD(v, size)                                           \
    if (NUM_BITS(size)) {                                               \
        v <<= (sizeof(v)*8 - LOW_BIT(size) - NUM_BITS(size));           \
        v >>= (sizeof(v)*8 - NUM_BITS(size));                           \

static PyObject *
h_get(void *ptr, Py_ssize_t size)
{
    short val;
    memcpy(&val, ptr, sizeof(val));
    GET_BITFIELD(val, size); // <==== HERE
    return PyLong_FromLong((long)val);
}

static struct fielddesc formattable[] = {
    ...
    { 'h', h_set, h_get, NULL, h_set_sw, h_get_sw},
    ...
};
----
msg414457 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2022-03-03 16:21
test_hashlib: test_gil() fails with:
---
test_gil (test.test_hashlib.HashLibTestCase) ... /home/vstinner/python/main/Modules/_sha3/kcp/KeccakP-1600-opt64.c:467:9: runtime error: load of misaligned address 0x000002daafd7 for type 'UINT64' (aka 'unsigned long'), which requires 8 byte alignment
0x000002daafd7: note: pointer points here
 23 23 23 23 23  23 23 23 23 23 23 23 23  23 23 23 23 23 23 23 23  23 23 23 23 23 23 23 23  23 23 23
             ^ 
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /home/vstinner/python/main/Modules/_sha3/kcp/KeccakP-1600-opt64.c:467:9 in 
---
msg414458 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2022-03-03 16:22
test_faulthandler: test_sigfpe() fails with:

======================================================================
FAIL: test_sigfpe (test.test_faulthandler.FaultHandlerTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/vstinner/python/main/Lib/test/test_faulthandler.py", line 228, in test_sigfpe
    self.check_fatal_error("""
    ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vstinner/python/main/Lib/test/test_faulthandler.py", line 129, in check_fatal_error
    self.check_error(code, line_number, fatal_error, **kw)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vstinner/python/main/Lib/test/test_faulthandler.py", line 122, in check_error
    self.assertRegex(output, regex)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: Regex didn't match: '(?m)^Fatal Python error: Floating point exception\n\nCurrent thread 0x[0-9a-f]+ \\(most recent call first\\):\n  File "<string>", line 3 in <module>' not found in 'Modules/faulthandler.c:1112:11: runtime error: division by zero\nSUMMARY: UndefinedBehaviorSanitizer: undefined-behavior Modules/faulthandler.c:1112:11 in '
msg414471 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2022-03-03 20:45
New changeset 4173d677a1d7c72bb32d292fbff1b4cf073d615c by Victor Stinner in branch 'main':
bpo-46913: Fix test_faulthandler.test_sigfpe() on UBSAN (GH-31662)
https://github.com/python/cpython/commit/4173d677a1d7c72bb32d292fbff1b4cf073d615c
msg414477 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2022-03-03 22:05
Reproducer of test_ctypes undefined behavior:
---
from ctypes import *

class BITS(Structure):
    _fields_ = [("A", c_int, 1),
                ("B", c_int, 2),
                ("C", c_int, 3),
                ("D", c_int, 4),
                ("E", c_int, 5),
                ("F", c_int, 6),
                ("G", c_int, 7),
                ("H", c_int, 8),
                ("I", c_int, 9),

                ("M", c_short, 1),
                ("N", c_short, 2),
                ("O", c_short, 3),
                ("P", c_short, 4),
                ("Q", c_short, 5),
                ("R", c_short, 6),
                ("S", c_short, 7)]

b = BITS()
a = getattr(b, "M")
---

>     GET_BITFIELD(val, size); // <==== HERE

I expanded the macro:
---
    if (NUM_BITS(size)) {
        size_t s = sizeof(val)*8;
        Py_ssize_t low = LOW_BIT(size);
        Py_ssize_t nbits = NUM_BITS(size);
        // val=0, size=65553 = (1 << 16) + 17
        // s=16, low=17, nbits=1
        // s - low - nbits = (size_t)-2
        val <<= (s - low - nbits);
        val >>= (s - nbits);
    }
---

The problem is that (s - low - nbits) is negative (-2), but becomes a very large number since it's unsigned (s is unsigned: "sizeof(v)*8" in the macro).

C code:
---
#include <stdio.h>

int main()
{
    short s = 0x7fff;
    size_t z = (size_t)-2;
    s <<= z;
    printf("s = %hi\n", s);
    return 0;
}
---

GCC and clang disagree :-D
---
$ gcc x.c -o x -O3 -Wall -Wextra -Wconversion && ./x
s = 0

$ clang x.c -o x -O3 -Wall -Wextra -Wconversion && ./x
s = -5784
---

Moreover, runtime the binary built by clang produces a different result at each run...
---
$ ./x
s = -4824
$ ./x
s = 4120
$ ./x
s = -22344
$ ./x
s = -26744
$ ./x
s = -18184
---
msg414486 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2022-03-03 22:45
> https://github.com/python/buildmaster-config/commit/0fd1e3e49e4b688d5767501484cccea5fa35d3fc

Previously, 4 tests were skipped on the UBSAN buildbot

* test_faulthandler
* test_hashlib
* test_concurrent_futures
* test_ctypes

It's not a regression, it's just that I made the buildbot stricter. I'm planning to attempt to fix the 3 failing tests, or at least skip them in Python, rather than skipping them in the buildbot configuration.
msg414489 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2022-03-03 23:25
New changeset 65b92ccdec2ee4a99e54aaf7ae2d9bbc2ebfe549 by Victor Stinner in branch 'main':
bpo-46913: Fix test_faulthandler.test_read_null() on UBSan (GH31672)
https://github.com/python/cpython/commit/65b92ccdec2ee4a99e54aaf7ae2d9bbc2ebfe549
msg414491 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2022-03-03 23:36
See also bpo-46887: ./Programs/_freeze_module fails with MSAN: Uninitialized value was created by an allocation of 'stat.i'.
msg414494 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2022-03-03 23:41
New changeset 6d0d7d2b8c1e04fd51c6cb29cc09a41b60b97b7b by Victor Stinner in branch 'main':
bpo-46913: test_hashlib skips _sha3 tests on UBSan (GH-31673)
https://github.com/python/cpython/commit/6d0d7d2b8c1e04fd51c6cb29cc09a41b60b97b7b
msg414495 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2022-03-03 23:42
New changeset ad1b04451d3aca2c6fa6dbe2891676a4e0baac49 by Victor Stinner in branch 'main':
bpo-46913: Skip test_ctypes.test_shorts() on UBSan (GH-31674)
https://github.com/python/cpython/commit/ad1b04451d3aca2c6fa6dbe2891676a4e0baac49
msg414497 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2022-03-03 23:54
I pushed changes just to turn back the buildbot back to green, but undefined behaviors in test_ctypes.test_shorts() and _sha3 (tested by test_hashlib) must be fixed.

Previously, test_ctypes, test_hashlib and test_faulthandler were fully skipped on UBSan. Now only 1 test_ctypes test and a few test_hashlib tests are skipped on the UBSan buildbot (test_faulthandler now pass on UBSan).
msg414499 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2022-03-04 00:12
New changeset 7b5b429adab4fe0fe81858fe3831f06adc2e2141 by Victor Stinner in branch '3.10':
[3.10] bpo-46913: Fix test_ctypes, test_hashlib, test_faulthandler on UBSan (GH-31675)
https://github.com/python/cpython/commit/7b5b429adab4fe0fe81858fe3831f06adc2e2141
msg414501 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2022-03-04 00:32
New changeset 6a14330318c9c7aedf3e9841c3dfea337064d8e6 by Victor Stinner in branch '3.9':
bpo-46913: Fix test_ctypes, test_hashlib, test_faulthandler on UBSan (GH-31675) (GH-31676)
https://github.com/python/cpython/commit/6a14330318c9c7aedf3e9841c3dfea337064d8e6
msg414507 - (view) Author: Christian Heimes (christian.heimes) * (Python committer) Date: 2022-03-04 07:49
I don't agree with GH-31673. Did you try defining NO_MISALIGNED_ACCESSES instead?
msg414512 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2022-03-04 09:42
> I don't agree with GH-31673. Did you try defining NO_MISALIGNED_ACCESSES instead?

Did you read the commit message? The change is not about skipping the test, but fixing the CI. Previously, test_hashlib was not run at all on the UBSan buildbot, now most test_hashlib tests are run. The intent is to make sure that we don't add *new* undefined behavior.

As I wrote in the commit, the UD must be fixed in _sha3.

No, I didn't try NO_MISALIGNED_ACCESSES, I don't know this macro. If you have an idea on how _sha3 can be fixed on the UBSan buildbot, please go head!
msg414694 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2022-03-07 19:24
The ctypes overflow is probably the same as described in Issue 28169 and Issue 15119
msg414867 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2022-03-10 17:01
Current status of tests skipped on ASAN, MSAN and UBSAN.

Only ASAN (1):

* _test_multiprocessing.py:76:if support.check_sanitizer(address=True):

ASAN and MSAN (10):

* test___all__.py:14:if support.check_sanitizer(address=True, memory=True):
* test_concurrent_futures.py:35:if support.check_sanitizer(address=True, memory=True):
* test_crypt.py:7:    if check_sanitizer(address=True, memory=True):
* test_decimal.py:5510:    @unittest.skipIf(check_sanitizer(address=True, memory=True),
* test_idle.py:5:if check_sanitizer(address=True, memory=True):
* test_peg_generator/__init__.py:7:if support.check_sanitizer(address=True, memory=True):
* test_tix.py:7:if check_sanitizer(address=True, memory=True):
* test_tk.py:6:if check_sanitizer(address=True, memory=True):
* test_tools/__init__.py:10:if support.check_sanitizer(address=True, memory=True):
* test_ttk_guionly.py:6:if check_sanitizer(address=True, memory=True):

Only UB (1):

* test_hashlib.py:68:SKIP_SHA3 = support.check_sanitizer(ub=True)
msg414870 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2022-03-10 17:10
I enabled the test on ASAN on test_crypt and I confirm that I get a crash on calling a NULL function.

The Python crypt.crypt() function calls the C function crypt_r() which is intercepted by libasan, but the libasan implementation calls a NULL function. I don't know why.

$ ./configure --with-address-sanitizer --with-pydebug
$ make clean
$ ASAN_OPTIONS="detect_leaks=0:allocator_may_return_null=1:handle_segv=0" make
$ ASAN_OPTIONS="detect_leaks=0:allocator_may_return_null=1:handle_segv=0" gdb -args ./python -m test -v test_crypt 
(gdb) run
(...)
0:00:00 load avg: 0.53 Run tests sequentially
0:00:00 load avg: 0.53 [1/1] test_crypt

Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()

(gdb) where
#0  0x0000000000000000 in ?? ()
#1  0x00007ffff761189f in __interceptor_crypt_r.part.0 () from /lib64/libasan.so.6
#2  0x00007fffe6a40821 in crypt_crypt_impl (module=<module at remote 0x6080004ae7c0>, word=0xfcb050 <importlib.bootstrap_external_toplevel_consts_7+48> "", salt=0x6080004bc660 "$6$d8Imx7a5WbE12iK4")
    at /home/vstinner/python/main/Modules/_cryptmodule.c:44
#3  0x00007fffe6a40695 in crypt_crypt (module=<module at remote 0x6080004ae7c0>, args=0x629000001368, nargs=2) at /home/vstinner/python/main/Modules/clinic/_cryptmodule.c.h:58
(...)

$ ASAN_OPTIONS="detect_leaks=0:allocator_may_return_null=1:handle_segv=0" ./python -m test -v test_crypt 
(...)
0:00:00 load avg: 0.56 Run tests sequentially
0:00:00 load avg: 0.56 [1/1] test_crypt
Fatal Python error: Segmentation fault

Current thread 0x00007f367c6c77c0 (most recent call first):
  File "/home/vstinner/python/main/Lib/crypt.py", line 82 in crypt
  File "/home/vstinner/python/main/Lib/crypt.py", line 94 in _add_method
  File "/home/vstinner/python/main/Lib/crypt.py", line 105 in <module>
  File "<frozen importlib._bootstrap>", line 241 in _call_with_frames_removed
  File "<frozen importlib._bootstrap_external>", line 931 in exec_module
  File "<frozen importlib._bootstrap>", line 690 in _load_unlocked
  File "<frozen importlib._bootstrap>", line 1149 in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 1178 in _find_and_load
  File "/home/vstinner/python/main/Lib/test/test_crypt.py", line 6 in <module>
  (...)
msg414872 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2022-03-10 17:29
The crypt_r() interceptor issue was reported in January 2021 to libasan:
https://github.com/google/sanitizers/issues/1365

> I enabled the test on ASAN on test_crypt and I confirm that I get a crash on calling a NULL function.

Note: I built Python with GCC ASAN (-fsanitize=address).
History
Date User Action Args
2022-04-11 14:59:56adminsetgithub: 91069
2022-03-10 17:29:40vstinnersetmessages: + msg414872
2022-03-10 17:10:29vstinnersetmessages: + msg414870
2022-03-10 17:01:28vstinnersetmessages: + msg414867
2022-03-07 19:24:56martin.pantersetnosy: + martin.panter
messages: + msg414694
2022-03-04 09:42:54vstinnersetmessages: + msg414512
2022-03-04 07:49:44christian.heimessetnosy: + christian.heimes
messages: + msg414507
2022-03-04 00:32:04vstinnersetmessages: + msg414501
2022-03-04 00:15:43vstinnersetpull_requests: + pull_request29796
2022-03-04 00:12:16vstinnersetmessages: + msg414499
2022-03-03 23:54:34vstinnersetmessages: + msg414497
2022-03-03 23:47:00vstinnersetpull_requests: + pull_request29795
2022-03-03 23:42:01vstinnersetmessages: + msg414495
2022-03-03 23:41:43vstinnersetmessages: + msg414494
2022-03-03 23:36:53vstinnersetmessages: + msg414491
2022-03-03 23:25:36vstinnersetmessages: + msg414489
2022-03-03 23:20:39vstinnersetpull_requests: + pull_request29794
2022-03-03 23:16:00vstinnersetpull_requests: + pull_request29793
2022-03-03 22:56:03vstinnersetpull_requests: + pull_request29792
2022-03-03 22:45:33vstinnersetmessages: + msg414486
2022-03-03 22:05:14vstinnersetmessages: + msg414477
2022-03-03 20:45:20miss-islingtonsetpull_requests: + pull_request29785
2022-03-03 20:45:13miss-islingtonsetnosy: + miss-islington
pull_requests: + pull_request29784
2022-03-03 20:45:08vstinnersetmessages: + msg414471
2022-03-03 16:59:31vstinnersetkeywords: + patch
stage: patch review
pull_requests: + pull_request29781
2022-03-03 16:22:11vstinnersetmessages: + msg414458
2022-03-03 16:21:12vstinnersetmessages: + msg414457
2022-03-03 16:20:36vstinnersetnosy: + gregory.p.smith
messages: + msg414456
2022-03-03 16:19:36vstinnercreate