Commit 4f3be8a0 authored by Neal Norwitz's avatar Neal Norwitz

Security patches from Apple: prevent int overflow when allocating memory

parent 83ac0144
...@@ -307,6 +307,8 @@ class CommonTest(unittest.TestCase): ...@@ -307,6 +307,8 @@ class CommonTest(unittest.TestCase):
self.assertEqual(id(s), id(s*1)) self.assertEqual(id(s), id(s*1))
def test_bigrepeat(self): def test_bigrepeat(self):
import sys
if sys.maxint <= 2147483647:
x = self.type2test([0]) x = self.type2test([0])
x *= 2**16 x *= 2**16
self.assertRaises(MemoryError, x.__mul__, 2**16) self.assertRaises(MemoryError, x.__mul__, 2**16)
......
from test import test_support from test import test_support
from test.test_support import bigmemtest, _1G, _2G from test.test_support import bigmemtest, _1G, _2G, _4G, precisionbigmemtest
import unittest import unittest
import operator import operator
...@@ -54,6 +54,22 @@ class StrTest(unittest.TestCase): ...@@ -54,6 +54,22 @@ class StrTest(unittest.TestCase):
self.assertEquals(s[lpadsize:-rpadsize], SUBSTR) self.assertEquals(s[lpadsize:-rpadsize], SUBSTR)
self.assertEquals(s.strip(), SUBSTR.strip()) self.assertEquals(s.strip(), SUBSTR.strip())
@precisionbigmemtest(size=_2G - 1, memuse=1)
def test_center_unicode(self, size):
SUBSTR = u' abc def ghi'
try:
s = SUBSTR.center(size)
except OverflowError:
pass # acceptable on 32-bit
else:
self.assertEquals(len(s), size)
lpadsize = rpadsize = (len(s) - len(SUBSTR)) // 2
if len(s) % 2:
lpadsize += 1
self.assertEquals(s[lpadsize:-rpadsize], SUBSTR)
self.assertEquals(s.strip(), SUBSTR.strip())
del s
@bigmemtest(minsize=_2G, memuse=2) @bigmemtest(minsize=_2G, memuse=2)
def test_count(self, size): def test_count(self, size):
SUBSTR = ' abc def ghi' SUBSTR = ' abc def ghi'
...@@ -70,10 +86,44 @@ class StrTest(unittest.TestCase): ...@@ -70,10 +86,44 @@ class StrTest(unittest.TestCase):
s = '.' * size s = '.' * size
self.assertEquals(len(s.decode('utf-8')), size) self.assertEquals(len(s.decode('utf-8')), size)
def basic_encode_test(self, size, enc, c=u'.', expectedsize=None):
if expectedsize is None:
expectedsize = size
s = c * size
self.assertEquals(len(s.encode(enc)), expectedsize)
@bigmemtest(minsize=_2G + 2, memuse=3) @bigmemtest(minsize=_2G + 2, memuse=3)
def test_encode(self, size): def test_encode(self, size):
s = u'.' * size return self.basic_encode_test(size, 'utf-8')
self.assertEquals(len(s.encode('utf-8')), size)
@precisionbigmemtest(size=_4G / 6 + 2, memuse=2)
def test_encode_raw_unicode_escape(self, size):
try:
return self.basic_encode_test(size, 'raw_unicode_escape')
except MemoryError:
pass # acceptable on 32-bit
@precisionbigmemtest(size=_4G / 5 + 70, memuse=3)
def test_encode_utf7(self, size):
try:
return self.basic_encode_test(size, 'utf7')
except MemoryError:
pass # acceptable on 32-bit
@precisionbigmemtest(size=_2G-1, memuse=2)
def test_decodeascii(self, size):
return self.basic_encode_test(size, 'ascii', c='A')
@precisionbigmemtest(size=_4G / 5, memuse=6+2)
def test_unicode_repr_oflw(self, size):
try:
s = u"\uAAAA"*size
r = repr(s)
except MemoryError:
pass # acceptable on 32-bit
else:
self.failUnless(s == eval(r))
@bigmemtest(minsize=_2G, memuse=2) @bigmemtest(minsize=_2G, memuse=2)
def test_endswith(self, size): def test_endswith(self, size):
...@@ -459,6 +509,11 @@ class StrTest(unittest.TestCase): ...@@ -459,6 +509,11 @@ class StrTest(unittest.TestCase):
self.assertEquals(s.count('\\'), size) self.assertEquals(s.count('\\'), size)
self.assertEquals(s.count('0'), size * 2) self.assertEquals(s.count('0'), size * 2)
@bigmemtest(minsize=2**32 / 5, memuse=6+2)
def test_unicode_repr(self, size):
s = u"\uAAAA" * size
self.failUnless(len(repr(s)) > size)
# This test is meaningful even with size < 2G, as long as the # This test is meaningful even with size < 2G, as long as the
# doubled string is > 2G (but it tests more if both are > 2G :) # doubled string is > 2G (but it tests more if both are > 2G :)
@bigmemtest(minsize=_1G + 2, memuse=3) @bigmemtest(minsize=_1G + 2, memuse=3)
...@@ -642,6 +697,35 @@ class TupleTest(unittest.TestCase): ...@@ -642,6 +697,35 @@ class TupleTest(unittest.TestCase):
def test_repeat_large(self, size): def test_repeat_large(self, size):
return self.basic_test_repeat(size) return self.basic_test_repeat(size)
@bigmemtest(minsize=_1G - 1, memuse=12)
def test_repeat_large_2(self, size):
return self.basic_test_repeat(size)
@precisionbigmemtest(size=_1G - 1, memuse=9)
def test_from_2G_generator(self, size):
try:
t = tuple(xrange(size))
except MemoryError:
pass # acceptable on 32-bit
else:
count = 0
for item in t:
self.assertEquals(item, count)
count += 1
self.assertEquals(count, size)
@precisionbigmemtest(size=_1G - 25, memuse=9)
def test_from_almost_2G_generator(self, size):
try:
t = tuple(xrange(size))
count = 0
for item in t:
self.assertEquals(item, count)
count += 1
self.assertEquals(count, size)
except MemoryError:
pass # acceptable, expected on 32-bit
# Like test_concat, split in two. # Like test_concat, split in two.
def basic_test_repr(self, size): def basic_test_repr(self, size):
t = (0,) * size t = (0,) * size
...@@ -957,8 +1041,23 @@ class ListTest(unittest.TestCase): ...@@ -957,8 +1041,23 @@ class ListTest(unittest.TestCase):
self.assertEquals(l[:10], [1] * 10) self.assertEquals(l[:10], [1] * 10)
self.assertEquals(l[-10:], [5] * 10) self.assertEquals(l[-10:], [5] * 10)
class BufferTest(unittest.TestCase):
@precisionbigmemtest(size=_1G, memuse=4)
def test_repeat(self, size):
try:
b = buffer("AAAA")*size
except MemoryError:
pass # acceptable on 32-bit
else:
count = 0
for c in b:
self.assertEquals(c, 'A')
count += 1
self.assertEquals(count, size*4)
def test_main(): def test_main():
test_support.run_unittest(StrTest, TupleTest, ListTest) test_support.run_unittest(StrTest, TupleTest, ListTest, BufferTest)
if __name__ == '__main__': if __name__ == '__main__':
if len(sys.argv) > 1: if len(sys.argv) > 1:
......
...@@ -115,6 +115,25 @@ class StropFunctionTestCase(unittest.TestCase): ...@@ -115,6 +115,25 @@ class StropFunctionTestCase(unittest.TestCase):
strop.uppercase strop.uppercase
strop.whitespace strop.whitespace
@test_support.precisionbigmemtest(size=test_support._2G - 1, memuse=5)
def test_stropjoin_huge_list(self, size):
a = "A" * size
try:
r = strop.join([a, a], a)
except OverflowError:
pass
else:
self.assertEquals(len(r), len(a) * 3)
@test_support.precisionbigmemtest(size=test_support._2G - 1, memuse=1)
def test_stropjoin_huge_tup(self, size):
a = "A" * size
try:
r = strop.join((a, a), a)
except OverflowError:
pass # acceptable on 32-bit
else:
self.assertEquals(len(r), len(a) * 3)
transtable = '\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037 !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`xyzdefghijklmnopqrstuvwxyz{|}~\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377' transtable = '\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037 !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`xyzdefghijklmnopqrstuvwxyz{|}~\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377'
......
...@@ -33,6 +33,7 @@ verbose = 1 # Flag set to 0 by regrtest.py ...@@ -33,6 +33,7 @@ verbose = 1 # Flag set to 0 by regrtest.py
use_resources = None # Flag set to [] by regrtest.py use_resources = None # Flag set to [] by regrtest.py
max_memuse = 0 # Disable bigmem tests (they will still be run with max_memuse = 0 # Disable bigmem tests (they will still be run with
# small sizes, to make sure they work.) # small sizes, to make sure they work.)
real_max_memuse = 0
# _original_stdout is meant to hold stdout at the time regrtest began. # _original_stdout is meant to hold stdout at the time regrtest began.
# This may be "the real" stdout, or IDLE's emulation of stdout, or whatever. # This may be "the real" stdout, or IDLE's emulation of stdout, or whatever.
...@@ -323,6 +324,7 @@ def run_with_locale(catstr, *locales): ...@@ -323,6 +324,7 @@ def run_with_locale(catstr, *locales):
_1M = 1024*1024 _1M = 1024*1024
_1G = 1024 * _1M _1G = 1024 * _1M
_2G = 2 * _1G _2G = 2 * _1G
_4G = 4 * _1G
# Hack to get at the maximum value an internal index can take. # Hack to get at the maximum value an internal index can take.
class _Dummy: class _Dummy:
...@@ -333,6 +335,7 @@ MAX_Py_ssize_t = _Dummy()[:] ...@@ -333,6 +335,7 @@ MAX_Py_ssize_t = _Dummy()[:]
def set_memlimit(limit): def set_memlimit(limit):
import re import re
global max_memuse global max_memuse
global real_max_memuse
sizes = { sizes = {
'k': 1024, 'k': 1024,
'm': _1M, 'm': _1M,
...@@ -344,6 +347,7 @@ def set_memlimit(limit): ...@@ -344,6 +347,7 @@ def set_memlimit(limit):
if m is None: if m is None:
raise ValueError('Invalid memory limit %r' % (limit,)) raise ValueError('Invalid memory limit %r' % (limit,))
memlimit = int(float(m.group(1)) * sizes[m.group(3).lower()]) memlimit = int(float(m.group(1)) * sizes[m.group(3).lower()])
real_max_memuse = memlimit
if memlimit > MAX_Py_ssize_t: if memlimit > MAX_Py_ssize_t:
memlimit = MAX_Py_ssize_t memlimit = MAX_Py_ssize_t
if memlimit < _2G - 1: if memlimit < _2G - 1:
...@@ -389,6 +393,27 @@ def bigmemtest(minsize, memuse, overhead=5*_1M): ...@@ -389,6 +393,27 @@ def bigmemtest(minsize, memuse, overhead=5*_1M):
return wrapper return wrapper
return decorator return decorator
def precisionbigmemtest(size, memuse, overhead=5*_1M):
def decorator(f):
def wrapper(self):
if not real_max_memuse:
maxsize = 5147
else:
maxsize = size
if real_max_memuse and real_max_memuse < maxsize * memuse:
if verbose:
sys.stderr.write("Skipping %s because of memory "
"constraint\n" % (f.__name__,))
return
return f(self, maxsize)
wrapper.size = size
wrapper.memuse = memuse
wrapper.overhead = overhead
return wrapper
return decorator
def bigaddrspacetest(f): def bigaddrspacetest(f):
"""Decorator for tests that fill the address space.""" """Decorator for tests that fill the address space."""
def wrapper(self): def wrapper(self):
......
...@@ -12,6 +12,8 @@ What's New in Python 2.5.3? ...@@ -12,6 +12,8 @@ What's New in Python 2.5.3?
Core and builtins Core and builtins
----------------- -----------------
- Apply security patches from Apple.
- Issue #2620: Overflow checking when allocating or reallocating memory - Issue #2620: Overflow checking when allocating or reallocating memory
was not always being done properly in some python types and extension was not always being done properly in some python types and extension
modules. PyMem_MALLOC, PyMem_REALLOC, PyMem_NEW and PyMem_RESIZE have modules. PyMem_MALLOC, PyMem_REALLOC, PyMem_NEW and PyMem_RESIZE have
......
...@@ -1318,7 +1318,10 @@ PyObject * ...@@ -1318,7 +1318,10 @@ PyObject *
_PyObject_GC_Malloc(size_t basicsize) _PyObject_GC_Malloc(size_t basicsize)
{ {
PyObject *op; PyObject *op;
PyGC_Head *g = (PyGC_Head *)PyObject_MALLOC( PyGC_Head *g;
if (basicsize > PY_SSIZE_T_MAX - sizeof(PyGC_Head))
return PyErr_NoMemory();
g = (PyGC_Head *)PyObject_MALLOC(
sizeof(PyGC_Head) + basicsize); sizeof(PyGC_Head) + basicsize);
if (g == NULL) if (g == NULL)
return PyErr_NoMemory(); return PyErr_NoMemory();
...@@ -1361,6 +1364,8 @@ _PyObject_GC_Resize(PyVarObject *op, Py_ssize_t nitems) ...@@ -1361,6 +1364,8 @@ _PyObject_GC_Resize(PyVarObject *op, Py_ssize_t nitems)
{ {
const size_t basicsize = _PyObject_VAR_SIZE(op->ob_type, nitems); const size_t basicsize = _PyObject_VAR_SIZE(op->ob_type, nitems);
PyGC_Head *g = AS_GC(op); PyGC_Head *g = AS_GC(op);
if (basicsize > PY_SSIZE_T_MAX - sizeof(PyGC_Head))
return (PyVarObject *)PyErr_NoMemory();
g = (PyGC_Head *)PyObject_REALLOC(g, sizeof(PyGC_Head) + basicsize); g = (PyGC_Head *)PyObject_REALLOC(g, sizeof(PyGC_Head) + basicsize);
if (g == NULL) if (g == NULL)
return (PyVarObject *)PyErr_NoMemory(); return (PyVarObject *)PyErr_NoMemory();
......
...@@ -223,7 +223,7 @@ mmap_read_method(mmap_object *self, ...@@ -223,7 +223,7 @@ mmap_read_method(mmap_object *self,
return(NULL); return(NULL);
/* silently 'adjust' out-of-range requests */ /* silently 'adjust' out-of-range requests */
if ((self->pos + num_bytes) > self->size) { if (num_bytes > self->size - self->pos) {
num_bytes -= (self->pos+num_bytes) - self->size; num_bytes -= (self->pos+num_bytes) - self->size;
} }
result = Py_BuildValue("s#", self->data+self->pos, num_bytes); result = Py_BuildValue("s#", self->data+self->pos, num_bytes);
......
...@@ -216,6 +216,13 @@ strop_joinfields(PyObject *self, PyObject *args) ...@@ -216,6 +216,13 @@ strop_joinfields(PyObject *self, PyObject *args)
return NULL; return NULL;
} }
slen = PyString_GET_SIZE(item); slen = PyString_GET_SIZE(item);
if (slen > PY_SSIZE_T_MAX - reslen ||
seplen > PY_SSIZE_T_MAX - reslen - seplen) {
PyErr_SetString(PyExc_OverflowError,
"input too long");
Py_DECREF(res);
return NULL;
}
while (reslen + slen + seplen >= sz) { while (reslen + slen + seplen >= sz) {
if (_PyString_Resize(&res, sz * 2) < 0) if (_PyString_Resize(&res, sz * 2) < 0)
return NULL; return NULL;
...@@ -253,6 +260,14 @@ strop_joinfields(PyObject *self, PyObject *args) ...@@ -253,6 +260,14 @@ strop_joinfields(PyObject *self, PyObject *args)
return NULL; return NULL;
} }
slen = PyString_GET_SIZE(item); slen = PyString_GET_SIZE(item);
if (slen > PY_SSIZE_T_MAX - reslen ||
seplen > PY_SSIZE_T_MAX - reslen - seplen) {
PyErr_SetString(PyExc_OverflowError,
"input too long");
Py_DECREF(res);
Py_XDECREF(item);
return NULL;
}
while (reslen + slen + seplen >= sz) { while (reslen + slen + seplen >= sz) {
if (_PyString_Resize(&res, sz * 2) < 0) { if (_PyString_Resize(&res, sz * 2) < 0) {
Py_DECREF(item); Py_DECREF(item);
......
...@@ -427,6 +427,10 @@ buffer_repeat(PyBufferObject *self, Py_ssize_t count) ...@@ -427,6 +427,10 @@ buffer_repeat(PyBufferObject *self, Py_ssize_t count)
count = 0; count = 0;
if (!get_buf(self, &ptr, &size, ANY_BUFFER)) if (!get_buf(self, &ptr, &size, ANY_BUFFER))
return NULL; return NULL;
if (count > PY_SSIZE_T_MAX / size) {
PyErr_SetString(PyExc_MemoryError, "result too large");
return NULL;
}
ob = PyString_FromStringAndSize(NULL, size * count); ob = PyString_FromStringAndSize(NULL, size * count);
if ( ob == NULL ) if ( ob == NULL )
return NULL; return NULL;
......
...@@ -70,6 +70,8 @@ _PyLong_New(Py_ssize_t size) ...@@ -70,6 +70,8 @@ _PyLong_New(Py_ssize_t size)
PyErr_NoMemory(); PyErr_NoMemory();
return NULL; return NULL;
} }
/* XXX(nnorwitz): This can overflow --
PyObject_NEW_VAR / _PyObject_VAR_SIZE need to detect overflow */
return PyObject_NEW_VAR(PyLongObject, &PyLong_Type, size); return PyObject_NEW_VAR(PyLongObject, &PyLong_Type, size);
} }
......
...@@ -75,6 +75,11 @@ PyString_FromStringAndSize(const char *str, Py_ssize_t size) ...@@ -75,6 +75,11 @@ PyString_FromStringAndSize(const char *str, Py_ssize_t size)
return (PyObject *)op; return (PyObject *)op;
} }
if (size > PY_SSIZE_T_MAX - sizeof(PyStringObject)) {
PyErr_SetString(PyExc_OverflowError, "string is too large");
return NULL;
}
/* Inline PyObject_NewVar */ /* Inline PyObject_NewVar */
op = (PyStringObject *)PyObject_MALLOC(sizeof(PyStringObject) + size); op = (PyStringObject *)PyObject_MALLOC(sizeof(PyStringObject) + size);
if (op == NULL) if (op == NULL)
...@@ -110,7 +115,7 @@ PyString_FromString(const char *str) ...@@ -110,7 +115,7 @@ PyString_FromString(const char *str)
assert(str != NULL); assert(str != NULL);
size = strlen(str); size = strlen(str);
if (size > PY_SSIZE_T_MAX) { if (size > PY_SSIZE_T_MAX - sizeof(PyStringObject)) {
PyErr_SetString(PyExc_OverflowError, PyErr_SetString(PyExc_OverflowError,
"string is too long for a Python string"); "string is too long for a Python string");
return NULL; return NULL;
...@@ -971,14 +976,24 @@ string_concat(register PyStringObject *a, register PyObject *bb) ...@@ -971,14 +976,24 @@ string_concat(register PyStringObject *a, register PyObject *bb)
Py_INCREF(a); Py_INCREF(a);
return (PyObject *)a; return (PyObject *)a;
} }
/* Check that string sizes are not negative, to prevent an
overflow in cases where we are passed incorrectly-created
strings with negative lengths (due to a bug in other code).
*/
size = a->ob_size + b->ob_size; size = a->ob_size + b->ob_size;
if (size < 0) { if (a->ob_size < 0 || b->ob_size < 0 ||
a->ob_size > PY_SSIZE_T_MAX - b->ob_size) {
PyErr_SetString(PyExc_OverflowError, PyErr_SetString(PyExc_OverflowError,
"strings are too large to concat"); "strings are too large to concat");
return NULL; return NULL;
} }
/* Inline PyObject_NewVar */ /* Inline PyObject_NewVar */
if (size > PY_SSIZE_T_MAX - sizeof(PyStringObject)) {
PyErr_SetString(PyExc_OverflowError,
"strings are too large to concat");
return NULL;
}
op = (PyStringObject *)PyObject_MALLOC(sizeof(PyStringObject) + size); op = (PyStringObject *)PyObject_MALLOC(sizeof(PyStringObject) + size);
if (op == NULL) if (op == NULL)
return PyErr_NoMemory(); return PyErr_NoMemory();
......
...@@ -60,11 +60,12 @@ PyTuple_New(register Py_ssize_t size) ...@@ -60,11 +60,12 @@ PyTuple_New(register Py_ssize_t size)
Py_ssize_t nbytes = size * sizeof(PyObject *); Py_ssize_t nbytes = size * sizeof(PyObject *);
/* Check for overflow */ /* Check for overflow */
if (nbytes / sizeof(PyObject *) != (size_t)size || if (nbytes / sizeof(PyObject *) != (size_t)size ||
(nbytes += sizeof(PyTupleObject) - sizeof(PyObject *)) (nbytes > PY_SSIZE_T_MAX - sizeof(PyTupleObject) - sizeof(PyObject *)))
<= 0)
{ {
return PyErr_NoMemory(); return PyErr_NoMemory();
} }
nbytes += sizeof(PyTupleObject) - sizeof(PyObject *);
op = PyObject_GC_NewVar(PyTupleObject, &PyTuple_Type, size); op = PyObject_GC_NewVar(PyTupleObject, &PyTuple_Type, size);
if (op == NULL) if (op == NULL)
return NULL; return NULL;
......
...@@ -240,6 +240,11 @@ PyUnicodeObject *_PyUnicode_New(Py_ssize_t length) ...@@ -240,6 +240,11 @@ PyUnicodeObject *_PyUnicode_New(Py_ssize_t length)
return unicode_empty; return unicode_empty;
} }
/* Ensure we won't overflow the size. */
if (length > ((PY_SSIZE_T_MAX / sizeof(Py_UNICODE)) - 1)) {
return (PyUnicodeObject *)PyErr_NoMemory();
}
/* Unicode freelist & memory allocation */ /* Unicode freelist & memory allocation */
if (unicode_freelist) { if (unicode_freelist) {
unicode = unicode_freelist; unicode = unicode_freelist;
...@@ -1095,6 +1100,9 @@ PyObject *PyUnicode_EncodeUTF7(const Py_UNICODE *s, ...@@ -1095,6 +1100,9 @@ PyObject *PyUnicode_EncodeUTF7(const Py_UNICODE *s,
char * out; char * out;
char * start; char * start;
if (cbAllocated / 5 != size)
return PyErr_NoMemory();
if (size == 0) if (size == 0)
return PyString_FromStringAndSize(NULL, 0); return PyString_FromStringAndSize(NULL, 0);
...@@ -1693,8 +1701,9 @@ PyUnicode_EncodeUTF16(const Py_UNICODE *s, ...@@ -1693,8 +1701,9 @@ PyUnicode_EncodeUTF16(const Py_UNICODE *s,
{ {
PyObject *v; PyObject *v;
unsigned char *p; unsigned char *p;
Py_ssize_t nsize, bytesize;
#ifdef Py_UNICODE_WIDE #ifdef Py_UNICODE_WIDE
int i, pairs; Py_ssize_t i, pairs;
#else #else
const int pairs = 0; const int pairs = 0;
#endif #endif
...@@ -1717,8 +1726,15 @@ PyUnicode_EncodeUTF16(const Py_UNICODE *s, ...@@ -1717,8 +1726,15 @@ PyUnicode_EncodeUTF16(const Py_UNICODE *s,
if (s[i] >= 0x10000) if (s[i] >= 0x10000)
pairs++; pairs++;
#endif #endif
v = PyString_FromStringAndSize(NULL, /* 2 * (size + pairs + (byteorder == 0)) */
2 * (size + pairs + (byteorder == 0))); if (size > PY_SSIZE_T_MAX ||
size > PY_SSIZE_T_MAX - pairs - (byteorder == 0))
return PyErr_NoMemory();
nsize = (size + pairs + (byteorder == 0));
bytesize = nsize * 2;
if (bytesize / 2 != nsize)
return PyErr_NoMemory();
v = PyString_FromStringAndSize(NULL, bytesize);
if (v == NULL) if (v == NULL)
return NULL; return NULL;
...@@ -2046,6 +2062,11 @@ PyObject *unicodeescape_string(const Py_UNICODE *s, ...@@ -2046,6 +2062,11 @@ PyObject *unicodeescape_string(const Py_UNICODE *s,
char *p; char *p;
static const char *hexdigit = "0123456789abcdef"; static const char *hexdigit = "0123456789abcdef";
#ifdef Py_UNICODE_WIDE
const Py_ssize_t expandsize = 10;
#else
const Py_ssize_t expandsize = 6;
#endif
/* Initial allocation is based on the longest-possible unichr /* Initial allocation is based on the longest-possible unichr
escape. escape.
...@@ -2061,13 +2082,12 @@ PyObject *unicodeescape_string(const Py_UNICODE *s, ...@@ -2061,13 +2082,12 @@ PyObject *unicodeescape_string(const Py_UNICODE *s,
escape. escape.
*/ */
if (size > (PY_SSIZE_T_MAX - 2 - 1) / expandsize)
return PyErr_NoMemory();
repr = PyString_FromStringAndSize(NULL, repr = PyString_FromStringAndSize(NULL,
2 2
#ifdef Py_UNICODE_WIDE + expandsize*size
+ 10*size
#else
+ 6*size
#endif
+ 1); + 1);
if (repr == NULL) if (repr == NULL)
return NULL; return NULL;
...@@ -2320,12 +2340,16 @@ PyObject *PyUnicode_EncodeRawUnicodeEscape(const Py_UNICODE *s, ...@@ -2320,12 +2340,16 @@ PyObject *PyUnicode_EncodeRawUnicodeEscape(const Py_UNICODE *s,
char *q; char *q;
static const char *hexdigit = "0123456789abcdef"; static const char *hexdigit = "0123456789abcdef";
#ifdef Py_UNICODE_WIDE #ifdef Py_UNICODE_WIDE
repr = PyString_FromStringAndSize(NULL, 10 * size); const Py_ssize_t expandsize = 10;
#else #else
repr = PyString_FromStringAndSize(NULL, 6 * size); const Py_ssize_t expandsize = 6;
#endif #endif
if (size > PY_SSIZE_T_MAX / expandsize)
return PyErr_NoMemory();
repr = PyString_FromStringAndSize(NULL, expandsize * size);
if (repr == NULL) if (repr == NULL)
return NULL; return NULL;
if (size == 0) if (size == 0)
...@@ -4761,6 +4785,11 @@ PyUnicodeObject *pad(PyUnicodeObject *self, ...@@ -4761,6 +4785,11 @@ PyUnicodeObject *pad(PyUnicodeObject *self,
return self; return self;
} }
if (left > PY_SSIZE_T_MAX - self->length ||
right > PY_SSIZE_T_MAX - (left + self->length)) {
PyErr_SetString(PyExc_OverflowError, "padded string is too long");
return NULL;
}
u = _PyUnicode_New(left + self->length + right); u = _PyUnicode_New(left + self->length + right);
if (u) { if (u) {
if (left) if (left)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment