From acd2c5c8349a4cd713b1b36c0e6ec6f39791ca19 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 18 Mar 2022 13:18:59 +1100 Subject: [PATCH] py/emitbc: Add check for bytecode jump offset overflow. Signed-off-by: Damien George --- py/emitbc.c | 9 +++++++++ tests/stress/bytecode_limit.py | 7 +++++++ tests/stress/bytecode_limit.py.exp | 4 ++++ 3 files changed, 20 insertions(+) diff --git a/py/emitbc.c b/py/emitbc.c index 14a72e2765..90ab6c0a92 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -64,6 +64,7 @@ struct _emit_t { size_t bytecode_offset; size_t bytecode_size; byte *code_base; // stores both byte code and code info + bool overflow; size_t n_info; size_t n_cell; @@ -260,6 +261,9 @@ STATIC void emit_write_bytecode_byte_label(emit_t *emit, int stack_adj, byte b1, if (is_signed) { bytecode_offset += 0x4000; } + if (emit->pass == MP_PASS_EMIT && !(0 <= bytecode_offset && bytecode_offset <= 0x7fff)) { + emit->overflow = true; + } c[1] = 0x80 | (bytecode_offset & 0x7f); c[2] = bytecode_offset >> 7; } @@ -274,6 +278,7 @@ void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) { emit->last_source_line = 1; emit->bytecode_offset = 0; emit->code_info_offset = 0; + emit->overflow = false; // Write local state size, exception stack size, scope flags and number of arguments { @@ -373,6 +378,10 @@ bool mp_emit_bc_end_pass(emit_t *emit) { return false; } + if (emit->overflow) { + mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("bytecode overflow")); + } + // Bytecode is finalised, assign it to the raw code object. mp_emit_glue_assign_bytecode(emit->scope->raw_code, emit->code_base, #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS diff --git a/tests/stress/bytecode_limit.py b/tests/stress/bytecode_limit.py index 0cb0c21e40..49f7cd2caf 100644 --- a/tests/stress/bytecode_limit.py +++ b/tests/stress/bytecode_limit.py @@ -24,3 +24,10 @@ x = [1 if x else 123] print(x) """ ) + +# Test overflow of jump offset. +for n in (430, 431, 432, 433): + try: + exec("cond = 0\nif cond:\n" + body * n + "else:\n print('cond false')\n") + except RuntimeError: + print("RuntimeError") diff --git a/tests/stress/bytecode_limit.py.exp b/tests/stress/bytecode_limit.py.exp index 3214bfe58c..b2d9737d80 100644 --- a/tests/stress/bytecode_limit.py.exp +++ b/tests/stress/bytecode_limit.py.exp @@ -1 +1,5 @@ [123] +cond false +cond false +RuntimeError +RuntimeError