Skip to content

Commit 028f0ef

Browse files
authored
bpo-9566: Fix compiler warnings in peephole.c (GH-10652)
1 parent 1133a8c commit 028f0ef

File tree

1 file changed

+47
-21
lines changed

1 file changed

+47
-21
lines changed

Python/peephole.c

+47-21
Original file line numberDiff line numberDiff line change
@@ -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

166175
static unsigned int *
@@ -221,7 +230,7 @@ PyObject *
221230
PyCode_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

Comments
 (0)