summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Fedoseev <fedoseev.sergey@gmail.com>2018-09-12 04:18:01 +0500
committerMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2018-09-11 16:18:01 -0700
commit6c7d67ce83a62b5f0fe5c53a6df602827451bf7f (patch)
tree124db646c91085418871cb49a645c96c700503d9
parent4859ba0d2ce4506fddc3f55f90f8dce031b3804f (diff)
downloadcpython-git-6c7d67ce83a62b5f0fe5c53a6df602827451bf7f.tar.gz
bpo-1621: Avoid signed integer overflow in set_table_resize(). (GH-9059)
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 -->
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2018-09-11-15-19-37.bpo-1621.7o19yG.rst2
-rw-r--r--Objects/setobject.c11
2 files changed, 5 insertions, 8 deletions
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
index 0000000000..4047ff3bfe
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2018-09-11-15-19-37.bpo-1621.7o19yG.rst
@@ -0,0 +1,2 @@
+Do not assume signed integer overflow behavior (C undefined behavior) when
+performing set hash table resizing.
diff --git a/Objects/setobject.c b/Objects/setobject.c
index 82b5838208..e7a528888e 100644
--- a/Objects/setobject.c
+++ b/Objects/setobject.c
@@ -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. */