mirror of
https://github.com/python/cpython.git
synced 2025-08-19 00:00:48 +00:00
Merged revisions 81904 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r81904 | mark.dickinson | 2010-06-11 21:27:05 +0100 (Fri, 11 Jun 2010) | 4 lines Fix possible undefined behaviour from signed overflow in struct module. Backport of revisions 81897, 81898 and 81902 from py3k. ........
This commit is contained in:
parent
4f6ebc2db8
commit
38b4a898fd
2 changed files with 34 additions and 23 deletions
|
@ -12,7 +12,6 @@ from test.test_support import TestFailed, verbose, run_unittest
|
||||||
import sys
|
import sys
|
||||||
ISBIGENDIAN = sys.byteorder == "big"
|
ISBIGENDIAN = sys.byteorder == "big"
|
||||||
IS32BIT = sys.maxsize == 0x7fffffff
|
IS32BIT = sys.maxsize == 0x7fffffff
|
||||||
del sys
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import _struct
|
import _struct
|
||||||
|
@ -605,7 +604,12 @@ class StructTest(unittest.TestCase):
|
||||||
def test_crasher(self):
|
def test_crasher(self):
|
||||||
self.assertRaises(MemoryError, struct.pack, "357913941c", "a")
|
self.assertRaises(MemoryError, struct.pack, "357913941c", "a")
|
||||||
|
|
||||||
|
def test_count_overflow(self):
|
||||||
|
hugecount = '{0}b'.format(sys.maxsize+1)
|
||||||
|
self.assertRaises(struct.error, struct.calcsize, hugecount)
|
||||||
|
|
||||||
|
hugecount2 = '{0}b{1}H'.format(sys.maxsize//2, sys.maxsize//2)
|
||||||
|
self.assertRaises(struct.error, struct.calcsize, hugecount2)
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
run_unittest(StructTest)
|
run_unittest(StructTest)
|
||||||
|
|
|
@ -1309,16 +1309,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 int
|
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;
|
||||||
|
@ -1337,7 +1340,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 = PyString_AS_STRING(self->s_format);
|
fmt = PyString_AS_STRING(self->s_format);
|
||||||
|
|
||||||
|
@ -1352,14 +1355,13 @@ prepare_s(PyStructObject *self)
|
||||||
if ('0' <= c && c <= '9') {
|
if ('0' <= c && c <= '9') {
|
||||||
num = c - '0';
|
num = c - '0';
|
||||||
while ('0' <= (c = *s++) && c <= '9') {
|
while ('0' <= (c = *s++) && c <= '9') {
|
||||||
x = num*10 + (c - '0');
|
/* overflow-safe version of
|
||||||
if (x/10 != num) {
|
if (num*10 + (c - '0') > PY_SSIZE_T_MAX) { ... } */
|
||||||
PyErr_SetString(
|
if (num >= PY_SSIZE_T_MAX / 10 && (
|
||||||
StructError,
|
num > PY_SSIZE_T_MAX / 10 ||
|
||||||
"overflow in item count");
|
(c - '0') > PY_SSIZE_T_MAX % 10))
|
||||||
return -1;
|
goto overflow;
|
||||||
}
|
num = num*10 + (c - '0');
|
||||||
num = x;
|
|
||||||
}
|
}
|
||||||
if (c == '\0')
|
if (c == '\0')
|
||||||
break;
|
break;
|
||||||
|
@ -1380,13 +1382,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 */
|
||||||
|
@ -1445,6 +1447,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…
Add table
Add a link
Reference in a new issue