Skip to content

Commit 6a14330

Browse files
authored
bpo-46913: Fix test_ctypes, test_hashlib, test_faulthandler on UBSan (GH-31675) (GH-31676)
* 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) (cherry picked from commit 7b5b429)
1 parent 0981986 commit 6a14330

File tree

4 files changed

+43
-12
lines changed

4 files changed

+43
-12
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: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@ def get_fips_mode():
6666
except ImportError:
6767
_sha3 = None
6868

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

7173

7274
def hexstr(s):
@@ -129,6 +131,8 @@ def __init__(self, *args, **kwargs):
129131

130132
self.constructors_to_test = {}
131133
for algorithm in algorithms:
134+
if SKIP_SHA3 and algorithm.startswith('sha3_'):
135+
continue
132136
self.constructors_to_test[algorithm] = set()
133137

134138
# For each algorithm, test the direct constructor and the use
@@ -181,14 +185,15 @@ def add_builtin_constructor(name):
181185
add_builtin_constructor('blake2s')
182186
add_builtin_constructor('blake2b')
183187

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

193198
super(HashLibTestCase, self).__init__(*args, **kwargs)
194199

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
@@ -27,6 +27,23 @@
2727

2828
#define PUTS(fd, str) _Py_write_noraise(fd, str, strlen(str))
2929

30+
31+
// clang uses __attribute__((no_sanitize("undefined")))
32+
// GCC 4.9+ uses __attribute__((no_sanitize_undefined))
33+
#if defined(__has_feature) // Clang
34+
# if __has_feature(undefined_behavior_sanitizer)
35+
# define _Py_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize("undefined")))
36+
# endif
37+
#endif
38+
#if defined(__GNUC__) \
39+
&& ((__GNUC__ >= 5) || (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9))
40+
# define _Py_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize_undefined))
41+
#endif
42+
#ifndef _Py_NO_SANITIZE_UNDEFINED
43+
# define _Py_NO_SANITIZE_UNDEFINED
44+
#endif
45+
46+
3047
_Py_IDENTIFIER(enable);
3148
_Py_IDENTIFIER(fileno);
3249
_Py_IDENTIFIER(flush);
@@ -1010,7 +1027,7 @@ faulthandler_suppress_crash_report(void)
10101027
#endif
10111028
}
10121029

1013-
static PyObject *
1030+
static PyObject* _Py_NO_SANITIZE_UNDEFINED
10141031
faulthandler_read_null(PyObject *self, PyObject *args)
10151032
{
10161033
volatile int *x;
@@ -1099,17 +1116,20 @@ faulthandler_fatal_error_c_thread(PyObject *self, PyObject *args)
10991116
Py_RETURN_NONE;
11001117
}
11011118

1102-
static PyObject *
1119+
static PyObject* _Py_NO_SANITIZE_UNDEFINED
11031120
faulthandler_sigfpe(PyObject *self, PyObject *args)
11041121
{
1122+
faulthandler_suppress_crash_report();
1123+
11051124
/* Do an integer division by zero: raise a SIGFPE on Intel CPU, but not on
11061125
PowerPC. Use volatile to disable compile-time optimizations. */
11071126
volatile int x = 1, y = 0, z;
1108-
faulthandler_suppress_crash_report();
11091127
z = x / y;
1128+
11101129
/* If the division by zero didn't raise a SIGFPE (e.g. on PowerPC),
11111130
raise it manually. */
11121131
raise(SIGFPE);
1132+
11131133
/* This line is never reached, but we pretend to make something with z
11141134
to silence a compiler warning. */
11151135
return PyLong_FromLong(z);

0 commit comments

Comments
 (0)