@@ -152,6 +152,15 @@ fold_tuple_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t codelen,
152152 PyTuple_SET_ITEM (newconst , i , constant );
153153 }
154154
155+ Py_ssize_t index = PyList_GET_SIZE (consts );
156+ #if SIZEOF_SIZE_T > SIZEOF_INT
157+ if ((size_t )index >= UINT_MAX - 1 ) {
158+ Py_DECREF (newconst );
159+ PyErr_SetString (PyExc_OverflowError , "too many constants" );
160+ return -1 ;
161+ }
162+ #endif
163+
155164 /* Append folded constant onto consts */
156165 if (PyList_Append (consts , newconst )) {
157166 Py_DECREF (newconst );
@@ -160,7 +169,7 @@ fold_tuple_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t codelen,
160169 Py_DECREF (newconst );
161170
162171 return copy_op_arg (codestr , c_start , LOAD_CONST ,
163- PyList_GET_SIZE ( consts ) - 1 , opcode_end );
172+ ( unsigned int ) index , opcode_end );
164173}
165174
166175static unsigned int *
@@ -221,7 +230,7 @@ PyObject *
221230PyCode_Optimize (PyObject * code , PyObject * consts , PyObject * names ,
222231 PyObject * lnotab_obj )
223232{
224- Py_ssize_t h , i , nexti , op_start , codelen , tgt ;
233+ Py_ssize_t h , i , nexti , op_start , tgt ;
225234 unsigned int j , nops ;
226235 unsigned char opcode , nextop ;
227236 _Py_CODEUNIT * codestr = NULL ;
@@ -249,17 +258,22 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
249258 the peephole optimizer doesn't modify line numbers. */
250259
251260 assert (PyBytes_Check (code ));
252- codelen = PyBytes_GET_SIZE (code );
253- assert (codelen % sizeof (_Py_CODEUNIT ) == 0 );
261+ Py_ssize_t codesize = PyBytes_GET_SIZE (code );
262+ assert (codesize % sizeof (_Py_CODEUNIT ) == 0 );
263+ Py_ssize_t codelen = codesize / sizeof (_Py_CODEUNIT );
264+ if (codelen > INT_MAX ) {
265+ /* Python assembler is limited to INT_MAX: see assembler.a_offset in
266+ compile.c. */
267+ goto exitUnchanged ;
268+ }
254269
255270 /* Make a modifiable copy of the code string */
256- codestr = (_Py_CODEUNIT * )PyMem_Malloc (codelen );
271+ codestr = (_Py_CODEUNIT * )PyMem_Malloc (codesize );
257272 if (codestr == NULL ) {
258273 PyErr_NoMemory ();
259274 goto exitError ;
260275 }
261- memcpy (codestr , PyBytes_AS_STRING (code ), codelen );
262- codelen /= sizeof (_Py_CODEUNIT );
276+ memcpy (codestr , PyBytes_AS_STRING (code ), codesize );
263277
264278 blocks = markblocks (codestr , codelen );
265279 if (blocks == NULL )
@@ -357,7 +371,11 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
357371 jump past it), and all conditional jumps pop their
358372 argument when they're not taken (so change the
359373 first jump to pop its argument when it's taken). */
360- h = set_arg (codestr , i , (tgt + 1 ) * sizeof (_Py_CODEUNIT ));
374+ Py_ssize_t arg = (tgt + 1 );
375+ /* cannot overflow: codelen <= INT_MAX */
376+ assert ((size_t )arg <= UINT_MAX / sizeof (_Py_CODEUNIT ));
377+ arg *= sizeof (_Py_CODEUNIT );
378+ h = set_arg (codestr , i , (unsigned int )arg );
361379 j = opcode == JUMP_IF_TRUE_OR_POP ?
362380 POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE ;
363381 }
@@ -383,17 +401,20 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
383401 codestr [op_start ] = PACKOPARG (RETURN_VALUE , 0 );
384402 fill_nops (codestr , op_start + 1 , i + 1 );
385403 } else if (UNCONDITIONAL_JUMP (_Py_OPCODE (codestr [tgt ]))) {
386- j = GETJUMPTGT (codestr , tgt );
404+ size_t arg = GETJUMPTGT (codestr , tgt );
387405 if (opcode == JUMP_FORWARD ) { /* JMP_ABS can go backwards */
388406 opcode = JUMP_ABSOLUTE ;
389407 } else if (!ABSOLUTE_JUMP (opcode )) {
390- if (( Py_ssize_t ) j < i + 1 ) {
408+ if (arg < ( size_t )( i + 1 ) ) {
391409 break ; /* No backward relative jumps */
392410 }
393- j -= i + 1 ; /* Calc relative jump addr */
411+ arg -= i + 1 ; /* Calc relative jump addr */
394412 }
395- j *= sizeof (_Py_CODEUNIT );
396- copy_op_arg (codestr , op_start , opcode , j , i + 1 );
413+ /* cannot overflow: codelen <= INT_MAX */
414+ assert (arg <= (UINT_MAX / sizeof (_Py_CODEUNIT )));
415+ arg *= sizeof (_Py_CODEUNIT );
416+ copy_op_arg (codestr , op_start , opcode ,
417+ (unsigned int )arg , i + 1 );
397418 }
398419 break ;
399420
@@ -427,11 +448,14 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
427448
428449 /* Fixup lnotab */
429450 for (i = 0 , nops = 0 ; i < codelen ; i ++ ) {
430- assert (i - nops <= INT_MAX );
451+ size_t block = (size_t )i - nops ;
452+ /* cannot overflow: codelen <= INT_MAX */
453+ assert (block <= UINT_MAX );
431454 /* original code offset => new code offset */
432- blocks [i ] = i - nops ;
433- if (_Py_OPCODE (codestr [i ]) == NOP )
455+ blocks [i ] = ( unsigned int ) block ;
456+ if (_Py_OPCODE (codestr [i ]) == NOP ) {
434457 nops ++ ;
458+ }
435459 }
436460 cum_orig_offset = 0 ;
437461 last_offset = 0 ;
@@ -476,12 +500,14 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
476500 j *= sizeof (_Py_CODEUNIT );
477501 break ;
478502 }
479- nexti = i - op_start + 1 ;
480- if (instrsize (j ) > nexti )
503+ Py_ssize_t ilen = i - op_start + 1 ;
504+ if (instrsize (j ) > ilen ) {
481505 goto exitUnchanged ;
482- /* If instrsize(j) < nexti, we'll emit EXTENDED_ARG 0 */
483- write_op_arg (codestr + h , opcode , j , nexti );
484- h += nexti ;
506+ }
507+ assert (ilen <= INT_MAX );
508+ /* If instrsize(j) < ilen, we'll emit EXTENDED_ARG 0 */
509+ write_op_arg (codestr + h , opcode , j , (int )ilen );
510+ h += ilen ;
485511 }
486512 assert (h + (Py_ssize_t )nops == codelen );
487513
0 commit comments