]> granicus.if.org Git - python/commitdiff
bpo-1621: Avoid signed integer overflow in set_table_resize(). (GH-9059)
authorSergey Fedoseev <fedoseev.sergey@gmail.com>
Tue, 11 Sep 2018 23:18:01 +0000 (04:18 +0500)
committerMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Tue, 11 Sep 2018 23:18:01 +0000 (16:18 -0700)
Address a C undefined behavior signed integer overflow issue in set object table resizing.  Our -fwrapv compiler flag and practical reasons why sets are unlikely to get this large should mean this was never an issue but it was incorrect code that generates code analysis warnings.

<!-- issue-number: [bpo-1621](https://www.bugs.python.org/issue1621) -->
https://bugs.python.org/issue1621
<!-- /issue-number -->

Misc/NEWS.d/next/Core and Builtins/2018-09-11-15-19-37.bpo-1621.7o19yG.rst [new file with mode: 0644]
Objects/setobject.c

diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-09-11-15-19-37.bpo-1621.7o19yG.rst b/Misc/NEWS.d/next/Core and Builtins/2018-09-11-15-19-37.bpo-1621.7o19yG.rst
new file mode 100644 (file)
index 0000000..4047ff3
--- /dev/null
@@ -0,0 +1,2 @@
+Do not assume signed integer overflow behavior (C undefined behavior) when
+performing set hash table resizing.
index 82b58382081625cfb085801098e56048de3f74bc..e7a528888ef0ec0819069e94269d9c32d825a825 100644 (file)
@@ -302,7 +302,6 @@ actually be smaller than the old one.
 static int
 set_table_resize(PySetObject *so, Py_ssize_t minused)
 {
-    Py_ssize_t newsize;
     setentry *oldtable, *newtable, *entry;
     Py_ssize_t oldmask = so->mask;
     size_t newmask;
@@ -313,13 +312,9 @@ set_table_resize(PySetObject *so, Py_ssize_t minused)
 
     /* Find the smallest table size > minused. */
     /* XXX speed-up with intrinsics */
-    for (newsize = PySet_MINSIZE;
-         newsize <= minused && newsize > 0;
-         newsize <<= 1)
-        ;
-    if (newsize <= 0) {
-        PyErr_NoMemory();
-        return -1;
+    size_t newsize = PySet_MINSIZE;
+    while (newsize <= (size_t)minused) {
+        newsize <<= 1; // The largest possible value is PY_SSIZE_T_MAX + 1.
     }
 
     /* Get space for a new table. */