]> granicus.if.org Git - jq/commitdiff
Error on bytecodes longer than 0xFFFF (fix #269)
authorDavid Tolnay <dtolnay@gmail.com>
Sat, 25 Jul 2015 15:53:28 +0000 (08:53 -0700)
committerDavid Tolnay <dtolnay@gmail.com>
Sun, 26 Jul 2015 23:19:20 +0000 (16:19 -0700)
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
compile.h
execute.c

index 407e9f056d779a8b02ff567f97f2ae9f2da39461..6988d27c6b55354e4736272ad65033a90d5efd05 100644 (file)
--- 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);
index 2ef193efec770a89d683734d2d633883f84540bd..baec373efa1955ba73f3744991b843b06b34b756 100644 (file)
--- 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);
 
index 9f3b5499679643ab24719604988fff47ece5e900..6a94a442808846396b730406d7a6c4e0f41d2686 100644 (file)
--- 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)