diff options
author | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2001-06-19 04:35:17 +0000 |
---|---|---|
committer | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2001-06-19 04:35:17 +0000 |
commit | 9d51cf8a6a5d651c1c4dd363dbf3f4905e3f307d (patch) | |
tree | 98247086ea05415f034f0b5a0e6cc97163f47be2 /eval.c | |
parent | 6aa71d4c800d11d9735007cf3b063e5ea2fc5941 (diff) | |
download | ruby-9d51cf8a6a5d651c1c4dd363dbf3f4905e3f307d.tar.gz |
* eval.c (rb_f_require): searches ".rb" and ".so" at the same
time. previous behavior (search ".rb", then ".so") has a
security risk (ruby-bugs#PR140).
* array.c (rb_ary_to_ary): new function to replace internal
rb_Array(), which never calls to_a, but to_ary (rb_Array() might
call both). [new]
* regex.c (PUSH_FAILURE_POINT): push option status again.
* regex.c (re_compile_pattern): avoid pushing unnecessary
option_set.
* eval.c (rb_load): tainted string is OK if wrapped *and*
$SAFE >= 4.
* eval.c (rb_thread_start_0): should not nail down higher blocks
before preserving original context (i.e. should not alter
original context).
* eval.c (proc_yield): new method equivalent to Proc#call but no
check for number of arguments. [new]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1526 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'eval.c')
-rw-r--r-- | eval.c | 111 |
1 files changed, 70 insertions, 41 deletions
@@ -1676,7 +1676,7 @@ copy_node_scope(node, rval) char *file = ruby_sourcefile;\ int line = ruby_sourceline;\ if (TYPE(args) != T_ARRAY)\ - args = rb_Array(args);\ + args = rb_ary_to_ary(args);\ argc = RARRAY(args)->len;\ argv = ALLOCA_N(VALUE, argc);\ MEMCPY(argv, RARRAY(args)->ptr, VALUE, argc);\ @@ -2129,7 +2129,7 @@ rb_eval(self, n) VALUE v = rb_eval(self, tag->nd_head->nd_head); int i; - if (TYPE(v) != T_ARRAY) v = rb_Array(v); + if (TYPE(v) != T_ARRAY) v = rb_ary_to_ary(v); for (i=0; i<RARRAY(v)->len; i++) { if (RTEST(RARRAY(v)->ptr[i])) { node = node->nd_body; @@ -2174,7 +2174,7 @@ rb_eval(self, n) VALUE v = rb_eval(self, tag->nd_head->nd_head); int i; - if (TYPE(v) != T_ARRAY) v = rb_Array(v); + if (TYPE(v) != T_ARRAY) v = rb_ary_to_ary(v); for (i=0; i<RARRAY(v)->len; i++) { if (RTEST(rb_funcall2(RARRAY(v)->ptr[i], eqq, 1, &val))){ node = node->nd_body; @@ -2347,14 +2347,14 @@ rb_eval(self, n) case NODE_RESTARY: result = rb_eval(self, node->nd_head); if (TYPE(result) != T_ARRAY) { - result = rb_Array(result); + result = rb_ary_to_ary(result); } break; case NODE_REXPAND: result = rb_eval(self, node->nd_head); if (TYPE(result) != T_ARRAY) { - result = rb_Array(result); + result = rb_ary_to_ary(result); } if (RARRAY(result)->len == 0) { result = Qnil; @@ -2520,7 +2520,7 @@ rb_eval(self, n) case NODE_ARGSCAT: result = rb_ary_concat(rb_eval(self, node->nd_head), - rb_Array(rb_eval(self, node->nd_body))); + rb_ary_to_ary(rb_eval(self, node->nd_body))); break; case NODE_ARGSPUSH: @@ -3546,16 +3546,20 @@ rb_f_block_given_p() return Qfalse; } +#define PC_NONE 0x0 +#define PC_ACHECK 0x1 +#define PC_PCALL 0x2 + static VALUE -rb_yield_0(val, self, klass, acheck) +rb_yield_0(val, self, klass, pcall) VALUE val, self, klass; /* OK */ - int acheck; + int pcall; { NODE *node; volatile VALUE result = Qnil; volatile VALUE old_cref; - struct BLOCK *block; - struct SCOPE *old_scope; + struct BLOCK * volatile block; + struct SCOPE * volatile old_scope; struct FRAME frame; int state; static unsigned serial = 1; @@ -3591,7 +3595,7 @@ rb_yield_0(val, self, klass, acheck) PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { if (block->var == (NODE*)1) { - if (acheck && val != Qundef && + if ((pcall&PC_ACHECK) && val != Qundef && TYPE(val) == T_ARRAY && RARRAY(val)->len != 0) { rb_raise(rb_eArgError, "wrong # of arguments (%d for 0)", RARRAY(val)->len); @@ -3605,14 +3609,14 @@ rb_yield_0(val, self, klass, acheck) } else { if (nd_type(block->var) == NODE_MASGN) - massign(self, block->var, val, acheck); + massign(self, block->var, val, (pcall&PC_ACHECK)); else { /* argument adjust for proc_call etc. */ - if (acheck && val != Qundef && + if (pcall && val != Qundef && TYPE(val) == T_ARRAY && RARRAY(val)->len == 1) { val = RARRAY(val)->ptr[0]; } - assign(self, block->var, val, acheck); + assign(self, block->var, val, (pcall&PC_ACHECK)); } } } @@ -3621,7 +3625,7 @@ rb_yield_0(val, self, klass, acheck) } else { /* argument adjust for proc_call etc. */ - if (acheck && val != Qundef && + if (pcall && val != Qundef && TYPE(val) == T_ARRAY && RARRAY(val)->len == 1) { val = RARRAY(val)->ptr[0]; } @@ -5171,7 +5175,12 @@ rb_load(fname, wrap) NODE *saved_cref = ruby_cref; TMP_PROTECT; - SafeStringValue(fname); + if (wrap && ruby_safe_level >= 4) { + StringValue(fname); + } + else { + SafeStringValue(fname); + } file = rb_find_file(RSTRING(fname)->ptr); if (!file) { rb_raise(rb_eLoadError, "No such file to load -- %s", RSTRING(fname)->ptr); @@ -5402,28 +5411,20 @@ rb_f_require(obj, fname) } buf = ALLOCA_N(char, strlen(RSTRING(fname)->ptr) + 5); strcpy(buf, RSTRING(fname)->ptr); - strcat(buf, ".rb"); - if (rb_find_file(buf)) { + switch (rb_find_file_noext(buf)) { + case 0: + break; + + case 1: fname = rb_str_new2(buf); - feature = buf; + file = feature = buf; goto load_rb; - } - strcpy(buf, RSTRING(fname)->ptr); - strcat(buf, DLEXT); - file = rb_find_file(buf); - if (file) { - feature = buf; - goto load_dyna; - } -#ifdef DLEXT2 - strcpy(buf, RSTRING(fname)->ptr); - strcat(buf, DLEXT2); - file = rb_find_file(buf); - if (file) { + + default: feature = buf; + file = rb_find_file(buf); goto load_dyna; } -#endif rb_raise(rb_eLoadError, "No such file to load -- %s", RSTRING(fname)->ptr); @@ -6330,8 +6331,9 @@ callargs(args) } static VALUE -proc_call(proc, args) +proc_invoke(proc, args, pcall) VALUE proc, args; /* OK */ + int pcall; { struct BLOCK * volatile old_block; struct BLOCK _block; @@ -6341,6 +6343,13 @@ proc_call(proc, args) volatile int orphan; volatile int safe = ruby_safe_level; + if (pcall) { + pcall = PC_ACHECK|PC_PCALL; + } + else { + pcall = PC_PCALL; + } + if (rb_block_given_p() && ruby_frame->last_func) { rb_warning("block for %s#%s is useless", rb_class2name(CLASS_OF(proc)), @@ -6367,7 +6376,7 @@ proc_call(proc, args) state = EXEC_TAG(); if (state == 0) { proc_set_safe_level(proc); - result = rb_yield_0(args, 0, 0, Qtrue); + result = rb_yield_0(args, 0, 0, pcall); } POP_TAG(); @@ -6399,6 +6408,20 @@ proc_call(proc, args) } static VALUE +proc_call(proc, args) + VALUE proc, args; /* OK */ +{ + return proc_invoke(proc, args, Qtrue); +} + +static VALUE +proc_yield(proc, args) + VALUE proc, args; /* OK */ +{ + return proc_invoke(proc, args, Qfalse); +} + +static VALUE proc_arity(proc) VALUE proc; { @@ -6899,6 +6922,7 @@ Init_Proc() rb_define_singleton_method(rb_cProc, "new", proc_s_new, -1); rb_define_method(rb_cProc, "call", proc_call, -2); + rb_define_method(rb_cProc, "yield", proc_yield, -2); rb_define_method(rb_cProc, "arity", proc_arity, 0); rb_define_method(rb_cProc, "[]", proc_call, -2); rb_define_method(rb_cProc, "==", proc_eq, 1); @@ -8210,7 +8234,11 @@ rb_thread_start_0(fn, arg, th_arg) } #endif - if (ruby_block) { /* should nail down higher scopes */ + if (THREAD_SAVE_CONTEXT(curr_thread)) { + return thread; + } + + if (ruby_block) { /* should nail down higher blocks */ struct BLOCK dummy; dummy.prev = ruby_block; @@ -8219,9 +8247,6 @@ rb_thread_start_0(fn, arg, th_arg) } scope_dup(ruby_scope); FL_SET(ruby_scope, SCOPE_SHARED); - if (THREAD_SAVE_CONTEXT(curr_thread)) { - return thread; - } if (!th->next) { /* merge in thread list */ @@ -8243,17 +8268,21 @@ rb_thread_start_0(fn, arg, th_arg) POP_TAG(); status = th->status; + if (th == main_thread) ruby_stop(state); + rb_thread_remove(th); + while (saved_block) { struct BLOCK *tmp = saved_block; + if (curr_thread == main_thread) { + printf("free(%p)\n", saved_block); + } if (tmp->frame.argc > 0) free(tmp->frame.argv); saved_block = tmp->prev; free(tmp); } - if (th == main_thread) ruby_stop(state); - rb_thread_remove(th); if (state && status != THREAD_TO_KILL && !NIL_P(ruby_errinfo)) { th->flags |= THREAD_RAISED; if (state == TAG_FATAL) { |