Skip to content

Commit 7b5b429

Browse files
authored
[3.10] bpo-46913: Fix test_ctypes, test_hashlib, test_faulthandler on UBSan (GH-31675)
* bpo-46913: Fix test_faulthandler.test_sigfpe() on UBSAN (GH-31662) Disable undefined behavior sanitizer (UBSAN) on faulthandler_sigfpe(). (cherry picked from commit 4173d67) * bpo-46913: Fix test_faulthandler.test_read_null() on UBSan (GH31672) Disable undefined behavior sanitizer (UBSan) on faulthandler._read_null(). (cherry picked from commit 65b92cc) * bpo-46913: test_hashlib skips _sha3 tests on UBSan (GH-31673) If Python is built with UBSan, test_hashlib skips tests on the _sha3 extension which currently has undefined behaviors. This change allows to run test_hashlib to check for new UBSan regression, but the known _sha3 undefined behavior must be fixed. (cherry picked from commit 6d0d7d2) * bpo-46913: Skip test_ctypes.test_shorts() on UBSan (GH-31674) If Python is built with UBSan, test_ctypes now skips test_shorts(). This change allows to run test_ctypes to check for new UBSan regression, but the known test_shorts() undefined behavior must be fixed. (cherry picked from commit ad1b044)
1 parent 9d9dc59 commit 7b5b429

File tree

4 files changed

+55
-11
lines changed

4 files changed

+55
-11
lines changed

Lib/ctypes/test/test_bitfields.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from ctypes import *
22
from ctypes.test import need_symbol
3+
from test import support
34
import unittest
45
import os
56

@@ -39,6 +40,8 @@ def test_ints(self):
3940
setattr(b, name, i)
4041
self.assertEqual(getattr(b, name), func(byref(b), name.encode('ascii')))
4142

43+
# bpo-46913: _ctypes/cfield.c h_get() has an undefined behavior
44+
@support.skip_if_sanitizer(ub=True)
4245
def test_shorts(self):
4346
b = BITS()
4447
name = "M"

Lib/test/test_hashlib.py

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ def get_fips_mode():
6464

6565
requires_blake2 = unittest.skipUnless(_blake2, 'requires _blake2')
6666

67+
# bpo-46913: Don't test the _sha3 extension on a Python UBSAN build
68+
SKIP_SHA3 = support.check_sanitizer(ub=True)
69+
requires_sha3 = unittest.skipUnless(not SKIP_SHA3, 'requires _sha3')
70+
6771

6872
def hexstr(s):
6973
assert isinstance(s, bytes), repr(s)
@@ -125,6 +129,8 @@ def __init__(self, *args, **kwargs):
125129

126130
self.constructors_to_test = {}
127131
for algorithm in algorithms:
132+
if SKIP_SHA3 and algorithm.startswith('sha3_'):
133+
continue
128134
self.constructors_to_test[algorithm] = set()
129135

130136
# For each algorithm, test the direct constructor and the use
@@ -177,14 +183,15 @@ def add_builtin_constructor(name):
177183
add_builtin_constructor('blake2s')
178184
add_builtin_constructor('blake2b')
179185

180-
_sha3 = self._conditional_import_module('_sha3')
181-
if _sha3:
182-
add_builtin_constructor('sha3_224')
183-
add_builtin_constructor('sha3_256')
184-
add_builtin_constructor('sha3_384')
185-
add_builtin_constructor('sha3_512')
186-
add_builtin_constructor('shake_128')
187-
add_builtin_constructor('shake_256')
186+
if not SKIP_SHA3:
187+
_sha3 = self._conditional_import_module('_sha3')
188+
if _sha3:
189+
add_builtin_constructor('sha3_224')
190+
add_builtin_constructor('sha3_256')
191+
add_builtin_constructor('sha3_384')
192+
add_builtin_constructor('sha3_512')
193+
add_builtin_constructor('shake_128')
194+
add_builtin_constructor('shake_256')
188195

189196
super(HashLibTestCase, self).__init__(*args, **kwargs)
190197

@@ -383,6 +390,7 @@ def test_no_unicode_blake2(self):
383390
self.check_no_unicode('blake2b')
384391
self.check_no_unicode('blake2s')
385392

393+
@requires_sha3
386394
def test_no_unicode_sha3(self):
387395
self.check_no_unicode('sha3_224')
388396
self.check_no_unicode('sha3_256')
@@ -418,6 +426,7 @@ def test_blocksize_name(self):
418426
self.check_blocksize_name('sha384', 128, 48)
419427
self.check_blocksize_name('sha512', 128, 64)
420428

