From 315cd8341823e129ba5df0f420443e9d06d62c6f Mon Sep 17 00:00:00 2001 From: matz Date: Tue, 22 May 2001 08:28:11 +0000 Subject: * variable.c (rb_alias_variable): should not allow variable aliasing if $SAFE >= 4. * parse.y (expr): "break" and "next" to take optional expression, which is used as a value for termination. [new, experimental] * eval.c (rb_eval): "break" can give value to terminating method. * eval.c (rb_eval): "break" and "next" to take optional expression. * eval.c (rb_yield_0): "next" can give value to terminating "yield". * eval.c (rb_iterate): "break" can give value to terminating method. * eval.c (proc_call): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1441 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 20 ++++++++++++++++++++ eval.c | 57 ++++++++++++++++++++++++++++++++++++++------------------- node.h | 4 ++-- parse.y | 49 ++++++++++++++++++++++++------------------------- variable.c | 2 ++ version.h | 4 ++-- 6 files changed, 88 insertions(+), 48 deletions(-) diff --git a/ChangeLog b/ChangeLog index e45ab1b4b3..ca161b279b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +Tue May 22 17:10:35 2001 K.Kosako + + * variable.c (rb_alias_variable): should not allow variable + aliasing if $SAFE >= 4. + +Tue May 22 02:37:45 2001 Yukihiro Matsumoto + + * parse.y (expr): "break" and "next" to take optional expression, + which is used as a value for termination. [new, experimental] + + * eval.c (rb_eval): "break" can give value to terminating method. + + * eval.c (rb_eval): "break" and "next" to take optional expression. + + * eval.c (rb_yield_0): "next" can give value to terminating "yield". + + * eval.c (rb_iterate): "break" can give value to terminating method. + + * eval.c (proc_call): ditto. + Mon May 21 13:15:25 2001 Yukihiro Matsumoto * bignum.c (rb_big2str): t should be protected from GC. diff --git a/eval.c b/eval.c index 6fa0cedec7..5116e90347 100644 --- a/eval.c +++ b/eval.c @@ -2288,7 +2288,7 @@ rb_eval(self, n) } else if (_block.tag->dst == state) { state &= TAG_MASK; - if (state == TAG_RETURN) { + if (state == TAG_RETURN || state == TAG_BREAK) { result = prot_tag->retval; } } @@ -2302,8 +2302,8 @@ rb_eval(self, n) goto iter_retry; case TAG_BREAK: - result = Qnil; break; + case TAG_RETURN: return_value(result); /* fall through */ @@ -2314,10 +2314,22 @@ rb_eval(self, n) break; case NODE_BREAK: + if (node->nd_stts) { + return_value(rb_eval(self, node->nd_stts)); + } + else { + return_value(Qnil); + } JUMP_TAG(TAG_BREAK); break; case NODE_NEXT: + if (node->nd_stts) { + return_value(rb_eval(self, node->nd_stts)); + } + else { + return_value(Qnil); + } JUMP_TAG(TAG_NEXT); break; @@ -3574,6 +3586,12 @@ rb_yield_0(val, self, klass, acheck) RARRAY(val)->len); } } + else if (block->var == (NODE*)2) { + if (val != Qundef && TYPE(val) == T_ARRAY && RARRAY(val)->len != 0) { + rb_raise(rb_eArgError, "wrong # of arguments (%d for 0)", + RARRAY(val)->len); + } + } else { if (nd_type(block->var) == NODE_MASGN) massign(self, block->var, val, acheck); @@ -3614,7 +3632,7 @@ rb_yield_0(val, self, klass, acheck) goto redo; case TAG_NEXT: state = 0; - result = Qnil; + result = prot_tag->retval; break; case TAG_BREAK: case TAG_RETURN: @@ -3842,7 +3860,7 @@ rb_iterate(it_proc, data1, bl_proc, data2) } if (ruby_block->tag->dst == state) { state &= TAG_MASK; - if (state == TAG_RETURN) { + if (state == TAG_RETURN || state == TAG_BREAK) { retval = prot_tag->retval; } } @@ -3858,7 +3876,6 @@ rb_iterate(it_proc, data1, bl_proc, data2) goto iter_retry; case TAG_BREAK: - retval = Qnil; break; case TAG_RETURN: @@ -6343,21 +6360,22 @@ proc_call(proc, args) ruby_block = old_block; ruby_safe_level = safe; - if (state) { - switch (state) { - case TAG_BREAK: - break; - case TAG_RETRY: - rb_raise(rb_eLocalJumpError, "retry from proc-closure"); - break; - case TAG_RETURN: - if (orphan) { /* orphan procedure */ - rb_raise(rb_eLocalJumpError, "return from proc-closure"); - } - /* fall through */ - default: - JUMP_TAG(state); + switch (state) { + case 0: + break; + case TAG_BREAK: + result = prot_tag->retval; + break; + case TAG_RETRY: + rb_raise(rb_eLocalJumpError, "retry from proc-closure"); + break; + case TAG_RETURN: + if (orphan) { /* orphan procedure */ + rb_raise(rb_eLocalJumpError, "return from proc-closure"); } + /* fall through */ + default: + JUMP_TAG(state); } return result; } @@ -6373,6 +6391,7 @@ proc_arity(proc) Data_Get_Struct(proc, struct BLOCK, data); if (data->var == 0) return INT2FIX(-1); if (data->var == (NODE*)1) return INT2FIX(0); + if (data->var == (NODE*)2) return INT2FIX(0); switch (nd_type(data->var)) { default: return INT2FIX(-1); diff --git a/node.h b/node.h index f64e368ad5..671dbeb520 100644 --- a/node.h +++ b/node.h @@ -248,8 +248,8 @@ typedef struct RNode { #define NEW_UNTIL(c,b,n) rb_node_newnode(NODE_UNTIL,c,b,n) #define NEW_FOR(v,i,b) rb_node_newnode(NODE_FOR,v,b,i) #define NEW_ITER(v,i,b) rb_node_newnode(NODE_ITER,v,b,i) -#define NEW_BREAK() rb_node_newnode(NODE_BREAK,0,0,0) -#define NEW_NEXT() rb_node_newnode(NODE_NEXT,0,0,0) +#define NEW_BREAK(s) rb_node_newnode(NODE_BREAK,s,0,0) +#define NEW_NEXT(s) rb_node_newnode(NODE_NEXT,s,0,0) #define NEW_REDO() rb_node_newnode(NODE_REDO,0,0,0) #define NEW_RETRY() rb_node_newnode(NODE_RETRY,0,0,0) #define NEW_BEGIN(b) rb_node_newnode(NODE_BEGIN,0,b,0) diff --git a/parse.y b/parse.y index 7e8d8b42a3..94df4497e2 100644 --- a/parse.y +++ b/parse.y @@ -426,21 +426,13 @@ expr : kRETURN ret_args yyerror("return appeared outside of method"); $$ = NEW_RETURN($2); } - | kBREAK + | kBREAK ret_args { - $$ = NEW_BREAK(); + $$ = NEW_BREAK($2); } - | kNEXT - { - $$ = NEW_NEXT(); - } - | kREDO - { - $$ = NEW_REDO(); - } - | kRETRY + | kNEXT ret_args { - $$ = NEW_RETRY(); + $$ = NEW_NEXT($2); } | command_call | expr kAND expr @@ -1142,19 +1134,6 @@ primary : literal { $$ = NEW_HASH($2); } - | kRETURN '(' ret_args ')' - { - if (!compile_for_eval && !in_def && !in_single) - yyerror("return appeared outside of method"); - value_expr($3); - $$ = NEW_RETURN($3); - } - | kRETURN '(' ')' - { - if (!compile_for_eval && !in_def && !in_single) - yyerror("return appeared outside of method"); - $$ = NEW_RETURN(0); - } | kRETURN { if (!compile_for_eval && !in_def && !in_single) @@ -1359,6 +1338,22 @@ primary : literal local_pop(); in_single--; } + | kBREAK + { + $$ = NEW_BREAK(0); + } + | kNEXT + { + $$ = NEW_NEXT(0); + } + | kREDO + { + $$ = NEW_REDO(); + } + | kRETRY + { + $$ = NEW_RETRY(); + } then : term | kTHEN @@ -1399,6 +1394,10 @@ opt_block_var : none { $$ = $2; } + | '<' f_args '>' + { + $$ = (NODE*)2; + } do_block : kDO_BLOCK diff --git a/variable.c b/variable.c index 16828a029d..4286f56086 100644 --- a/variable.c +++ b/variable.c @@ -700,6 +700,8 @@ rb_alias_variable(name1, name2) { struct global_entry *entry1, *entry2; + if (rb_safe_level() >= 4) + rb_raise(rb_eSecurityError, "Insecure: can't alias global variable"); entry1 = rb_global_entry(name1); entry2 = rb_global_entry(name2); diff --git a/version.h b/version.h index 57dfb4663a..29813a6f6d 100644 --- a/version.h +++ b/version.h @@ -1,4 +1,4 @@ #define RUBY_VERSION "1.7.0" -#define RUBY_RELEASE_DATE "2001-05-21" +#define RUBY_RELEASE_DATE "2001-05-22" #define RUBY_VERSION_CODE 170 -#define RUBY_RELEASE_CODE 20010521 +#define RUBY_RELEASE_CODE 20010522 -- cgit v1.2.3