From 45aadd7e604c886ba7b96c69fa797a8e2937c711 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 11 Nov 2016 22:49:23 +0900 Subject: HEREDOC could fail with NUL terminated lines; fix#3244 --- mrbgems/mruby-compiler/core/parse.y | 2 ++ 1 file changed, 2 insertions(+) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 426c262fb..76fb398e2 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -3907,6 +3907,8 @@ parse_string(parser_state *p) int end = (intptr_t)p->lex_strterm->cdr->cdr->cdr; parser_heredoc_info *hinf = (type & STR_FUNC_HEREDOC) ? parsing_heredoc_inf(p) : NULL; + if (beg == 0) beg = -3; /* should never happen */ + if (end == 0) end = -3; newtok(p); while ((c = nextc(p)) != end || nest_level != 0) { if (hinf && (c == '\n' || c < 0)) { -- cgit v1.2.3 From 185dad3a6eaf24e106c515bb580807e2b41e1f66 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 11 Nov 2016 22:50:41 +0900 Subject: node_dump() to print NODE_HEREDOC terminator --- mrbgems/mruby-compiler/core/parse.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 76fb398e2..b23016bd3 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -6506,7 +6506,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset) break; case NODE_HEREDOC: - printf("NODE_HEREDOC:\n"); + printf("NODE_HEREDOC (<<%s):\n", ((parser_heredoc_info*)tree)->term); mrb_parser_dump(mrb, ((parser_heredoc_info*)tree)->doc, offset+1); break; -- cgit v1.2.3 From 752ca514f6e3d9435a8af345fa2481e733a5ddca Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 11 Nov 2016 22:51:48 +0900 Subject: do not dump_node if parser failed --- mrbgems/mruby-compiler/core/parse.y | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index b23016bd3..90b8812b9 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -5479,7 +5479,10 @@ mrb_parser_parse(parser_state *p, mrbc_context *c) p->lex_strterm = NULL; parser_init_cxt(p, c); - yyparse(p); + if (yyparse(p) != 0 || p->nerr > 0) { + p->tree = 0; + return; + } if (!p->tree) { p->tree = new_nil(p); } -- cgit v1.2.3 From 669bbc70b0553b68483c8d7eff8c31a602f283e9 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 23 Nov 2016 21:08:35 +0900 Subject: codegen_scope should not keep old iseq ptr from irep --- mrbgems/mruby-compiler/core/codegen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 9b064b867..85ca21dd4 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -2713,7 +2713,7 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *lv) p->icapa = 1024; p->iseq = (mrb_code*)mrb_malloc(mrb, sizeof(mrb_code)*p->icapa); - p->irep->iseq = p->iseq; + p->irep->iseq = NULL; p->pcapa = 32; p->irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa); -- cgit v1.2.3 From dc4be19aab7df7b3d31102a68c4ed12c63a5814c Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 24 Nov 2016 10:01:03 +0900 Subject: Add forgotten loop_pop() in NODE_OP_ASGN codegen --- mrbgems/mruby-compiler/core/codegen.c | 1 + 1 file changed, 1 insertion(+) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 85ca21dd4..6d3ece9aa 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -1746,6 +1746,7 @@ codegen(codegen_scope *s, node *tree, int val) genop(s, MKOP_A(OP_RESCUE, exc)); genop(s, MKOP_A(OP_LOADF, exc)); dispatch(s, noexc); + loop_pop(s, NOVAL); } else if ((intptr_t)tree->car->car == NODE_CALL) { node *n = tree->car->cdr; -- cgit v1.2.3 From 1c9593954bfcdcd1c99732eb572c3995228d8fbb Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 24 Nov 2016 10:32:28 +0900 Subject: Add "void value expression" check to the parser. --- mrbgems/mruby-compiler/core/parse.y | 78 ++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 26 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 90b8812b9..ea7f809f3 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -41,6 +41,7 @@ static void yyerror(parser_state *p, const char *s); static void yywarn(parser_state *p, const char *s); static void yywarning(parser_state *p, const char *s); static void backref_error(parser_state *p, node *n); +static void void_expr_error(parser_state *p, node *n); static void tokadd(parser_state *p, int32_t c); #define identchar(c) (ISALNUM(c) || (c) == '_' || !ISASCII(c)) @@ -1097,7 +1098,7 @@ heredoc_end(parser_state *p) %type literal numeric cpath symbol %type top_compstmt top_stmts top_stmt %type bodystmt compstmt stmts stmt expr arg primary command command_call method_call -%type expr_value arg_value arg_rhs primary_value +%type expr_value arg0 arg_rhs primary_value %type if_tail opt_else case_body cases opt_rescue exc_list exc_var opt_ensure %type args call_args opt_call_args %type paren_args opt_paren_args variable @@ -1322,7 +1323,7 @@ stmt : keyword_alias fsym {p->lstate = EXPR_FNAME;} fsym { $$ = new_asgn(p, $1, new_array(p, $3)); } - | mlhs '=' arg_value + | mlhs '=' arg { $$ = new_masgn(p, $1, $3); } @@ -1395,13 +1396,16 @@ expr : command_call { $$ = call_uni_op(p, cond($2), "!"); } - | arg + | arg0 ; expr_value : expr { if (!$1) $$ = new_nil(p); - else $$ = $1; + else { + void_expr_error(p, $1); + $$ = $1; + } } ; @@ -1734,7 +1738,7 @@ reswords : keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__ | keyword_while | keyword_until ; -arg : lhs '=' arg_rhs +arg0 : lhs '=' arg_rhs { $$ = new_asgn(p, $1, $3); } @@ -1907,10 +1911,13 @@ arg : lhs '=' arg_rhs } ; -arg_value : arg +arg : arg0 { - $$ = $1; - if (!$$) $$ = new_nil(p); + if (!$1) $$ = new_nil(p); + else { + void_expr_error(p, $1); + $$ = $1; + } } ; @@ -1931,7 +1938,7 @@ aref_args : none } ; -arg_rhs : arg %prec tOP_ASGN +arg_rhs : arg %prec tOP_ASGN | arg modifier_rescue arg { $$ = new_mod_rescue(p, $1, $3); @@ -2005,7 +2012,7 @@ command_args : { } ; -block_arg : tAMPER arg_value +block_arg : tAMPER arg { $$ = new_block_arg(p, $2); } @@ -2021,43 +2028,43 @@ opt_block_arg : ',' block_arg } ; -args : arg_value +args : arg { $$ = cons($1, 0); NODE_LINENO($$, $1); } - | tSTAR arg_value + | tSTAR arg { $$ = cons(new_splat(p, $2), 0); NODE_LINENO($$, $2); } - | args ',' arg_value + | args ',' arg { $$ = push($1, $3); } - | args ',' tSTAR arg_value + | args ',' tSTAR arg { $$ = push($1, new_splat(p, $4)); } - | args ',' heredoc_bodies arg_value + | args ',' heredoc_bodies arg { $$ = push($1, $4); } - | args ',' heredoc_bodies tSTAR arg_value + | args ',' heredoc_bodies tSTAR arg { $$ = push($1, new_splat(p, $5)); } ; -mrhs : args ',' arg_value +mrhs : args ',' arg { $$ = push($1, $3); } - | args ',' tSTAR arg_value + | args ',' tSTAR arg { $$ = push($1, new_splat(p, $4)); } - | tSTAR arg_value + | tSTAR arg { $$ = list1(new_splat(p, $2)); } @@ -2688,7 +2695,7 @@ opt_rescue : keyword_rescue exc_list exc_var then | none ; -exc_list : arg_value +exc_list : arg { $$ = list1($1); } @@ -3115,7 +3122,7 @@ f_opt_asgn : tIDENTIFIER '=' } ; -f_opt : f_opt_asgn arg_value +f_opt : f_opt_asgn arg { $$ = cons(nsym($1), $2); } @@ -3233,23 +3240,23 @@ assocs : assoc } ; -assoc : arg_value tASSOC arg_value +assoc : arg tASSOC arg { $$ = cons($1, $3); } - | tLABEL arg_value + | tLABEL arg { $$ = cons(new_sym(p, $1), $2); } - | tLABEL_END arg_value + | tLABEL_END arg { $$ = cons(new_sym(p, new_strsym(p, $1)), $2); } - | tSTRING_BEG tLABEL_END arg_value + | tSTRING_BEG tLABEL_END arg { $$ = cons(new_sym(p, new_strsym(p, $2)), $3); } - | tSTRING_BEG string_rep tLABEL_END arg_value + | tSTRING_BEG string_rep tLABEL_END arg { $$ = cons(new_dsym(p, push($2, $3)), $4); } @@ -3430,6 +3437,25 @@ backref_error(parser_state *p, node *n) } } +static void +void_expr_error(parser_state *p, node *n) +{ + int c; + + c = (int)(intptr_t)n->car; + switch (c) { + case NODE_BREAK: + case NODE_RETURN: + case NODE_NEXT: + case NODE_REDO: + case NODE_RETRY: + yyerror(p, "void value expression"); + break; + default: + break; + } +} + static void pushback(parser_state *p, int c); static mrb_bool peeks(parser_state *p, const char *s); static mrb_bool skips(parser_state *p, const char *s); -- cgit v1.2.3 From 227daa881137d5251e03eea0883b9b574a1f064e Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 24 Nov 2016 11:22:54 +0900 Subject: Relax 'void value expression' check that was too strict --- mrbgems/mruby-compiler/core/parse.y | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index ea7f809f3..0ff7d819c 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -1098,7 +1098,7 @@ heredoc_end(parser_state *p) %type literal numeric cpath symbol %type top_compstmt top_stmts top_stmt %type bodystmt compstmt stmts stmt expr arg primary command command_call method_call -%type expr_value arg0 arg_rhs primary_value +%type expr_value arg_rhs primary_value %type if_tail opt_else case_body cases opt_rescue exc_list exc_var opt_ensure %type args call_args opt_call_args %type paren_args opt_paren_args variable @@ -1396,7 +1396,7 @@ expr : command_call { $$ = call_uni_op(p, cond($2), "!"); } - | arg0 + | arg ; expr_value : expr @@ -1738,7 +1738,7 @@ reswords : keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__ | keyword_while | keyword_until ; -arg0 : lhs '=' arg_rhs +arg : lhs '=' arg_rhs { $$ = new_asgn(p, $1, $3); } @@ -1911,16 +1911,6 @@ arg0 : lhs '=' arg_rhs } ; -arg : arg0 - { - if (!$1) $$ = new_nil(p); - else { - void_expr_error(p, $1); - $$ = $1; - } - } - ; - aref_args : none | args trailer { @@ -1939,8 +1929,14 @@ aref_args : none ; arg_rhs : arg %prec tOP_ASGN + { + void_expr_error(p, $1); + $$ = $1; + } | arg modifier_rescue arg { + void_expr_error(p, $1); + void_expr_error(p, $3); $$ = new_mod_rescue(p, $1, $3); } ; @@ -2030,42 +2026,51 @@ opt_block_arg : ',' block_arg args : arg { + void_expr_error(p, $1); $$ = cons($1, 0); NODE_LINENO($$, $1); } | tSTAR arg { + void_expr_error(p, $2); $$ = cons(new_splat(p, $2), 0); NODE_LINENO($$, $2); } | args ',' arg { + void_expr_error(p, $3); $$ = push($1, $3); } | args ',' tSTAR arg { + void_expr_error(p, $4); $$ = push($1, new_splat(p, $4)); } | args ',' heredoc_bodies arg { + void_expr_error(p, $4); $$ = push($1, $4); } | args ',' heredoc_bodies tSTAR arg { + void_expr_error(p, $5); $$ = push($1, new_splat(p, $5)); } ; mrhs : args ',' arg { + void_expr_error(p, $3); $$ = push($1, $3); } | args ',' tSTAR arg { + void_expr_error(p, $4); $$ = push($1, new_splat(p, $4)); } | tSTAR arg { + void_expr_error(p, $2); $$ = list1(new_splat(p, $2)); } ; -- cgit v1.2.3 From 22f73250dbe38dd1b5878143b81284f510d91923 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 24 Nov 2016 21:25:27 +0900 Subject: redo should work well in for statement; fix #3275 --- mrbgems/mruby-compiler/core/codegen.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 6d3ece9aa..0c84dd558 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -588,9 +588,6 @@ for_body(codegen_scope *s, node *tree) push(); /* push for a block parameter */ - lp = loop_push(s, LOOP_FOR); - lp->pc1 = new_label(s); - /* generate loop variable */ n2 = tree->car; genop(s, MKOP_Ax(OP_ENTER, 0x40000)); @@ -600,6 +597,11 @@ for_body(codegen_scope *s, node *tree) else { gen_vmassignment(s, n2, 1, VAL); } + /* construct loop */ + lp = loop_push(s, LOOP_FOR); + lp->pc2 = new_label(s); + + /* loop body */ codegen(s, tree->cdr->cdr->car, VAL); pop(); if (s->pc > 0) { -- cgit v1.2.3 From 73e4f069becaf69707b990d658b34155f8973508 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Fri, 18 Nov 2016 16:17:40 -0500 Subject: Fix nested empty heredoc causing segfault As reported by https://hackerone.com/jpenalbae --- mrbgems/mruby-compiler/core/codegen.c | 6 +++++- mrbgems/mruby-compiler/core/parse.y | 2 +- test/t/codegen.rb | 10 ++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 test/t/codegen.rb (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 0c84dd558..13091a6f5 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -2285,7 +2285,11 @@ codegen(codegen_scope *s, node *tree, int val) if (val) { node *n = tree; - if (!n) break; + if (!n) { + genop(s, MKOP_A(OP_LOADNIL, cursp())); + push(); + break; + } codegen(s, n->car, VAL); n = n->cdr; while (n) { diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 0ff7d819c..c44669f45 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -6541,7 +6541,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset) case NODE_HEREDOC: printf("NODE_HEREDOC (<<%s):\n", ((parser_heredoc_info*)tree)->term); - mrb_parser_dump(mrb, ((parser_heredoc_info*)tree)->doc, offset+1); + dump_recur(mrb, ((parser_heredoc_info*)tree)->doc, offset+1); break; default: diff --git a/test/t/codegen.rb b/test/t/codegen.rb new file mode 100644 index 000000000..2f44ca247 --- /dev/null +++ b/test/t/codegen.rb @@ -0,0 +1,10 @@ +## +# Codegen tests + +assert('nested empty heredoc') do + _, a = nil, < Date: Thu, 17 Nov 2016 11:12:35 -0500 Subject: Fix segfault on method call with exactly 127 arguments Reported by https://hackerone.com/dkasak --- mrbgems/mruby-compiler/core/codegen.c | 8 +++++--- test/t/codegen.rb | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 test/t/codegen.rb (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 0c84dd558..a36984dea 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -772,6 +772,8 @@ attrsym(codegen_scope *s, mrb_sym a) return mrb_intern(s->mrb, name2, len+1); } +#define CALL_MAXARGS 127 + static int gen_values(codegen_scope *s, node *t, int val) { @@ -780,7 +782,9 @@ gen_values(codegen_scope *s, node *t, int val) while (t) { is_splat = (intptr_t)t->car->car == NODE_SPLAT; /* splat mode */ - if (n >= 127 || is_splat) { + if ( + n >= CALL_MAXARGS - 1 /* need to subtract one because vm.c expects an array if n == CALL_MAXARGS */ + || is_splat) { if (val) { if (is_splat && n == 0 && (intptr_t)t->car->cdr->car == NODE_ARRAY) { codegen(s, t->car->cdr, VAL); @@ -831,8 +835,6 @@ gen_values(codegen_scope *s, node *t, int val) return n; } -#define CALL_MAXARGS 127 - static void gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe) { diff --git a/test/t/codegen.rb b/test/t/codegen.rb new file mode 100644 index 000000000..0690cef06 --- /dev/null +++ b/test/t/codegen.rb @@ -0,0 +1,17 @@ +## +# Codegen tests + +assert('method call with exactly 127 arguments') do + def args_to_ary(*args) + args + end + + assert_equal [0]*127, args_to_ary( + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + ) +end -- cgit v1.2.3 From 12539825773ddb13fac38091d13341b816ac23fa Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Mon, 14 Nov 2016 15:07:07 -0500 Subject: Fix codegen issue causing misaligned register Reported by https://hackerone.com/haquaman --- mrbgems/mruby-compiler/core/codegen.c | 2 ++ test/t/codegen.rb | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 test/t/codegen.rb (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 0c84dd558..75adbefdd 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -2024,6 +2024,7 @@ codegen(codegen_scope *s, node *tree, int val) } genop(s, MKOP_sBx(OP_JMP, s->loop->pc2 - s->pc)); } + if (val) push(); break; case NODE_RETRY: @@ -2058,6 +2059,7 @@ codegen(codegen_scope *s, node *tree, int val) genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc)); } } + if (val) push(); } break; diff --git a/test/t/codegen.rb b/test/t/codegen.rb new file mode 100644 index 000000000..89ad94bae --- /dev/null +++ b/test/t/codegen.rb @@ -0,0 +1,20 @@ +## +# Codegen tests + +assert('codegen absorbs arguments to redo and retry if they are the argument of a call') do + assert_nothing_raised do + a=*"1", case nil + when 1 + redo | + 1 + end + end + + assert_nothing_raised do + a=*"1", case nil + when 1 + retry | + 1 + end + end +end -- cgit v1.2.3 From 71641bbf732ab8cbadf8a07e20b2a939b0e3b82b Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Mon, 14 Nov 2016 17:28:18 -0500 Subject: Fix segfault caused by empty condition in ternary Reported by https://hackerone.com/jpenalbae --- mrbgems/mruby-compiler/core/codegen.c | 4 ++++ test/t/codegen.rb | 6 ++++++ 2 files changed, 10 insertions(+) create mode 100644 test/t/codegen.rb (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 0c84dd558..71b1dcc6f 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -1362,6 +1362,10 @@ codegen(codegen_scope *s, node *tree, int val) int pos1, pos2; node *e = tree->cdr->cdr->car; + if (!tree->car) { + codegen(s, e, val); + return; + } switch ((intptr_t)tree->car->car) { case NODE_TRUE: case NODE_INT: diff --git a/test/t/codegen.rb b/test/t/codegen.rb new file mode 100644 index 000000000..99d6dbe66 --- /dev/null +++ b/test/t/codegen.rb @@ -0,0 +1,6 @@ +## +# Codegen tests + +assert('empty condition in ternary expression parses correctly') do + assert_equal () ? 1 : 2, 2 +end -- cgit v1.2.3 From 964427f82c5a8556daf4448b47cc65fb6d2a94b8 Mon Sep 17 00:00:00 2001 From: Francis Bogsanyi Date: Thu, 17 Nov 2016 12:59:27 -0500 Subject: Fix unsafe peephole optimization Reported by https://hackerone.com/dkasak --- mrbgems/mruby-compiler/core/codegen.c | 6 ++++-- test/t/codegen.rb | 11 +++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 test/t/codegen.rb (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 0c84dd558..39d62348a 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -1798,8 +1798,10 @@ codegen(codegen_scope *s, node *tree, int val) int pos; pop(); - if (val && vsp >= 0) { - genop(s, MKOP_AB(OP_MOVE, vsp, cursp())); + if (val) { + if (vsp >= 0) { + genop(s, MKOP_AB(OP_MOVE, vsp, cursp())); + } pos = genop(s, MKOP_AsBx(name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0)); } else { diff --git a/test/t/codegen.rb b/test/t/codegen.rb new file mode 100644 index 000000000..f910d37fb --- /dev/null +++ b/test/t/codegen.rb @@ -0,0 +1,11 @@ +## +# Codegen tests + +assert('peephole optimization does not eliminate move whose result is reused') do + assert_raise LocalJumpError do + def method + yield + end + method(&a &&= 0) + end +end -- cgit v1.2.3 From 27ceb848180463e66e080d13c3a96b1e56dbddbd Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 27 Nov 2016 22:43:46 +0900 Subject: parse.y: use opt_paren_args to simplify yield rule --- mrbgems/mruby-compiler/core/parse.y | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index c44669f45..3a14b4fcc 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -2137,17 +2137,9 @@ primary : literal { $$ = new_return(p, 0); } - | keyword_yield '(' call_args rparen + | keyword_yield opt_paren_args { - $$ = new_yield(p, $3); - } - | keyword_yield '(' rparen - { - $$ = new_yield(p, 0); - } - | keyword_yield - { - $$ = new_yield(p, 0); + $$ = new_yield(p, $2); } | keyword_not '(' expr rparen { -- cgit v1.2.3 From 523c267020787c3545bd72f27362cf8727372c0d Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Mon, 28 Nov 2016 13:37:20 -0500 Subject: Interpret argument in 'f ()' as nil instead of nothing --- mrbgems/mruby-compiler/bintest/mrbc.rb | 9 +++++++++ mrbgems/mruby-compiler/core/parse.y | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/bintest/mrbc.rb b/mrbgems/mruby-compiler/bintest/mrbc.rb index e4dc6a9a8..e27365edb 100644 --- a/mrbgems/mruby-compiler/bintest/mrbc.rb +++ b/mrbgems/mruby-compiler/bintest/mrbc.rb @@ -10,3 +10,12 @@ assert('Compiling multiple files without new line in last line. #2361') do assert_equal "#{cmd('mrbc')}:#{a.path}:Syntax OK", result.chomp assert_equal 0, $?.exitstatus end + +assert('parsing function with void argument') do + a, out = Tempfile.new('a.rb'), Tempfile.new('out.mrb') + a.write('f ()') + a.flush + result = `#{cmd('mrbc')} -c -o #{out.path} #{a.path} 2>&1` + assert_equal "#{cmd('mrbc')}:#{a.path}:Syntax OK", result.chomp + assert_equal 0, $?.exitstatus +end diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 3a14b4fcc..9f6914104 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -2109,7 +2109,7 @@ primary : literal } | tLPAREN_ARG {p->lstate = EXPR_ENDARG;} rparen { - $$ = 0; + $$ = new_nil(p); } | tLPAREN compstmt ')' { -- cgit v1.2.3 From 8461a31cb491f272524d14a9e54fcc9fae7a22c1 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 30 Nov 2016 13:04:50 +0900 Subject: Fixed too much void_expr_error(); fix #3307 --- mrbgems/mruby-compiler/core/parse.y | 1 - 1 file changed, 1 deletion(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 9f6914104..ef522d239 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -1936,7 +1936,6 @@ arg_rhs : arg %prec tOP_ASGN | arg modifier_rescue arg { void_expr_error(p, $1); - void_expr_error(p, $3); $$ = new_mod_rescue(p, $1, $3); } ; -- cgit v1.2.3 From fed40b44b8ec56c977b85be65ff460dcf713dc3c Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 1 Dec 2016 11:30:07 +0900 Subject: Extract read_escape_unicode from read_escape --- mrbgems/mruby-compiler/core/parse.y | 88 +++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 43 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index ef522d239..65b89bed3 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -3752,6 +3752,44 @@ scan_hex(const int *start, int len, int *retlen) return retval; } +static int32_t +read_escape_unicode(parser_state *p, size_t limit) +{ + int32_t c; + int buf[9]; + int i; + + /* Look for opening brace */ + i = 0; + buf[0] = nextc(p); + if (buf[0] < 0) goto eof; + if (ISXDIGIT(buf[0])) { + /* \uxxxx form */ + for (i=1; i 0x10FFFF || (c & 0xFFFFF800) == 0xD800) { + yyerror(p, "Invalid Unicode code point"); + return -1; + } + return c; +} + /* Return negative to indicate Unicode code point */ static int32_t read_escape(parser_state *p) @@ -3824,53 +3862,17 @@ read_escape(parser_state *p) return c; case 'u': /* Unicode */ - { - int buf[9]; - int i; - - /* Look for opening brace */ - i = 0; - buf[0] = nextc(p); - if (buf[0] < 0) goto eof; - if (buf[0] == '{') { + if (peek(p, '{')) { /* \u{xxxxxxxx} form */ - for (i=0; i<9; i++) { - buf[i] = nextc(p); - if (buf[i] < 0) goto eof; - if (buf[i] == '}') { - break; - } - else if (!ISXDIGIT(buf[i])) { - yyerror(p, "Invalid escape character syntax"); - pushback(p, buf[i]); - return 0; - } - } - } - else if (ISXDIGIT(buf[0])) { - /* \uxxxx form */ - for (i=1; i<4; i++) { - buf[i] = nextc(p); - if (buf[i] < 0) goto eof; - if (!ISXDIGIT(buf[i])) { - pushback(p, buf[i]); - break; - } - } + nextc(p); + c = read_escape_unicode(p, 8); + if (c < 0) return 0; + if (nextc(p) != '}') goto eof; } else { - pushback(p, buf[0]); - } - c = scan_hex(buf, i, &i); - if (i == 0) { - yyerror(p, "Invalid escape character syntax"); - return 0; + c = read_escape_unicode(p, 4); + if (c < 0) return 0; } - if (c < 0 || c > 0x10FFFF || (c & 0xFFFFF800) == 0xD800) { - yyerror(p, "Invalid Unicode code point"); - return 0; - } - } return -c; case 'b':/* backspace */ -- cgit v1.2.3 From 0f08914ac0d433545a4224ee1c3f8d3eb8d51e68 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 1 Dec 2016 14:37:59 +0900 Subject: Support multiple elements \u syntax --- mrbgems/mruby-compiler/core/parse.y | 14 ++++++++++++++ test/t/unicode.rb | 4 ++++ 2 files changed, 18 insertions(+) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 65b89bed3..f0c45b85b 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -3995,6 +3995,20 @@ parse_string(parser_state *p) tokadd(p, '\\'); tokadd(p, c); } + else if (c == 'u' && peek(p, '{')) { + /* \u{xxxx xxxx xxxx} form */ + nextc(p); + while (1) { + do c = nextc(p); while (ISSPACE(c)); + if (c == '}') break; + pushback(p, c); + c = read_escape_unicode(p, 8); + if (c < 0) break; + tokadd(p, -c); + } + if (hinf) + hinf->line_head = FALSE; + } else { pushback(p, c); tokadd(p, read_escape(p)); diff --git a/test/t/unicode.rb b/test/t/unicode.rb index b8c54ca66..8622ae08a 100644 --- a/test/t/unicode.rb +++ b/test/t/unicode.rb @@ -33,3 +33,7 @@ assert('braced \u notation test') do assert_equal("\xF0\x90\x80\x80", "\u{10000}") assert_equal("\xF4\x8F\xBF\xBF", "\u{10FFFF}") end + +assert('braced multiple \u notation test') do + assert_equal("ABC", "\u{41 42 43}") +end -- cgit v1.2.3 From 2cca9d368815e9c83a7489c40d69937d68cb43a2 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 1 Dec 2016 18:49:39 +0900 Subject: avoid comparison between signed and unsigned integer; ref #3312 --- mrbgems/mruby-compiler/core/parse.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index f0c45b85b..bf893fb37 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -3753,7 +3753,7 @@ scan_hex(const int *start, int len, int *retlen) } static int32_t -read_escape_unicode(parser_state *p, size_t limit) +read_escape_unicode(parser_state *p, int limit) { int32_t c; int buf[9]; -- cgit v1.2.3 From fe362c1f2649c9c502d9a5998ef8c4c94893f3ea Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Thu, 24 Nov 2016 13:31:47 -0500 Subject: Fix segfault when using result of rest assignment Reported by https://hackerone.com/haquaman --- mrbgems/mruby-compiler/core/codegen.c | 4 +++- test/t/codegen.rb | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 553baa116..2c75c8aed 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -1061,7 +1061,9 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val) n++; } } - push(); + if (!val) { + push(); + } } } diff --git a/test/t/codegen.rb b/test/t/codegen.rb index 1ac689a82..bb0f5c306 100644 --- a/test/t/codegen.rb +++ b/test/t/codegen.rb @@ -54,3 +54,12 @@ A B assert_equal "\n", a end + +assert('splat in case splat') do + a = *case + when 0 + * = 1 + end + + assert_equal [1], a +end -- cgit v1.2.3 From c029c6c4440c730c1ed5b0d6a10e81cebe23ac9c Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 3 Dec 2016 14:50:36 +0900 Subject: codegen: avoid unnecessary OP_MOVE after CASE --- mrbgems/mruby-compiler/core/codegen.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 2c75c8aed..414ca2627 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -1520,7 +1520,9 @@ codegen(codegen_scope *s, node *tree, int val) genop(s, MKOP_A(OP_LOADNIL, cursp())); if (pos3) dispatch_linked(s, pos3); if (head) pop(); - genop(s, MKOP_AB(OP_MOVE, cursp(), pos)); + if (cursp() != pos) { + genop(s, MKOP_AB(OP_MOVE, cursp(), pos)); + } push(); } else { -- cgit v1.2.3 From 6b84ff4a443d55a5b94d3bfa8b0a7ba9ee9646dc Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 3 Dec 2016 16:21:15 +0900 Subject: Print NODE_SCALL (&.) from mrb_parser_dump() --- mrbgems/mruby-compiler/core/parse.y | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index bf893fb37..dc09d33ff 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -6067,7 +6067,17 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset) case NODE_FCALL: case NODE_CALL: - printf("NODE_CALL:\n"); + case NODE_SCALL: + switch (nodetype) { + case NODE_FCALL: + printf("NODE_FCALL:\n"); break; + case NODE_CALL: + printf("NODE_CALL(.):\n"); break; + case NODE_SCALL: + printf("NODE_SCALL(&.):\n"); break; + default: + break; + } mrb_parser_dump(mrb, tree->car, offset+1); dump_prefix(tree, offset+1); printf("method='%s' (%d)\n", -- cgit v1.2.3 From f6d199919d433adad03f2eb27757503bc61a5507 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 3 Dec 2016 16:38:43 +0900 Subject: Needed to apply block from safe-navigation operators; fix #3310 --- mrbgems/mruby-compiler/core/parse.y | 1 + 1 file changed, 1 insertion(+) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index dc09d33ff..e81d191d9 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -871,6 +871,7 @@ call_with_block(parser_state *p, node *a, node *b) break; case NODE_CALL: case NODE_FCALL: + case NODE_SCALL: n = a->cdr->cdr->cdr; if (!n->car) n->car = cons(0, b); else { -- cgit v1.2.3 From a0fbc46ccd3e129532b05a9fe4f13f42a3c349b2 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 3 Dec 2016 18:47:04 +0900 Subject: Import locale insensitive strtod() from Ruby1.8; fix #3270 The function was renamed to `mrb_float_read(const char*, char**)`. --- include/mruby/value.h | 5 +- mrbgems/mruby-compiler/core/codegen.c | 4 +- mrbgems/mruby-compiler/core/parse.y | 2 +- src/string.c | 242 +++++++++++++++++++++++++++++++++- 4 files changed, 245 insertions(+), 8 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/include/mruby/value.h b/include/mruby/value.h index 61110e3dd..54d197f8f 100644 --- a/include/mruby/value.h +++ b/include/mruby/value.h @@ -62,12 +62,12 @@ struct mrb_state; # define MRB_PRIx PRIx32 #endif + +MRB_API double mrb_float_read(const char*, char**); #ifdef MRB_USE_FLOAT typedef float mrb_float; -# define str_to_mrb_float(buf) strtof(buf, NULL) #else typedef double mrb_float; -# define str_to_mrb_float(buf) strtod(buf, NULL) #endif #if defined _MSC_VER && _MSC_VER < 1900 @@ -85,7 +85,6 @@ MRB_API int mrb_msvc_snprintf(char *s, size_t n, const char *format, ...); # define isnan _isnan # define isinf(n) (!_finite(n) && !_isnan(n)) # define signbit(n) (_copysign(1.0, (n)) < 0.0) -# define strtof (float)strtod static const unsigned int IEEE754_INFINITY_BITS_SINGLE = 0x7F800000; # define INFINITY (*(float *)&IEEE754_INFINITY_BITS_SINGLE) # define NAN ((float)(INFINITY - INFINITY)) diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 414ca2627..b2cd12225 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -2211,7 +2211,7 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_FLOAT: if (val) { char *p = (char*)tree; - mrb_float f = str_to_mrb_float(p); + mrb_float f = mrb_float_read(p, NULL); int off = new_lit(s, mrb_float_value(s->mrb, f)); genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); @@ -2227,7 +2227,7 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_FLOAT: { char *p = (char*)tree; - mrb_float f = str_to_mrb_float(p); + mrb_float f = mrb_float_read(p, NULL); int off = new_lit(s, mrb_float_value(s->mrb, -f)); genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index e81d191d9..19cb88e5b 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -4912,7 +4912,7 @@ parser_yylex(parser_state *p) char *endp; errno = 0; - d = strtod(tok(p), &endp); + d = mrb_float_read(tok(p), &endp); if (d == 0 && endp == tok(p)) { yywarning_s(p, "corrupted float value %s", tok(p)); } diff --git a/src/string.c b/src/string.c index f47294291..e3a268f78 100644 --- a/src/string.c +++ b/src/string.c @@ -2286,7 +2286,7 @@ mrb_cstr_to_dbl(mrb_state *mrb, const char * p, mrb_bool badcheck) if (!badcheck && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { return 0.0; } - d = strtod(p, &end); + d = mrb_float_read(p, &end); if (p == end) { if (badcheck) { bad: @@ -2324,7 +2324,7 @@ bad: return 0.0; } - d = strtod(p, &end); + d = mrb_float_read(p, &end); if (badcheck) { if (!end || p == end) goto bad; while (*end && ISSPACE(*end)) end++; @@ -2749,3 +2749,241 @@ mrb_init_string(mrb_state *mrb) mrb_define_method(mrb, s, "freeze", mrb_str_freeze, MRB_ARGS_NONE()); } + +/* + * Source code for the "strtod" library procedure. + * + * Copyright (c) 1988-1993 The Regents of the University of California. + * Copyright (c) 1994 Sun Microsystems, Inc. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies. The University of California + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. + * + * RCS: @(#) $Id: strtod.c 11708 2007-02-12 23:01:19Z shyouhei $ + */ + +#include +#include +extern int errno; + +#ifndef __STDC__ +# ifdef __GNUC__ +# define const __const__ +# else +# define const +# endif +#endif + +static const int maxExponent = 511; /* Largest possible base 10 exponent. Any + * exponent larger than this will already + * produce underflow or overflow, so there's + * no need to worry about additional digits. + */ +static const double powersOf10[] = {/* Table giving binary powers of 10. Entry */ + 10., /* is 10^2^i. Used to convert decimal */ + 100., /* exponents into floating-point numbers. */ + 1.0e4, + 1.0e8, + 1.0e16, + 1.0e32, + 1.0e64, + 1.0e128, + 1.0e256 +}; + +double +mrb_float_read(const char *string, char **endPtr) +/* const char *string; A decimal ASCII floating-point number, + * optionally preceded by white space. + * Must have form "-I.FE-X", where I is the + * integer part of the mantissa, F is the + * fractional part of the mantissa, and X + * is the exponent. Either of the signs + * may be "+", "-", or omitted. Either I + * or F may be omitted, or both. The decimal + * point isn't necessary unless F is present. + * The "E" may actually be an "e". E and X + * may both be omitted (but not just one). + */ +/* char **endPtr; If non-NULL, store terminating character's + * address here. */ +{ + int sign, expSign = FALSE; + double fraction, dblExp; + const double *d; + register const char *p; + register int c; + int exp = 0; /* Exponent read from "EX" field. */ + int fracExp = 0; /* Exponent that derives from the fractional + * part. Under normal circumstatnces, it is + * the negative of the number of digits in F. + * However, if I is very long, the last digits + * of I get dropped (otherwise a long I with a + * large negative exponent could cause an + * unnecessary overflow on I alone). In this + * case, fracExp is incremented one for each + * dropped digit. */ + int mantSize; /* Number of digits in mantissa. */ + int decPt; /* Number of mantissa digits BEFORE decimal + * point. */ + const char *pExp; /* Temporarily holds location of exponent + * in string. */ + + /* + * Strip off leading blanks and check for a sign. + */ + + p = string; + while (isspace(*p)) { + p += 1; + } + if (*p == '-') { + sign = TRUE; + p += 1; + } else { + if (*p == '+') { + p += 1; + } + sign = FALSE; + } + + /* + * Count the number of digits in the mantissa (including the decimal + * point), and also locate the decimal point. + */ + + decPt = -1; + for (mantSize = 0; ; mantSize += 1) + { + c = *p; + if (!isdigit(c)) { + if ((c != '.') || (decPt >= 0)) { + break; + } + decPt = mantSize; + } + p += 1; + } + + /* + * Now suck up the digits in the mantissa. Use two integers to + * collect 9 digits each (this is faster than using floating-point). + * If the mantissa has more than 18 digits, ignore the extras, since + * they can't affect the value anyway. + */ + + pExp = p; + p -= mantSize; + if (decPt < 0) { + decPt = mantSize; + } else { + mantSize -= 1; /* One of the digits was the point. */ + } + if (mantSize > 18) { + fracExp = decPt - 18; + mantSize = 18; + } else { + fracExp = decPt - mantSize; + } + if (mantSize == 0) { + fraction = 0.0; + p = string; + goto done; + } else { + int frac1, frac2; + frac1 = 0; + for ( ; mantSize > 9; mantSize -= 1) + { + c = *p; + p += 1; + if (c == '.') { + c = *p; + p += 1; + } + frac1 = 10*frac1 + (c - '0'); + } + frac2 = 0; + for (; mantSize > 0; mantSize -= 1) + { + c = *p; + p += 1; + if (c == '.') { + c = *p; + p += 1; + } + frac2 = 10*frac2 + (c - '0'); + } + fraction = (1.0e9 * frac1) + frac2; + } + + /* + * Skim off the exponent. + */ + + p = pExp; + if ((*p == 'E') || (*p == 'e')) { + p += 1; + if (*p == '-') { + expSign = TRUE; + p += 1; + } else { + if (*p == '+') { + p += 1; + } + expSign = FALSE; + } + while (isdigit(*p)) { + exp = exp * 10 + (*p - '0'); + p += 1; + } + } + if (expSign) { + exp = fracExp - exp; + } else { + exp = fracExp + exp; + } + + /* + * Generate a floating-point number that represents the exponent. + * Do this by processing the exponent one bit at a time to combine + * many powers of 2 of 10. Then combine the exponent with the + * fraction. + */ + + if (exp < 0) { + expSign = TRUE; + exp = -exp; + } else { + expSign = FALSE; + } + if (exp > maxExponent) { + exp = maxExponent; + errno = ERANGE; + } + dblExp = 1.0; + for (d = powersOf10; exp != 0; exp >>= 1, d += 1) { + if (exp & 01) { + dblExp *= *d; + } + } + if (expSign) { + fraction /= dblExp; + } else { + fraction *= dblExp; + } + +done: + if (endPtr != NULL) { + *endPtr = (char *) p; + } + + if (sign) { + return -fraction; + } + return fraction; +} -- cgit v1.2.3 From 43512cc7bdb4949a24e310aa03e67a95c59b5f1b Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 5 Dec 2016 02:55:39 +0900 Subject: Reorganize heredoc rules; fix #3273 The following codes used to be SyntaxError: (1) a = <<-EOD; hello EOD (2) <<-EOD.bla begin k EOD end --- mrbgems/mruby-compiler/core/parse.y | 41 +++++++++++++++---------------------- 1 file changed, 16 insertions(+), 25 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 19cb88e5b..05b948f8e 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -1918,7 +1918,7 @@ aref_args : none $$ = $1; NODE_LINENO($$, $1); } - | args ',' assocs trailer + | args comma assocs trailer { $$ = push($1, new_hash(p, $3)); } @@ -1958,7 +1958,7 @@ opt_call_args : none $$ = cons($1,0); NODE_LINENO($$, $1); } - | args ',' assocs ',' + | args comma assocs ',' { $$ = cons(push($1, new_hash(p, $3)), 0); NODE_LINENO($$, $1); @@ -1985,7 +1985,7 @@ call_args : command $$ = cons(list1(new_hash(p, $1)), $2); NODE_LINENO($$, $1); } - | args ',' assocs opt_block_arg + | args comma assocs opt_block_arg { $$ = cons(push($1, new_hash(p, $3)), $4); NODE_LINENO($$, $1); @@ -2014,7 +2014,7 @@ block_arg : tAMPER arg } ; -opt_block_arg : ',' block_arg +opt_block_arg : comma block_arg { $$ = $2; } @@ -2024,6 +2024,10 @@ opt_block_arg : ',' block_arg } ; +comma : ',' + | ',' heredoc_bodies + ; + args : arg { void_expr_error(p, $1); @@ -2036,34 +2040,24 @@ args : arg $$ = cons(new_splat(p, $2), 0); NODE_LINENO($$, $2); } - | args ',' arg + | args comma arg { void_expr_error(p, $3); $$ = push($1, $3); } - | args ',' tSTAR arg + | args comma tSTAR arg { void_expr_error(p, $4); $$ = push($1, new_splat(p, $4)); } - | args ',' heredoc_bodies arg - { - void_expr_error(p, $4); - $$ = push($1, $4); - } - | args ',' heredoc_bodies tSTAR arg - { - void_expr_error(p, $5); - $$ = push($1, new_splat(p, $5)); - } ; -mrhs : args ',' arg +mrhs : args comma arg { void_expr_error(p, $3); $$ = push($1, $3); } - | args ',' tSTAR arg + | args comma tSTAR arg { void_expr_error(p, $4); $$ = push($1, new_splat(p, $4)); @@ -2787,10 +2781,6 @@ regexp : tREGEXP_BEG tREGEXP heredoc : tHEREDOC_BEG ; -opt_heredoc_bodies : /* none */ - | heredoc_bodies - ; - heredoc_bodies : heredoc_body | heredoc_bodies heredoc_body ; @@ -3312,11 +3302,12 @@ rbracket : opt_nl ']' trailer : /* none */ | nl - | ',' + | comma ; term : ';' {yyerrok;} | nl + | heredoc_body ; nl : '\n' @@ -3324,10 +3315,10 @@ nl : '\n' p->lineno++; p->column = 0; } - opt_heredoc_bodies + ; terms : term - | terms ';' {yyerrok;} + | terms term ; none : /* none */ -- cgit v1.2.3 From d56a19cbf526190de036130fe3a5bf14a0705ee2 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Fri, 2 Dec 2016 09:48:28 -0500 Subject: Don't generate code for NODE_NEGATE if the result isn't used Reported by https://hackerone.com/haquaman --- mrbgems/mruby-compiler/core/codegen.c | 4 ++++ test/t/codegen.rb | 10 ++++++++++ 2 files changed, 14 insertions(+) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index b2cd12225..891c4f62b 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -2223,6 +2223,10 @@ codegen(codegen_scope *s, node *tree, int val) { nt = (intptr_t)tree->car; tree = tree->cdr; + if (!val) { + codegen(s, tree, NOVAL); + break; + } switch (nt) { case NODE_FLOAT: { diff --git a/test/t/codegen.rb b/test/t/codegen.rb index bb0f5c306..bd360dbcb 100644 --- a/test/t/codegen.rb +++ b/test/t/codegen.rb @@ -63,3 +63,13 @@ assert('splat in case splat') do assert_equal [1], a end + +assert('negate literal register alignment') do + a = *case + when 0 + -0.0 + 2 + end + + assert_equal [2], a +end -- cgit v1.2.3 From 0360a744b5fae6c29d91ba9729b7445415b9e293 Mon Sep 17 00:00:00 2001 From: Tomasz Dąbrowski Date: Wed, 7 Dec 2016 21:12:59 +0100 Subject: Promote load_exec to mruby API as mrb_load_exec (fixes #3248) --- include/mruby/compile.h | 1 + mrbgems/mruby-compiler/core/parse.y | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/include/mruby/compile.h b/include/mruby/compile.h index 3ccaf9f6a..ebcb3f355 100644 --- a/include/mruby/compile.h +++ b/include/mruby/compile.h @@ -174,6 +174,7 @@ MRB_API struct mrb_parser_state* mrb_parse_file(mrb_state*,FILE*,mrbc_context*); MRB_API struct mrb_parser_state* mrb_parse_string(mrb_state*,const char*,mrbc_context*); MRB_API struct mrb_parser_state* mrb_parse_nstring(mrb_state*,const char*,int,mrbc_context*); MRB_API struct RProc* mrb_generate_code(mrb_state*, struct mrb_parser_state*); +MRB_API mrb_value mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c); /* program load functions */ #ifndef MRB_DISABLE_STDIO diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 05b948f8e..957ad5815 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -5692,8 +5692,8 @@ mrb_parse_string(mrb_state *mrb, const char *s, mrbc_context *c) return mrb_parse_nstring(mrb, s, strlen(s), c); } -static mrb_value -load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c) +MRB_API mrb_value +mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c) { struct RClass *target = mrb->object_class; struct RProc *proc; @@ -5752,7 +5752,7 @@ load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c) MRB_API mrb_value mrb_load_file_cxt(mrb_state *mrb, FILE *f, mrbc_context *c) { - return load_exec(mrb, mrb_parse_file(mrb, f, c), c); + return mrb_load_exec(mrb, mrb_parse_file(mrb, f, c), c); } MRB_API mrb_value @@ -5765,7 +5765,7 @@ mrb_load_file(mrb_state *mrb, FILE *f) MRB_API mrb_value mrb_load_nstring_cxt(mrb_state *mrb, const char *s, int len, mrbc_context *c) { - return load_exec(mrb, mrb_parse_nstring(mrb, s, len, c), c); + return mrb_load_exec(mrb, mrb_parse_nstring(mrb, s, len, c), c); } MRB_API mrb_value -- cgit v1.2.3 From c8da3c4df4f8cb6f6d00c70e75606c59f9888509 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Wed, 7 Dec 2016 11:22:30 -0500 Subject: Fix segfault when undef is called with exactly 127 arguments The issue is that when there are more than 126 arguments an array needs to be created to pass the arguments on with. Reported by https://hackerone.com/revskills --- mrbgems/mruby-compiler/core/codegen.c | 22 ++++++++++++++++++++-- test/t/codegen.rb | 10 ++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index b2cd12225..3cfd99d41 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -2560,13 +2560,31 @@ codegen(codegen_scope *s, node *tree, int val) genop(s, MKOP_A(OP_TCLASS, cursp())); push(); while (t) { - int symbol = new_msym(s, sym(t->car)); + int symbol; + if (num >= CALL_MAXARGS - 1) { + pop_n(num); + genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), num)); + while (t) { + symbol = new_msym(s, sym(t->car)); + push(); + genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol)); + pop(); + genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1)); + t = t->cdr; + } + num = CALL_MAXARGS; + break; + } + symbol = new_msym(s, sym(t->car)); genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol)); push(); t = t->cdr; num++; } - pop_n(num + 1); + pop(); + if (num < CALL_MAXARGS) { + pop_n(num); + } genop(s, MKOP_ABC(OP_SEND, cursp(), undef, num)); if (val) { push(); diff --git a/test/t/codegen.rb b/test/t/codegen.rb index bb0f5c306..3058a7fbc 100644 --- a/test/t/codegen.rb +++ b/test/t/codegen.rb @@ -63,3 +63,13 @@ assert('splat in case splat') do assert_equal [1], a end + +assert('undef with 127 or more arguments') do + assert_raise NameError do + undef + a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, + a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, + a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, + a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a + end +end -- cgit v1.2.3 From 1264219832aeff2630f47d4abb9bee6d013c3e75 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Tue, 15 Nov 2016 11:13:38 -0500 Subject: Fix segfault in gen_values with NOVAL and more than 127 args --- mrbgems/mruby-compiler/core/codegen.c | 2 -- test/t/codegen.rb | 8 ++++++++ 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 3cfd99d41..99ab4dd97 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -818,8 +818,6 @@ gen_values(codegen_scope *s, node *t, int val) } } else { - codegen(s, t->car->cdr, NOVAL); - t = t->cdr; while (t) { codegen(s, t->car, NOVAL); t = t->cdr; diff --git a/test/t/codegen.rb b/test/t/codegen.rb index 3058a7fbc..528f58d9e 100644 --- a/test/t/codegen.rb +++ b/test/t/codegen.rb @@ -73,3 +73,11 @@ assert('undef with 127 or more arguments') do a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a end end + +assert('next in normal loop with 127 arguments') do + assert_raise NameError do + while true + next A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A + end + end +end -- cgit v1.2.3 From 7b968ca893b5c24e07ba67e4e5100d93a4024418 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 10 Dec 2016 12:34:23 +0900 Subject: Clear parsing_heredoc at the end of file --- mrbgems/mruby-compiler/core/parse.y | 1 + 1 file changed, 1 insertion(+) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 957ad5815..ee3373fbf 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -3946,6 +3946,7 @@ parse_string(parser_state *p) } } if ((len-1 == hinf->term_len) && (strncmp(s, hinf->term, len-1) == 0)) { + if (c < 0) p->parsing_heredoc = NULL; return tHEREDOC_END; } } -- cgit v1.2.3 From a4ae22ae0cfe5efe420cb6b8c68c6ebadb9cead8 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 13 Dec 2016 01:55:08 +0900 Subject: Failed to realloc irep->syms in certain condition. Also msym size changed to 512 from 256. --- mrbgems/mruby-compiler/core/codegen.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 38da952b4..33d3f96d4 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -500,7 +500,12 @@ new_lit(codegen_scope *s, mrb_value val) return i; } -static inline int +/* method symbols should be fit in 9 bits */ +#define MAXMSYMLEN 512 +/* maximum symbol numbers */ +#define MAXSYMLEN 65536 + +static int new_msym(codegen_scope *s, mrb_sym sym) { size_t i, len; @@ -508,20 +513,20 @@ new_msym(codegen_scope *s, mrb_sym sym) mrb_assert(s->irep); len = s->irep->slen; - if (len > 256) len = 256; + if (len > MAXMSYMLEN) len = MAXMSYMLEN; for (i=0; iirep->syms[i] == sym) return i; if (s->irep->syms[i] == 0) break; } - if (i == 256) { - codegen_error(s, "too many symbols (max 256)"); + if (i == MAXMSYMLEN) { + codegen_error(s, "too many symbols (max " MRB_STRINGIZE(MAXMSYMLEN) ")"); } s->irep->syms[i] = sym; if (i == s->irep->slen) s->irep->slen++; return i; } -static inline int +static int new_sym(codegen_scope *s, mrb_sym sym) { size_t i; @@ -529,13 +534,17 @@ new_sym(codegen_scope *s, mrb_sym sym) for (i=0; iirep->slen; i++) { if (s->irep->syms[i] == sym) return i; } - if (s->irep->slen > 125 && s->irep->slen < 256) { - s->irep->syms = (mrb_sym *)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*65536); - for (i = 0; i < 256 - s->irep->slen; i++) { + if (s->irep->slen == MAXSYMLEN) { + codegen_error(s, "too many symbols (max " MRB_STRINGIZE(MAXSYMLEN) ")"); + } + if (s->scapa == MAXMSYMLEN) { + s->scapa = MAXSYMLEN; + s->irep->syms = (mrb_sym *)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*MAXSYMLEN); + for (i = s->irep->slen; i < MAXMSYMLEN; i++) { static const mrb_sym mrb_sym_zero = { 0 }; - s->irep->syms[i + s->irep->slen] = mrb_sym_zero; + s->irep->syms[i] = mrb_sym_zero; } - s->irep->slen = 256; + s->irep->slen = MAXMSYMLEN; } s->irep->syms[s->irep->slen] = sym; return s->irep->slen++; @@ -2760,7 +2769,7 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *lv) p->irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa); p->irep->plen = 0; - p->scapa = 256; + p->scapa = MAXMSYMLEN; p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*p->scapa); p->irep->slen = 0; -- cgit v1.2.3 From 647ad29a7a1147e2c3ed93329cabbb974482697f Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 13 Dec 2016 02:32:50 +0900 Subject: Fixed wrong condition in new_sym() that breaks symbol data. --- mrbgems/mruby-compiler/core/codegen.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 33d3f96d4..90bafb3c2 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -537,7 +537,8 @@ new_sym(codegen_scope *s, mrb_sym sym) if (s->irep->slen == MAXSYMLEN) { codegen_error(s, "too many symbols (max " MRB_STRINGIZE(MAXSYMLEN) ")"); } - if (s->scapa == MAXMSYMLEN) { + + if (s->irep->slen > MAXMSYMLEN/2 && s->scapa == MAXMSYMLEN) { s->scapa = MAXSYMLEN; s->irep->syms = (mrb_sym *)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*MAXSYMLEN); for (i = s->irep->slen; i < MAXMSYMLEN; i++) { -- cgit v1.2.3 From d196e4dd04d2b1879401f31788d4630d3c1c972a Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 13 Dec 2016 11:18:05 +0900 Subject: void_expr_error(): n may be NULL. Reported from @clayton-shopify. --- mrbgems/mruby-compiler/core/parse.y | 1 + 1 file changed, 1 insertion(+) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index ee3373fbf..d70125a0b 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -3430,6 +3430,7 @@ void_expr_error(parser_state *p, node *n) { int c; + if (n == NULL) return; c = (int)(intptr_t)n->car; switch (c) { case NODE_BREAK: -- cgit v1.2.3 From fead715cef36abe7fe448b240636312acdd10775 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 13 Dec 2016 23:44:10 +0900 Subject: tLABEL should not come after conditional ternary; fix #3344 --- mrbgems/mruby-compiler/core/parse.y | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index d70125a0b..821411cf4 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -3923,6 +3923,7 @@ parse_string(parser_state *p) int beg = (intptr_t)p->lex_strterm->cdr->cdr->car; int end = (intptr_t)p->lex_strterm->cdr->cdr->cdr; parser_heredoc_info *hinf = (type & STR_FUNC_HEREDOC) ? parsing_heredoc_inf(p) : NULL; + int cmd_state = p->cmd_start; if (beg == 0) beg = -3; /* should never happen */ if (end == 0) end = -3; @@ -4127,10 +4128,13 @@ parse_string(parser_state *p) return tREGEXP; } yylval.nd = new_str(p, tok(p), toklen(p)); - if (IS_LABEL_SUFFIX(0)) { - p->lstate = EXPR_BEG; - nextc(p); - return tLABEL_END; + if (IS_LABEL_POSSIBLE()) { + if (IS_LABEL_SUFFIX(0)) { + fprintf(stderr, "tLABEL_END: %d->%d\n", p->lstate, EXPR_BEG); + p->lstate = EXPR_BEG; + nextc(p); + return tLABEL_END; + } } return tSTRING; -- cgit v1.2.3 From 73cc08772f1a11140b238525698bce0664326a50 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 14 Dec 2016 13:34:24 +0900 Subject: remove debug code; ref #3344 --- mrbgems/mruby-compiler/core/parse.y | 1 - 1 file changed, 1 deletion(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 821411cf4..fac779b07 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -4130,7 +4130,6 @@ parse_string(parser_state *p) yylval.nd = new_str(p, tok(p), toklen(p)); if (IS_LABEL_POSSIBLE()) { if (IS_LABEL_SUFFIX(0)) { - fprintf(stderr, "tLABEL_END: %d->%d\n", p->lstate, EXPR_BEG); p->lstate = EXPR_BEG; nextc(p); return tLABEL_END; -- cgit v1.2.3 From b0886d5692dd58bed608fe8fb2be0c017c729060 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 17 Dec 2016 15:08:05 +0900 Subject: Zero length heredoc still crashed; ref Shopify/mruby-internal#81 --- mrbgems/mruby-compiler/core/parse.y | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index fac779b07..ec9b652d7 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -3948,8 +3948,12 @@ parse_string(parser_state *p) } } if ((len-1 == hinf->term_len) && (strncmp(s, hinf->term, len-1) == 0)) { - if (c < 0) p->parsing_heredoc = NULL; - return tHEREDOC_END; + if (c < 0) { + p->parsing_heredoc = NULL; + } + else { + return tHEREDOC_END; + } } } if (c < 0) { -- cgit v1.2.3 From c2bbfa5b61450426f286f5a5e45c7ea479edf90c Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 17 Dec 2016 15:29:28 +0900 Subject: NODE_NEGATE cdr may not be code-node; fix #3348 ref #3324 Reported by Denis Kasak https://hackerone.com/dkasak --- mrbgems/mruby-compiler/core/codegen.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 90bafb3c2..fc54a0647 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -2231,13 +2231,9 @@ codegen(codegen_scope *s, node *tree, int val) { nt = (intptr_t)tree->car; tree = tree->cdr; - if (!val) { - codegen(s, tree, NOVAL); - break; - } switch (nt) { case NODE_FLOAT: - { + if (val) { char *p = (char*)tree; mrb_float f = mrb_float_read(p, NULL); int off = new_lit(s, mrb_float_value(s->mrb, -f)); @@ -2248,7 +2244,7 @@ codegen(codegen_scope *s, node *tree, int val) break; case NODE_INT: - { + if (val) { char *p = (char*)tree->car; int base = (intptr_t)tree->cdr->car; mrb_int i; @@ -2277,7 +2273,7 @@ codegen(codegen_scope *s, node *tree, int val) break; default: - { + if (val) { int sym = new_msym(s, mrb_intern_lit(s->mrb, "-")); genop(s, MKOP_ABx(OP_LOADI, cursp(), 0)); @@ -2286,6 +2282,9 @@ codegen(codegen_scope *s, node *tree, int val) pop(); pop(); genop(s, MKOP_ABC(OP_SUB, cursp(), sym, 2)); } + else { + codegen(s, tree, NOVAL); + } break; } } -- cgit v1.2.3 From 2c0f8f1a23047338a3449b51142b075fb33573f5 Mon Sep 17 00:00:00 2001 From: Clayton Smith Date: Fri, 20 Jan 2017 18:40:18 -0500 Subject: Remove problematic optimization. --- mrbgems/mruby-compiler/core/codegen.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index fc54a0647..89dc20f04 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -1675,7 +1675,6 @@ codegen(codegen_scope *s, node *tree, int val) } tree = tree->car; if (tree->car) { /* pre */ - int first = TRUE; t = tree->car; n = 0; while (t) { @@ -1684,10 +1683,7 @@ codegen(codegen_scope *s, node *tree, int val) n++; } else { - if (first) { - genop(s, MKOP_A(OP_LOADNIL, rhs+n)); - first = FALSE; - } + genop(s, MKOP_A(OP_LOADNIL, rhs+n)); gen_assignment(s, t->car, rhs+n, NOVAL); } t = t->cdr; -- cgit v1.2.3 From 797ff625f3ef182ca9ce55d7f8f3bc9ba8adb298 Mon Sep 17 00:00:00 2001 From: Clayton Smith Date: Sat, 21 Jan 2017 09:08:37 -0500 Subject: Fix incorrect parsing of block parameters. --- mrbgems/mruby-compiler/core/parse.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index ec9b652d7..f8e4eb72f 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -2448,7 +2448,7 @@ block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_f_block_arg } | f_arg ',' { - $$ = new_args(p, $1, 0, 1, 0, 0); + $$ = new_args(p, $1, 0, 0, 0, 0); } | f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg { -- cgit v1.2.3 From 3ce82603a56f2b9480e2bd889dd98f813b868757 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 23 Jan 2017 16:48:18 +0900 Subject: Fix memory leak; ref #3378 The fix was proposed by @titanous --- mrbgems/mruby-compiler/core/codegen.c | 1 + 1 file changed, 1 insertion(+) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 89dc20f04..fae12b288 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -93,6 +93,7 @@ codegen_error(codegen_scope *s, const char *message) if (!s) return; while (s->prev) { codegen_scope *tmp = s->prev; + mrb_free(s->mrb, s->iseq); mrb_pool_close(s->mpool); s = tmp; } -- cgit v1.2.3 From f0f095bc135c4d2e6f6d54d6b5683db77708369b Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 23 Jan 2017 16:53:31 +0900 Subject: Fix a double free problem in codegen.c; fix #3378 This issue was first reported by https://hackerone.com/geeknik The fix was proposed by @titanous --- include/mruby/irep.h | 1 + mrbgems/mruby-compiler/core/codegen.c | 4 +--- src/state.c | 5 ++++- 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'mrbgems/mruby-compiler') diff --git a/include/mruby/irep.h b/include/mruby/irep.h index 8922f4b76..35ae2bbaa 100644 --- a/include/mruby/irep.h +++ b/include/mruby/irep.h @@ -39,6 +39,7 @@ typedef struct mrb_irep { struct mrb_locals *lv; /* debug info */ + mrb_bool own_filename; const char *filename; uint16_t *lines; struct mrb_irep_debug_info* debug_info; diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index fae12b288..eae0492ce 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -2844,6 +2844,7 @@ scope_finish(codegen_scope *s) memcpy(fname, s->filename, fname_len); fname[fname_len] = '\0'; irep->filename = fname; + irep->own_filename = TRUE; } irep->nlocals = s->nlocals; @@ -2951,9 +2952,6 @@ mrb_generate_code(mrb_state *mrb, parser_state *p) return proc; } MRB_CATCH(&scope->jmp) { - if (scope->filename == scope->irep->filename) { - scope->irep->filename = NULL; - } mrb_irep_decref(mrb, scope->irep); mrb_pool_close(scope->mpool); return NULL; diff --git a/src/state.c b/src/state.c index 1259ac3a0..11b71dd63 100644 --- a/src/state.c +++ b/src/state.c @@ -159,7 +159,9 @@ mrb_irep_free(mrb_state *mrb, mrb_irep *irep) } mrb_free(mrb, irep->reps); mrb_free(mrb, irep->lv); - mrb_free(mrb, (void *)irep->filename); + if (irep->own_filename) { + mrb_free(mrb, (void *)irep->filename); + } mrb_free(mrb, irep->lines); mrb_debug_info_free(mrb, irep->debug_info); mrb_free(mrb, irep); @@ -261,6 +263,7 @@ mrb_add_irep(mrb_state *mrb) irep = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep)); *irep = mrb_irep_zero; irep->refcnt = 1; + irep->own_filename = FALSE; return irep; } -- cgit v1.2.3 From 6e0ba0085d22b7751c46b178e841046483f0f6b4 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 4 Feb 2017 12:37:08 +0900 Subject: Jump address should fit in 16 bits range; fix #3426 --- mrbgems/mruby-compiler/core/codegen.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index eae0492ce..1f7c069d4 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -388,6 +388,9 @@ dispatch(codegen_scope *s, int pc) scope_error(s); break; } + if (diff > MAXARG_sBx) { + codegen_error(s, "too distant jump address"); + } s->iseq[pc] = MKOP_AsBx(c, GETARG_A(i), diff); } -- cgit v1.2.3 From f2b18a604c6e4db5875b689ba26b377ad720a3ab Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 6 Feb 2017 09:14:49 +0900 Subject: Check maximum number of formal arguments. http://hkdnet.hatenablog.com/entry/2017/02/06/080000 (Japanese) --- mrbgems/mruby-compiler/core/codegen.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 1f7c069d4..778b6fe0f 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -666,6 +666,9 @@ lambda_body(codegen_scope *s, node *tree, int blk) ka = kd = 0; ba = tree->car->cdr->cdr->cdr->cdr ? 1 : 0; + if (ma > 0x1f || oa > 0x1f || pa > 0x1f || ka > 0x1f) { + codegen_error(s, "too many formal arguments"); + } a = ((mrb_aspec)(ma & 0x1f) << 18) | ((mrb_aspec)(oa & 0x1f) << 13) | ((ra & 1) << 12) -- cgit v1.2.3 From ecb6ac8b4aca56582ebed3e955178a0ad6c77d5d Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 13 Feb 2017 19:31:06 +0900 Subject: Fixed codegen error of redo in rescue; fix #3422 The issue (and the fix) was reported by https://hackerone.com/dgaletic --- mrbgems/mruby-compiler/core/codegen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems/mruby-compiler') diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 778b6fe0f..23e036d49 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -2038,7 +2038,7 @@ codegen(codegen_scope *s, node *tree, int val) break; case NODE_REDO: - if (!s->loop) { + if (!s->loop || s->loop->type == LOOP_BEGIN || s->loop->type == LOOP_RESCUE) { raise_error(s, "unexpected redo"); } else { -- cgit v1.2.3