@@ -152,6 +152,15 @@ fold_tuple_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t codelen,
152
152
PyTuple_SET_ITEM (newconst , i , constant );
153
153
}
154
154
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
+
155
164
/* Append folded constant onto consts */
156
165
if (PyList_Append (consts , newconst )) {
157
166
Py_DECREF (newconst );
@@ -160,7 +169,7 @@ fold_tuple_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t codelen,
160
169
Py_DECREF (newconst );
161
170
162
171
return copy_op_arg (codestr , c_start , LOAD_CONST ,
163
- PyList_GET_SIZE ( consts ) - 1 , opcode_end );
172
+ ( unsigned int ) index , opcode_end );
164
173
}
165
174
166
175
static unsigned int *
@@ -221,7 +230,7 @@ PyObject *
221
230
PyCode_Optimize (PyObject * code , PyObject * consts , PyObject * names ,
222
231
PyObject * lnotab_obj )
223
232
{
224
- Py_ssize_t h , i , nexti , op_start , codelen , tgt ;
233
+ Py_ssize_t h , i , nexti , op_start , tgt ;
225
234
unsigned int j , nops ;
226
235
unsigned char opcode , nextop ;
227
236
_Py_CODEUNIT * codestr = NULL ;
@@ -249,17 +258,22 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
249
258
the peephole optimizer doesn't modify line numbers. */
250
259
251
260
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
+ }
254
269
255
270
/* Make a modifiable copy of the code string */
256
- codestr = (_Py_CODEUNIT * )PyMem_Malloc (codelen );
271
+ codestr = (_Py_CODEUNIT * )PyMem_Malloc (codesize );
257
272
if (codestr == NULL ) {
258
273
PyErr_NoMemory ();
259
274
goto exitError ;
260
275
}
261
- memcpy (codestr , PyBytes_AS_STRING (code ), codelen );
262
- codelen /= sizeof (_Py_CODEUNIT );
276
+ memcpy (codestr , PyBytes_AS_STRING (code ), codesize );
263
277
264
278
blocks = markblocks (codestr , codelen );
265
279
if (blocks == NULL )
@@ -357,7 +371,11 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
357
371
jump past it), and all conditional jumps pop their
358
372
argument when they're not taken (so change the
359
373
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 );
361
379
j = opcode == JUMP_IF_TRUE_OR_POP ?
362
380
POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE ;
363
381
}
@@ -383,17 +401,20 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
383
401
codestr [op_start ] = PACKOPARG (RETURN_VALUE , 0 );
384
402
fill_nops (codestr , op_start + 1 , i + 1 );
385
403
} else if (UNCONDITIONAL_JUMP (_Py_OPCODE (codestr [tgt ]))) {
386
- j = GETJUMPTGT (codestr , tgt );
404
+ size_t arg = GETJUMPTGT (codestr , tgt );
387
405
if (opcode == JUMP_FORWARD ) { /* JMP_ABS can go backwards */
388
406
opcode = JUMP_ABSOLUTE ;
389
407
} else if (!ABSOLUTE_JUMP (opcode )) {
390
- if (( Py_ssize_t ) j < i + 1 ) {
408
+ if (arg < ( size_t )( i + 1 ) ) {
391
409
break ; /* No backward relative jumps */
392
410
}
393
- j -= i + 1 ; /* Calc relative jump addr */
411
+ arg -= i + 1 ; /* Calc relative jump addr */
394
412
}
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 );
397
418
}
398
419
break ;
399
420
@@ -427,11 +448,14 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
427
448
428
449
/* Fixup lnotab */
429
450
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 );
431
454
/* 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 ) {
434
457
nops ++ ;
458
+ }
435
459
}
436
460
cum_orig_offset = 0 ;
437
461
last_offset = 0 ;
@@ -476,12 +500,14 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
476
500
j *= sizeof (_Py_CODEUNIT );
477
501
break ;
478
502
}
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 ) {
481
505
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 ;
485
511
}
486
512
assert (h + (Py_ssize_t )nops == codelen );
487
513
0 commit comments