summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-compiler/core
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2017-06-05 13:16:56 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2017-06-05 13:18:31 +0900
commitfc7096f18ac48fd92323ea75b8ee541748bff78b (patch)
treee9854b414d50e67eb394243c3fbde718ed6056a6 /mrbgems/mruby-compiler/core
parent788cea2b43963a87bf1c4e3c42e30cc2b25ca508 (diff)
downloadmruby-fc7096f18ac48fd92323ea75b8ee541748bff78b.tar.gz
mruby-fc7096f18ac48fd92323ea75b8ee541748bff78b.zip
Limit recursion level of `codegen()`; fix #3690
Diffstat (limited to 'mrbgems/mruby-compiler/core')
-rw-r--r--mrbgems/mruby-compiler/core/codegen.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c
index 3c13d23a6..174be4196 100644
--- a/mrbgems/mruby-compiler/core/codegen.c
+++ b/mrbgems/mruby-compiler/core/codegen.c
@@ -19,6 +19,10 @@
#include <mruby/re.h>
#include <mruby/throw.h>
+#ifndef MRB_CODEGEN_LEVEL_MAX
+#define MRB_CODEGEN_LEVEL_MAX 1024
+#endif
+
typedef mrb_ast_node node;
typedef struct mrb_parser_state parser_state;
@@ -73,6 +77,8 @@ typedef struct scope {
int debug_start_pos;
uint16_t filename_index;
parser_state* parser;
+
+ int rlev; /* recursion levels */
} codegen_scope;
static codegen_scope* scope_new(mrb_state *mrb, codegen_scope *prev, node *lv);
@@ -1243,6 +1249,7 @@ static void
codegen(codegen_scope *s, node *tree, int val)
{
int nt;
+ int rlev = s->rlev;
if (!tree) {
if (val) {
@@ -1252,6 +1259,10 @@ codegen(codegen_scope *s, node *tree, int val)
return;
}
+ s->rlev++;
+ if (s->rlev > MRB_CODEGEN_LEVEL_MAX) {
+ codegen_error(s, "too complex expression");
+ }
if (s->irep && s->filename_index != tree->filename_index) {
s->irep->filename = mrb_parser_get_filename(s->parser, s->filename_index);
mrb_debug_info_append_file(s->mrb, s->irep, s->debug_start_pos, s->pc);
@@ -1280,7 +1291,7 @@ codegen(codegen_scope *s, node *tree, int val)
int onerr, noexc, exend, pos1, pos2, tmp;
struct loopinfo *lp;
- if (tree->car == NULL) return;
+ if (tree->car == NULL) goto exit;
onerr = genop(s, MKOP_Bx(OP_ONERR, 0));
lp = loop_push(s, LOOP_BEGIN);
lp->pc1 = onerr;
@@ -1409,18 +1420,18 @@ codegen(codegen_scope *s, node *tree, int val)
if (!tree->car) {
codegen(s, e, val);
- return;
+ goto exit;
}
switch ((intptr_t)tree->car->car) {
case NODE_TRUE:
case NODE_INT:
case NODE_STR:
codegen(s, tree->cdr->car, val);
- return;
+ goto exit;
case NODE_FALSE:
case NODE_NIL:
codegen(s, e, val);
- return;
+ goto exit;
}
codegen(s, tree->car, VAL);
pop();
@@ -1881,7 +1892,7 @@ codegen(codegen_scope *s, node *tree, int val)
gen_assignment(s, tree->car, cursp(), val);
}
dispatch(s, pos);
- return;
+ goto exit;
}
codegen(s, tree->cdr->cdr->car, VAL);
push(); pop();
@@ -2764,6 +2775,8 @@ codegen(codegen_scope *s, node *tree, int val)
default:
break;
}
+ exit:
+ s->rlev = rlev;
}
static void
@@ -2855,6 +2868,8 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *lv)
p->parser = prev->parser;
p->filename_index = prev->filename_index;
+ p->rlev = prev->rlev+1;
+
return p;
}