Skip to content

Commit

Permalink
[3.10] GH-93964: Harden overflow checks before _PyBytes_Resize in com…
Browse files Browse the repository at this point in the history
…pile.c (GH-94045)
  • Loading branch information
sweeneyde authored Jun 22, 2022
1 parent ad2e9f9 commit 08069ba
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Strengthened compiler overflow checks to prevent crashes when compiling very large source files.
26 changes: 21 additions & 5 deletions Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -6605,16 +6605,26 @@ static int
assemble_emit_linetable_pair(struct assembler *a, int bdelta, int ldelta)
{
Py_ssize_t len = PyBytes_GET_SIZE(a->a_lnotab);
if (a->a_lnotab_off + 2 >= len) {
if (_PyBytes_Resize(&a->a_lnotab, len * 2) < 0)
if (a->a_lnotab_off > INT_MAX - 2) {
goto overflow;
}
if (a->a_lnotab_off >= len - 2) {
if (len > INT_MAX / 2) {
goto overflow;
}
if (_PyBytes_Resize(&a->a_lnotab, len * 2) < 0) {
return 0;
}
}
unsigned char *lnotab = (unsigned char *) PyBytes_AS_STRING(a->a_lnotab);
lnotab += a->a_lnotab_off;
a->a_lnotab_off += 2;
*lnotab++ = bdelta;
*lnotab++ = ldelta;
return 1;
overflow:
PyErr_SetString(PyExc_OverflowError, "line number table is too long");
return 0;
}

/* Appends a range to the end of the line number table. See
Expand Down Expand Up @@ -6687,21 +6697,27 @@ assemble_emit(struct assembler *a, struct instr *i)
int size, arg = 0;
Py_ssize_t len = PyBytes_GET_SIZE(a->a_bytecode);
_Py_CODEUNIT *code;

arg = i->i_oparg;
size = instrsize(arg);
if (i->i_lineno && !assemble_lnotab(a, i))
return 0;
if (a->a_offset > INT_MAX - size) {
goto overflow;
}
if (a->a_offset + size >= len / (int)sizeof(_Py_CODEUNIT)) {
if (len > PY_SSIZE_T_MAX / 2)
return 0;
if (len > INT_MAX / 2) {
goto overflow;
}
if (_PyBytes_Resize(&a->a_bytecode, len * 2) < 0)
return 0;
}
code = (_Py_CODEUNIT *)PyBytes_AS_STRING(a->a_bytecode) + a->a_offset;
a->a_offset += size;
write_op_arg(code, i->i_opcode, arg, size);
return 1;
overflow:
PyErr_SetString(PyExc_OverflowError, "bytecode is too long");
return 0;
}

static void
Expand Down

0 comments on commit 08069ba

Please sign in to comment.