From 6665802549006eb50c1a68c3489ee3aaf81d0c8e Mon Sep 17 00:00:00 2001 From: "Miss Islington (bot)" <31488909+miss-islington@users.noreply.github.com> Date: Fri, 19 Oct 2018 15:50:34 -0700 Subject: [PATCH] bpo-1621: Avoid signed integer overflow in set_table_resize() (GH-9059) (GH-9198) 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. Co-authored-by: Sergey Fedoseev --- .../2018-09-11-15-19-37.bpo-1621.7o19yG.rst | 2 ++ Objects/setobject.c | 11 +++-------- 2 files changed, 5 insertions(+), 8 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2018-09-11-15-19-37.bpo-1621.7o19yG.rst 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 00000000000..4047ff3bfe8 --- /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 ce35aa2a0cd..357e48ca3ce 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. */