@@ -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