429+
@requires_sha3
421430
def test_blocksize_name_sha3(self):
422431
self.check_blocksize_name('sha3_224', 144, 28)
423432
self.check_blocksize_name('sha3_256', 136, 32)
@@ -438,6 +447,7 @@ def check_sha3(self, name, capacity, rate, suffix):
438447
self.assertEqual(m._rate_bits, rate)
439448
self.assertEqual(m._suffix, suffix)
440449

450+
@requires_sha3
441451
def test_extra_sha3(self):
442452
self.check_sha3('sha3_224', 448, 1152, b'\x06')
443453
self.check_sha3('sha3_256', 512, 1088, b'\x06')
@@ -777,36 +787,44 @@ def test_blake2s_vectors(self):
777787
key = bytes.fromhex(key)
778788
self.check('blake2s', msg, md, key=key)
779789

790+
@requires_sha3
780791
def test_case_sha3_224_0(self):
781792
self.check('sha3_224', b"",
782793
"6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7")
783794

795+
@requires_sha3
784796
def test_case_sha3_224_vector(self):
785797
for msg, md in read_vectors('sha3_224'):
786798
self.check('sha3_224', msg, md)
787799

800+
@requires_sha3
788801
def test_case_sha3_256_0(self):
789802
self.check('sha3_256', b"",
790803
"a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a")
791804

805+
@requires_sha3
792806
def test_case_sha3_256_vector(self):
793807
for msg, md in read_vectors('sha3_256'):
794808
self.check('sha3_256', msg, md)
795809

810+
@requires_sha3
796811
def test_case_sha3_384_0(self):
797812
self.check('sha3_384', b"",
798813
"0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2a"+
799814
"c3713831264adb47fb6bd1e058d5f004")
800815

816+
@requires_sha3
801817
def test_case_sha3_384_vector(self):
802818
for msg, md in read_vectors('sha3_384'):
803819
self.check('sha3_384', msg, md)
804820

821+
@requires_sha3
805822
def test_case_sha3_512_0(self):
806823
self.check('sha3_512', b"",
807824
"a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a6"+
808825
"15b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26")
809826

827+
@requires_sha3
810828
def test_case_sha3_512_vector(self):
811829
for msg, md in read_vectors('sha3_512'):
812830
self.check('sha3_512', msg, md)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix test_faulthandler.test_sigfpe() if Python is built with undefined
2+
behavior sanitizer (UBSAN): disable UBSAN on the faulthandler_sigfpe()
3+
function. Patch by Victor Stinner.

Modules/faulthandler.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,23 @@
2929

3030
#define PUTS(fd, str) _Py_write_noraise(fd, str, strlen(str))
3131

32+
33+
// clang uses __attribute__((no_sanitize("undefined")))
34+
// GCC 4.9+ uses __attribute__((no_sanitize_undefined))
35+
#if defined(__has_feature) // Clang
36+
# if __has_feature(undefined_behavior_sanitizer)
37+
# define _Py_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize("undefined")))
38+
# endif
39+
#endif
40+
#if defined(__GNUC__) \
41+
&& ((__GNUC__ >= 5) || (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9))
42+
# define _Py_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize_undefined))
43+
#endif
44+
#ifndef _Py_NO_SANITIZE_UNDEFINED
45+
# define _Py_NO_SANITIZE_UNDEFINED
46+
#endif
47+
48+
3249
_Py_IDENTIFIER(enable);
3350
_Py_IDENTIFIER(fileno);
3451
_Py_IDENTIFIER(flush);
@@ -1014,7 +1031,7 @@ faulthandler_suppress_crash_report(void)
10141031
#endif
10151032
}
10161033

1017-
static PyObject *
1034+
static PyObject* _Py_NO_SANITIZE_UNDEFINED
10181035
faulthandler_read_null(PyObject *self, PyObject *args)
10191036
{
10201037
volatile int *x;
@@ -1103,17 +1120,20 @@ faulthandler_fatal_error_c_thread(PyObject *self, PyObject *args)
11031120
Py_RETURN_NONE;
11041121
}
11051122

1106-
static PyObject *
1123+
static PyObject* _Py_NO_SANITIZE_UNDEFINED
11071124
faulthandler_sigfpe(PyObject *self, PyObject *args)
11081125
{
1126+
faulthandler_suppress_crash_report();
1127+
11091128
/* Do an integer division by zero: raise a SIGFPE on Intel CPU, but not on
11101129
PowerPC. Use volatile to disable compile-time optimizations. */
11111130
volatile int x = 1, y = 0, z;
1112-
faulthandler_suppress_crash_report();
11131131
z = x / y;
1132+
11141133
/* If the division by zero didn't raise a SIGFPE (e.g. on PowerPC),
11151134
raise it manually. */
11161135
raise(SIGFPE);
1136+
11171137
/* This line is never reached, but we pretend to make something with z
11181138
to silence a compiler warning. */
11191139
return PyLong_FromLong(z);

0 commit comments

Comments
 (0)