-
-
Notifications
You must be signed in to change notification settings - Fork 32.1k
bpo-9566: Fix compiler warnings in peephole.c #11011
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -135,6 +135,13 @@ fold_tuple_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t codelen, | |
/* Pre-conditions */ | ||
assert(PyList_CheckExact(consts)); | ||
|
||
#if SIZEOF_SIZE_T > 4 | ||
if (PyList_GET_SIZE(consts) >= UINT_MAX-1) { | ||
PyErr_SetString(PyExc_OverflowError, | ||
"cannot add more objects to co_consts"); | ||
return -1; | ||
} | ||
#endif | ||
/* Buildup new tuple of constants */ | ||
PyObject *newconst = PyTuple_New(n); | ||
if (newconst == NULL) { | ||
|
@@ -160,7 +167,7 @@ fold_tuple_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t codelen, | |
Py_DECREF(newconst); | ||
|
||
return copy_op_arg(codestr, c_start, LOAD_CONST, | ||
PyList_GET_SIZE(consts)-1, opcode_end); | ||
(unsigned int)PyList_GET_SIZE(consts)-1, opcode_end); | ||
} | ||
|
||
static unsigned int * | ||
|
@@ -222,6 +229,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, | |
PyObject *lnotab_obj) | ||
{ | ||
Py_ssize_t h, i, nexti, op_start, codelen, tgt; | ||
size_t oparg; | ||
unsigned int j, nops; | ||
unsigned char opcode, nextop; | ||
_Py_CODEUNIT *codestr = NULL; | ||
|
@@ -357,9 +365,18 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, | |
jump past it), and all conditional jumps pop their | ||
argument when they're not taken (so change the | ||
first jump to pop its argument when it's taken). */ | ||
h = set_arg(codestr, i, (tgt + 1) * sizeof(_Py_CODEUNIT)); | ||
j = opcode == JUMP_IF_TRUE_OR_POP ? | ||
POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE; | ||
oparg = (tgt + 1) * sizeof(_Py_CODEUNIT); | ||
#if SIZEOF_SIZE_T > 4 | ||
/* only replace if it is not too far away */ | ||
if (oparg > UINT_MAX) { | ||
h = -1; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I cannot overflow in practice. My PR uses an assertion instead, but also makes sure that the code is smaller than INT_MAX at PyCode_Optimize() entry point (sanity check, it should never occur in pratice, see my comment in my PR ;-)). |
||
} else | ||
#endif | ||
{ | ||
h = set_arg(codestr, i, (unsigned int)oparg); | ||
j = opcode == JUMP_IF_TRUE_OR_POP ? | ||
POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE; | ||
} | ||
} | ||
|
||
if (h >= 0) { | ||
|
@@ -377,23 +394,34 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, | |
case JUMP_ABSOLUTE: | ||
h = GETJUMPTGT(codestr, i); | ||
tgt = find_op(codestr, codelen, h); | ||
j = _Py_OPCODE(codestr[tgt]); | ||
/* Replace JUMP_* to a RETURN into just a RETURN */ | ||
if (UNCONDITIONAL_JUMP(opcode) && | ||
_Py_OPCODE(codestr[tgt]) == RETURN_VALUE) { | ||
if (UNCONDITIONAL_JUMP(opcode) && j == RETURN_VALUE) { | ||
codestr[op_start] = PACKOPARG(RETURN_VALUE, 0); | ||
fill_nops(codestr, op_start + 1, i + 1); | ||
} else if (UNCONDITIONAL_JUMP(_Py_OPCODE(codestr[tgt]))) { | ||
j = GETJUMPTGT(codestr, tgt); | ||
if (opcode == JUMP_FORWARD) { /* JMP_ABS can go backwards */ | ||
opcode = JUMP_ABSOLUTE; | ||
} else if (!ABSOLUTE_JUMP(opcode)) { | ||
if ((Py_ssize_t)j < i + 1) { | ||
break; /* No backward relative jumps */ | ||
} else if (UNCONDITIONAL_JUMP(j)) { | ||
oparg = get_arg(codestr, tgt); | ||
if (j == JUMP_FORWARD) { | ||
h = (tgt + 1) * sizeof(_Py_CODEUNIT); | ||
oparg += h; | ||
/* If the new jump target index is larger than the | ||
eval loop's oparg (unsigned int), no rewritting | ||
can be done. */ | ||
#if SIZEOF_SIZE_T > 4 | ||
if (oparg > UINT_MAX) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It cannot overflow in practice, again, see my PR. |
||
#else | ||
if (oparg < h) /* addition wrapped? */ | ||
#endif | ||
{ | ||
break; | ||
} | ||
j -= i + 1; /* Calc relative jump addr */ | ||
} | ||
j *= sizeof(_Py_CODEUNIT); | ||
copy_op_arg(codestr, op_start, opcode, j, i + 1); | ||
if (opcode == JUMP_FORWARD) | ||
{ | ||
opcode = JUMP_ABSOLUTE; | ||
} | ||
copy_op_arg(codestr, op_start, opcode, | ||
(unsigned int)oparg, i + 1); | ||
} | ||
break; | ||
|
||
|
@@ -429,7 +457,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, | |
for (i = 0, nops = 0; i < codelen; i++) { | ||
assert(i - nops <= INT_MAX); | ||
/* original code offset => new code offset */ | ||
blocks[i] = i - nops; | ||
blocks[i] = (int)(i - nops); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. blocks uses unsigned int, not signed int. |
||
if (_Py_OPCODE(codestr[i]) == NOP) | ||
nops++; | ||
} | ||
|
@@ -480,7 +508,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, | |
if (instrsize(j) > nexti) | ||
goto exitUnchanged; | ||
/* If instrsize(j) < nexti, we'll emit EXTENDED_ARG 0 */ | ||
write_op_arg(codestr + h, opcode, j, nexti); | ||
write_op_arg(codestr + h, opcode, j, (int)nexti); | ||
h += nexti; | ||
} | ||
assert(h + (Py_ssize_t)nops == codelen); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My PR uses "if ((size_t)index >= UINT_MAX - 1) {" which shouldn't emit a compiler warning on 32-bit size_t.