From 21309bc6d7c783c5614575603a197bfac35b5dab Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 25 Jul 2015 08:53:28 -0700 Subject: [PATCH] Error on bytecodes longer than 0xFFFF (fix #269) This lets us use uint16_t for the program counter. JVM languages have the same limit on method size so it is a reasonable limit. --- compile.c | 16 +++++++++++----- compile.h | 2 +- execute.c | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/compile.c b/compile.c index 407e9f0..6988d27 100644 --- a/compile.c +++ b/compile.c @@ -1047,7 +1047,7 @@ static int expand_call_arglist(block* b) { return errors; } -static int compile(struct bytecode* bc, block b) { +static int compile(struct bytecode* bc, block b, struct locfile* lf) { int errors = 0; int pos = 0; int var_frame_idx = 0; @@ -1088,6 +1088,13 @@ static int compile(struct bytecode* bc, block b) { curr->imm.intval = idx; } } + if (pos > 0xFFFF) { + // too long for program counter to fit in uint16_t + locfile_locate(lf, UNKNOWN_LOCATION, + "function compiled to %d bytes which is too long", pos); + errors++; + } + bc->codelen = pos; bc->debuginfo = jv_object_set(bc->debuginfo, jv_string("locals"), localnames); if (bc->nsubfunctions) { bc->subfunctions = jv_mem_alloc(sizeof(struct bytecode*) * bc->nsubfunctions); @@ -1108,14 +1115,13 @@ static int compile(struct bytecode* bc, block b) { params = jv_array_append(params, jv_string(param->symbol)); } subfn->debuginfo = jv_object_set(subfn->debuginfo, jv_string("params"), params); - errors += compile(subfn, curr->subfn); + errors += compile(subfn, curr->subfn, lf); curr->subfn = gen_noop(); } } } else { bc->subfunctions = 0; } - bc->codelen = pos; uint16_t* code = jv_mem_alloc(sizeof(uint16_t) * bc->codelen); bc->code = code; pos = 0; @@ -1174,7 +1180,7 @@ static int compile(struct bytecode* bc, block b) { return errors; } -int block_compile(block b, struct bytecode** out) { +int block_compile(block b, struct bytecode** out, struct locfile* lf) { struct bytecode* bc = jv_mem_alloc(sizeof(struct bytecode)); bc->parent = 0; bc->nclosures = 0; @@ -1184,7 +1190,7 @@ int block_compile(block b, struct bytecode** out) { bc->globals->cfunctions = jv_mem_alloc(sizeof(struct cfunction) * ncfunc); bc->globals->cfunc_names = jv_array(); bc->debuginfo = jv_object_set(jv_object(), jv_string("name"), jv_null()); - int nerrors = compile(bc, b); + int nerrors = compile(bc, b, lf); assert(bc->globals->ncfunctions == ncfunc); if (nerrors > 0) { bytecode_free(bc); diff --git a/compile.h b/compile.h index 2ef193e..baec373 100644 --- a/compile.h +++ b/compile.h @@ -75,7 +75,7 @@ block block_drop_unreferenced(block body); jv block_take_imports(block* body); -int block_compile(block, struct bytecode**); +int block_compile(block, struct bytecode**, struct locfile*); void block_free(block); diff --git a/execute.c b/execute.c index 9f3b549..6a94a44 100644 --- a/execute.c +++ b/execute.c @@ -1088,7 +1088,7 @@ int jq_compile_args(jq_state *jq, const char* str, jv args) { nerrors = builtins_bind(jq, &program); if (nerrors == 0) { - nerrors = block_compile(program, &jq->bc); + nerrors = block_compile(program, &jq->bc, locations); } } if (nerrors) -- 2.40.0