mirror of https://github.com/python/cpython.git
Fix more undefined-behaviour inducing overflow checks in struct module.
This commit is contained in:
parent
2e5416d0e6
commit
b72e6860d8
|
@ -510,6 +510,8 @@ def test_count_overflow(self):
|
||||||
hugecount = '{}b'.format(sys.maxsize+1)
|
hugecount = '{}b'.format(sys.maxsize+1)
|
||||||
self.assertRaises(struct.error, struct.calcsize, hugecount)
|
self.assertRaises(struct.error, struct.calcsize, hugecount)
|
||||||
|
|
||||||
|
hugecount2 = '{}b{}H'.format(sys.maxsize//2, sys.maxsize//2)
|
||||||
|
self.assertRaises(struct.error, struct.calcsize, hugecount2)
|
||||||
|
|
||||||
if IS32BIT:
|
if IS32BIT:
|
||||||
def test_crasher(self):
|
def test_crasher(self):
|
||||||
|
|
|
@ -1143,16 +1143,19 @@ getentry(int c, const formatdef *f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Align a size according to a format code */
|
/* Align a size according to a format code. Return -1 on overflow. */
|
||||||
|
|
||||||
static Py_ssize_t
|
static Py_ssize_t
|
||||||
align(Py_ssize_t size, char c, const formatdef *e)
|
align(Py_ssize_t size, char c, const formatdef *e)
|
||||||
{
|
{
|
||||||
|
Py_ssize_t extra;
|
||||||
|
|
||||||
if (e->format == c) {
|
if (e->format == c) {
|
||||||
if (e->alignment) {
|
if (e->alignment && size > 0) {
|
||||||
size = ((size + e->alignment - 1)
|
extra = (e->alignment - 1) - (size - 1) % (e->alignment);
|
||||||
/ e->alignment)
|
if (extra > PY_SSIZE_T_MAX - size)
|
||||||
* e->alignment;
|
return -1;
|
||||||
|
size += extra;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
|
@ -1171,7 +1174,7 @@ prepare_s(PyStructObject *self)
|
||||||
const char *s;
|
const char *s;
|
||||||
const char *fmt;
|
const char *fmt;
|
||||||
char c;
|
char c;
|
||||||
Py_ssize_t size, len, num, itemsize, x;
|
Py_ssize_t size, len, num, itemsize;
|
||||||
|
|
||||||
fmt = PyBytes_AS_STRING(self->s_format);
|
fmt = PyBytes_AS_STRING(self->s_format);
|
||||||
|
|
||||||
|
@ -1190,12 +1193,8 @@ prepare_s(PyStructObject *self)
|
||||||
if (num*10 + (c - '0') > PY_SSIZE_T_MAX) { ... } */
|
if (num*10 + (c - '0') > PY_SSIZE_T_MAX) { ... } */
|
||||||
if (num >= PY_SSIZE_T_MAX / 10 && (
|
if (num >= PY_SSIZE_T_MAX / 10 && (
|
||||||
num > PY_SSIZE_T_MAX / 10 ||
|
num > PY_SSIZE_T_MAX / 10 ||
|
||||||
(c - '0') > PY_SSIZE_T_MAX % 10)) {
|
(c - '0') > PY_SSIZE_T_MAX % 10))
|
||||||
PyErr_SetString(
|
goto overflow;
|
||||||
StructError,
|
|
||||||
"overflow in item count");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
num = num*10 + (c - '0');
|
num = num*10 + (c - '0');
|
||||||
}
|
}
|
||||||
if (c == '\0') {
|
if (c == '\0') {
|
||||||
|
@ -1220,13 +1219,13 @@ prepare_s(PyStructObject *self)
|
||||||
|
|
||||||
itemsize = e->size;
|
itemsize = e->size;
|
||||||
size = align(size, c, e);
|
size = align(size, c, e);
|
||||||
x = num * itemsize;
|
if (size == -1)
|
||||||
size += x;
|
goto overflow;
|
||||||
if (x/itemsize != num || size < 0) {
|
|
||||||
PyErr_SetString(StructError,
|
/* if (size + num * itemsize > PY_SSIZE_T_MAX) { ... } */
|
||||||
"total struct size too long");
|
if (num > (PY_SSIZE_T_MAX - size) / itemsize)
|
||||||
return -1;
|
goto overflow;
|
||||||
}
|
size += num * itemsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check for overflow */
|
/* check for overflow */
|
||||||
|
@ -1285,6 +1284,11 @@ prepare_s(PyStructObject *self)
|
||||||
codes->size = 0;
|
codes->size = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
overflow:
|
||||||
|
PyErr_SetString(StructError,
|
||||||
|
"total struct size too long");
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
|
Loading…
Reference in New Issue