[Python-checkins] bpo-46913: Fix test_ctypes, test_hashlib, test_faulthandler on UBSan (GH-31675) (GH-31676)

vstinner webhook-mailer at python.org
Thu Mar 3 19:32:05 EST 2022


https://github.com/python/cpython/commit/6a14330318c9c7aedf3e9841c3dfea337064d8e6
commit: 6a14330318c9c7aedf3e9841c3dfea337064d8e6
branch: 3.9
author: Victor Stinner <vstinner at python.org>
committer: vstinner <vstinner at python.org>
date: 2022-03-04T01:31:54+01:00
summary:

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 4173d677a1d7c72bb32d292fbff1b4cf073d615c)

* bpo-46913: Fix test_faulthandler.test_read_null() on UBSan (GH31672)

Disable undefined behavior sanitizer (UBSan) on
faulthandler._read_null().

(cherry picked from commit 65b92ccdec2ee4a99e54aaf7ae2d9bbc2ebfe549)

* 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 6d0d7d2b8c1e04fd51c6cb29cc09a41b60b97b7b)

* 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 ad1b04451d3aca2c6fa6dbe2891676a4e0baac49)
(cherry picked from commit 7b5b429adab4fe0fe81858fe3831f06adc2e2141)

files:
A Misc/NEWS.d/next/Tests/2022-03-03-17-36-24.bpo-46913.vxETIE.rst
M Lib/ctypes/test/test_bitfields.py
M Lib/test/test_hashlib.py
M Modules/faulthandler.c

diff --git a/Lib/ctypes/test/test_bitfields.py b/Lib/ctypes/test/test_bitfields.py
index 992b8c4da3a77..66acd62e6851a 100644
--- a/Lib/ctypes/test/test_bitfields.py
+++ b/Lib/ctypes/test/test_bitfields.py
@@ -1,5 +1,6 @@
 from ctypes import *
 from ctypes.test import need_symbol
+from test import support
 import unittest
 import os
 
@@ -39,6 +40,8 @@ def test_ints(self):
                 setattr(b, name, i)
                 self.assertEqual(getattr(b, name), func(byref(b), name.encode('ascii')))
 
+    # bpo-46913: _ctypes/cfield.c h_get() has an undefined behavior
+    @support.skip_if_sanitizer(ub=True)
     def test_shorts(self):
         b = BITS()
         name = "M"
diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py
index 969e5e42e44c7..214bc3cb2b187 100644
--- a/Lib/test/test_hashlib.py
+++ b/Lib/test/test_hashlib.py
@@ -66,7 +66,9 @@ def get_fips_mode():
 except ImportError:
     _sha3 = None
 
-requires_sha3 = unittest.skipUnless(_sha3, 'requires _sha3')
+# bpo-46913: Don't test the _sha3 extension on a Python UBSAN build
+SKIP_SHA3 = support.check_sanitizer(ub=True)
+requires_sha3 = unittest.skipUnless(not SKIP_SHA3 and _sha3, 'requires _sha3')
 
 
 def hexstr(s):
@@ -129,6 +131,8 @@ def __init__(self, *args, **kwargs):
 
         self.constructors_to_test = {}
         for algorithm in algorithms:
+            if SKIP_SHA3 and algorithm.startswith('sha3_'):
+                continue
             self.constructors_to_test[algorithm] = set()
 
         # For each algorithm, test the direct constructor and the use
@@ -181,14 +185,15 @@ def add_builtin_constructor(name):
             add_builtin_constructor('blake2s')
             add_builtin_constructor('blake2b')
 
-        _sha3 = self._conditional_import_module('_sha3')
-        if _sha3:
-            add_builtin_constructor('sha3_224')
-            add_builtin_constructor('sha3_256')
-            add_builtin_constructor('sha3_384')
-            add_builtin_constructor('sha3_512')
-            add_builtin_constructor('shake_128')
-            add_builtin_constructor('shake_256')
+        if not SKIP_SHA3:
+            _sha3 = self._conditional_import_module('_sha3')
+            if _sha3:
+                add_builtin_constructor('sha3_224')
+                add_builtin_constructor('sha3_256')
+                add_builtin_constructor('sha3_384')
+                add_builtin_constructor('sha3_512')
+                add_builtin_constructor('shake_128')
+                add_builtin_constructor('shake_256')
 
         super(HashLibTestCase, self).__init__(*args, **kwargs)
 
diff --git a/Misc/NEWS.d/next/Tests/2022-03-03-17-36-24.bpo-46913.vxETIE.rst b/Misc/NEWS.d/next/Tests/2022-03-03-17-36-24.bpo-46913.vxETIE.rst
new file mode 100644
index 0000000000000..65fed1c249d87
--- /dev/null
+++ b/Misc/NEWS.d/next/Tests/2022-03-03-17-36-24.bpo-46913.vxETIE.rst
@@ -0,0 +1,3 @@
+Fix test_faulthandler.test_sigfpe() if Python is built with undefined
+behavior sanitizer (UBSAN): disable UBSAN on the faulthandler_sigfpe()
+function. Patch by Victor Stinner.
diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c
index e7a285033051d..9855a3e0065ca 100644
--- a/Modules/faulthandler.c
+++ b/Modules/faulthandler.c
@@ -27,6 +27,23 @@
 
 #define PUTS(fd, str) _Py_write_noraise(fd, str, strlen(str))
 
+
+// clang uses __attribute__((no_sanitize("undefined")))
+// GCC 4.9+ uses __attribute__((no_sanitize_undefined))
+#if defined(__has_feature)  // Clang
+#  if __has_feature(undefined_behavior_sanitizer)
+#    define _Py_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize("undefined")))
+#  endif
+#endif
+#if defined(__GNUC__) \
+    && ((__GNUC__ >= 5) || (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9))
+#  define _Py_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize_undefined))
+#endif
+#ifndef _Py_NO_SANITIZE_UNDEFINED
+#  define _Py_NO_SANITIZE_UNDEFINED
+#endif
+
+
 _Py_IDENTIFIER(enable);
 _Py_IDENTIFIER(fileno);
 _Py_IDENTIFIER(flush);
@@ -1010,7 +1027,7 @@ faulthandler_suppress_crash_report(void)
 #endif
 }
 
-static PyObject *
+static PyObject* _Py_NO_SANITIZE_UNDEFINED
 faulthandler_read_null(PyObject *self, PyObject *args)
 {
     volatile int *x;
@@ -1099,17 +1116,20 @@ faulthandler_fatal_error_c_thread(PyObject *self, PyObject *args)
     Py_RETURN_NONE;
 }
 
-static PyObject *
+static PyObject* _Py_NO_SANITIZE_UNDEFINED
 faulthandler_sigfpe(PyObject *self, PyObject *args)
 {
+    faulthandler_suppress_crash_report();
+
     /* Do an integer division by zero: raise a SIGFPE on Intel CPU, but not on
        PowerPC. Use volatile to disable compile-time optimizations. */
     volatile int x = 1, y = 0, z;
-    faulthandler_suppress_crash_report();
     z = x / y;
+
     /* If the division by zero didn't raise a SIGFPE (e.g. on PowerPC),
        raise it manually. */
     raise(SIGFPE);
+
     /* This line is never reached, but we pretend to make something with z
        to silence a compiler warning. */
     return PyLong_FromLong(z);



More information about the Python-checkins mailing list