Skip to content

Commit d254ea6

Browse files
committed
merge 3.3 (closes #22518)
2 parents 73e7a2b + 4237899 commit d254ea6

2 files changed

Lines changed: 49 additions & 17 deletions

File tree

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ What's New in Python 3.4.3?
99
Core and Builtins
1010
-----------------
1111

12+
- Issue #22518: Fix integer overflow issues in latin-1 encoding.
13+
1214
Library
1315
-------
1416

Objects/unicodeobject.c

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4093,23 +4093,32 @@ unicode_decode_call_errorhandler_wchar(
40934093
have+the replacement+the rest of the string (starting
40944094
at the new input position), so we won't have to check space
40954095
when there are no errors in the rest of the string) */
4096-
requiredsize = *outpos + repwlen + insize-newpos;
4096+
requiredsize = *outpos;
4097+
if (requiredsize > PY_SSIZE_T_MAX - repwlen)
4098+
goto overflow;
4099+
requiredsize += repwlen;
4100+
if (requiredsize > PY_SSIZE_T_MAX - (insize - newpos))
4101+
goto overflow;
4102+
requiredsize += insize - newpos;
40974103
if (requiredsize > outsize) {
4098-
if (requiredsize < 2*outsize)
4104+
if (outsize <= PY_SSIZE_T_MAX/2 && requiredsize < 2*outsize)
40994105
requiredsize = 2*outsize;
41004106
if (unicode_resize(output, requiredsize) < 0)
41014107
goto onError;
41024108
}
41034109
wcsncpy(_PyUnicode_WSTR(*output) + *outpos, repwstr, repwlen);
41044110
*outpos += repwlen;
4105-
41064111
*endinpos = newpos;
41074112
*inptr = *input + newpos;
41084113

41094114
/* we made it! */
41104115
Py_XDECREF(restuple);
41114116
return 0;
41124117

4118+
overflow:
4119+
PyErr_SetString(PyExc_OverflowError,
4120+
"decoded result is too long for a Python string");
4121+
41134122
onError:
41144123
Py_XDECREF(restuple);
41154124
return -1;
@@ -6502,7 +6511,7 @@ unicode_encode_ucs1(PyObject *unicode,
65026511
Py_ssize_t collstart = pos;
65036512
Py_ssize_t collend = pos;
65046513
/* find all unecodable characters */
6505-
while ((collend < size) && (PyUnicode_READ(kind, data, collend)>=limit))
6514+
while ((collend < size) && (PyUnicode_READ(kind, data, collend) >= limit))
65066515
++collend;
65076516
/* cache callback name lookup (if not done yet, i.e. it's the first error) */
65086517
if (known_errorHandler==-1) {
@@ -6522,36 +6531,43 @@ unicode_encode_ucs1(PyObject *unicode,
65226531
raise_encode_exception(&exc, encoding, unicode, collstart, collend, reason);
65236532
goto onError;
65246533
case 2: /* replace */
6525-
while (collstart++<collend)
6534+
while (collstart++ < collend)
65266535
*str++ = '?'; /* fall through */
65276536
case 3: /* ignore */
65286537
pos = collend;
65296538
break;
65306539
case 4: /* xmlcharrefreplace */
65316540
respos = str - PyBytes_AS_STRING(res);
6541+
requiredsize = respos;
65326542
/* determine replacement size */
6533-
for (i = collstart, repsize = 0; i < collend; ++i) {
6543+
for (i = collstart; i < collend; ++i) {
65346544
Py_UCS4 ch = PyUnicode_READ(kind, data, i);
6545+
Py_ssize_t incr;
65356546
if (ch < 10)
6536-
repsize += 2+1+1;
6547+
incr = 2+1+1;
65376548
else if (ch < 100)
6538-
repsize += 2+2+1;
6549+
incr = 2+2+1;
65396550
else if (ch < 1000)
6540-
repsize += 2+3+1;
6551+
incr = 2+3+1;
65416552
else if (ch < 10000)
6542-
repsize += 2+4+1;
6553+
incr = 2+4+1;
65436554
else if (ch < 100000)
6544-
repsize += 2+5+1;
6555+
incr = 2+5+1;
65456556
else if (ch < 1000000)
6546-
repsize += 2+6+1;
6557+
incr = 2+6+1;
65476558
else {
65486559
assert(ch <= MAX_UNICODE);
6549-
repsize += 2+7+1;
6560+
incr = 2+7+1;
65506561
}
6562+
if (requiredsize > PY_SSIZE_T_MAX - incr)
6563+
goto overflow;
6564+
requiredsize += incr;
65516565
}
6552-
requiredsize = respos+repsize+(size-collend);
6566+
if (requiredsize > PY_SSIZE_T_MAX - (size - collend))
6567+
goto overflow;
6568+
requiredsize += size - collend;
65536569
if (requiredsize > ressize) {
6554-
if (requiredsize<2*ressize)
6570+
if (ressize <= PY_SSIZE_T_MAX/2 && requiredsize < 2*ressize)
65556571
requiredsize = 2*ressize;
65566572
if (_PyBytes_Resize(&res, requiredsize))
65576573
goto onError;
@@ -6577,6 +6593,10 @@ unicode_encode_ucs1(PyObject *unicode,
65776593
if (repsize > 1) {
65786594
/* Make room for all additional bytes. */
65796595
respos = str - PyBytes_AS_STRING(res);
6596+
if (ressize > PY_SSIZE_T_MAX - repsize - 1) {
6597+
Py_DECREF(repunicode);
6598+
goto overflow;
6599+
}
65806600
if (_PyBytes_Resize(&res, ressize+repsize-1)) {
65816601
Py_DECREF(repunicode);
65826602
goto onError;
@@ -6595,9 +6615,15 @@ unicode_encode_ucs1(PyObject *unicode,
65956615
we won't have to check space for encodable characters) */
65966616
respos = str - PyBytes_AS_STRING(res);
65976617
repsize = PyUnicode_GET_LENGTH(repunicode);
6598-
requiredsize = respos+repsize+(size-collend);
6618+
requiredsize = respos;
6619+
if (requiredsize > PY_SSIZE_T_MAX - repsize)
6620+
goto overflow;
6621+
requiredsize += repsize;
6622+
if (requiredsize > PY_SSIZE_T_MAX - (size - collend))
6623+
goto overflow;
6624+
requiredsize += size - collend;
65996625
if (requiredsize > ressize) {
6600-
if (requiredsize<2*ressize)
6626+
if (ressize <= PY_SSIZE_T_MAX/2 && requiredsize < 2*ressize)
66016627
requiredsize = 2*ressize;
66026628
if (_PyBytes_Resize(&res, requiredsize)) {
66036629
Py_DECREF(repunicode);
@@ -6635,6 +6661,10 @@ unicode_encode_ucs1(PyObject *unicode,
66356661
Py_XDECREF(exc);
66366662
return res;
66376663

6664+
overflow:
6665+
PyErr_SetString(PyExc_OverflowError,
6666+
"encoded result is too long for a Python string");
6667+
66386668
onError:
66396669
Py_XDECREF(res);
66406670
Py_XDECREF(errorHandler);

0 commit comments

Comments
 (0)