Issue #16096: Fix several occurrences of potential signed integer ove… · pythoncapi/cpython@c04ddff · GitHub
Skip to content

Commit c04ddff

Browse files
committed
Issue python#16096: Fix several occurrences of potential signed integer overflow. Thanks Serhiy Storchaka.
1 parent a202873 commit c04ddff

7 files changed

Lines changed: 30 additions & 35 deletions

File tree

Modules/_codecsmodule.c

Lines changed: 2 additions & 2 deletions

Modules/_datetimemodule.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,14 +1265,13 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
12651265
assert(ptoappend != NULL);
12661266
assert(ntoappend > 0);
12671267
while (usednew + ntoappend > totalnew) {
1268-
size_t bigger = totalnew << 1;
1269-
if ((bigger >> 1) != totalnew) { /* overflow */
1268+
if (totalnew > (PY_SSIZE_T_MAX >> 1)) { /* overflow */
12701269
PyErr_NoMemory();
12711270
goto Done;
12721271
}
1273-
if (_PyBytes_Resize(&newfmt, bigger) < 0)
1272+
totalnew <<= 1;
1273+
if (_PyBytes_Resize(&newfmt, totalnew) < 0)
12741274
goto Done;
1275-
totalnew = bigger;
12761275
pnew = PyBytes_AsString(newfmt) + usednew;
12771276
}
12781277
memcpy(pnew, ptoappend, ntoappend);

Modules/_randommodule.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,8 @@ random_seed(RandomObject *self, PyObject *args)
284284
n = newn;
285285
if (keyused >= keymax) {
286286
unsigned long bigger = keymax << 1;
287-
if ((bigger >> 1) != keymax) {
287+
if ((bigger >> 1) != keymax ||
288+
bigger > PY_SSIZE_T_MAX / sizeof(*key)) {
288289
PyErr_NoMemory();
289290
goto Done;
290291
}

Modules/arraymodule.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -483,11 +483,11 @@ newarrayobject(PyTypeObject *type, Py_ssize_t size, struct arraydescr *descr)
483483
return NULL;
484484
}
485485

486-
nbytes = size * descr->itemsize;
487486
/* Check for overflow */
488-
if (nbytes / descr->itemsize != (size_t)size) {
487+
if (size > PY_SSIZE_T_MAX / descr->itemsize) {
489488
return PyErr_NoMemory();
490489
}
490+
nbytes = size * descr->itemsize;
491491
op = (arrayobject *) type->tp_alloc(type, 0);
492492
if (op == NULL) {
493493
return NULL;
@@ -1251,11 +1251,15 @@ array_fromfile(arrayobject *self, PyObject *args)
12511251
if (!PyArg_ParseTuple(args, "On:fromfile", &f, &n))
12521252
return NULL;
12531253

1254-
nbytes = n * itemsize;
1255-
if (nbytes < 0 || nbytes/itemsize != n) {
1254+
if (n < 0) {
1255+
PyErr_SetString(PyExc_ValueError, "negative count");
1256+
return NULL;
1257+
}
1258+
if (n > PY_SSIZE_T_MAX / itemsize) {
12561259
PyErr_NoMemory();
12571260
return NULL;
12581261
}
1262+
nbytes = n * itemsize;
12591263

12601264
b = _PyObject_CallMethodId(f, &PyId_read, "n", nbytes);
12611265
if (b == NULL)

Modules/audioop.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,15 +1108,15 @@ audioop_ratecv(PyObject *self, PyObject *args)
11081108
PyErr_SetString(AudioopError, "# of channels should be >= 1");
11091109
return NULL;
11101110
}
1111-
bytes_per_frame = size * nchannels;
1112-
if (bytes_per_frame / nchannels != size) {
1111+
if (size > INT_MAX / nchannels) {
11131112
/* This overflow test is rigorously correct because
11141113
both multiplicands are >= 1. Use the argument names
11151114
from the docs for the error msg. */
11161115
PyErr_SetString(PyExc_OverflowError,
11171116
"width * nchannels too big for a C int");
11181117
return NULL;
11191118
}
1119+
bytes_per_frame = size * nchannels;
11201120
if (weightA < 1 || weightB < 0) {
11211121
PyErr_SetString(AudioopError,
11221122
"weightA should be >= 1, weightB should be >= 0");

Objects/tupleobject.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -96,15 +96,11 @@ PyTuple_New(register Py_ssize_t size)
9696
else
9797
#endif
9898
{
99-
Py_ssize_t nbytes = size * sizeof(PyObject *);
10099
/* Check for overflow */
101-
if (nbytes / sizeof(PyObject *) != (size_t)size ||
102-
(nbytes > PY_SSIZE_T_MAX - sizeof(PyTupleObject) - sizeof(PyObject *)))
103-
{
100+
if (size > (PY_SSIZE_T_MAX - sizeof(PyTupleObject) -
101+
sizeof(PyObject *)) / sizeof(PyObject *)) {
104102
return PyErr_NoMemory();
105103
}
106-
/* nbytes += sizeof(PyTupleObject) - sizeof(PyObject *); */
107-
108104
op = PyObject_GC_NewVar(PyTupleObject, &PyTuple_Type, size);
109105
if (op == NULL)
110106
return NULL;
@@ -481,9 +477,9 @@ tuplerepeat(PyTupleObject *a, Py_ssize_t n)
481477
if (Py_SIZE(a) == 0)
482478
return PyTuple_New(0);
483479
}
484-
size = Py_SIZE(a) * n;
485-
if (size/Py_SIZE(a) != n)
480+
if (n > PY_SSIZE_T_MAX / Py_SIZE(a))
486481
return PyErr_NoMemory();
482+
size = Py_SIZE(a) * n;
487483
np = (PyTupleObject *) PyTuple_New(size);
488484
if (np == NULL)
489485
return NULL;

Objects/unicodeobject.c

Lines changed: 9 additions & 14 deletions

0 commit comments

Comments
 (0)