--- /tmp/eval.c 2005-09-21 01:37:35.144705141 +0900 +++ eval.c 2005-09-21 01:32:05.458758905 +0900 @@ -244,2 +244,7 @@ +#define NOEX_TAINTED 8 +#define NOEX_SAFE(n) ((n) >> 4) +#define NOEX_WITH(n, v) ((n) | (v) << 4) +#define NOEX_WITH_SAFE(n) NOEX_WITH(n, ruby_safe_level) + void @@ -259,3 +264,3 @@ rb_clear_cache_by_id(mid); - body = NEW_METHOD(node, noex); + body = NEW_METHOD(node, NOEX_WITH_SAFE(noex)); st_insert(RCLASS(klass)->m_tbl, mid, body); @@ -4350,3 +4356,3 @@ static VALUE -rb_call0(klass, recv, id, argc, argv, body, nosuper) +rb_call0(klass, recv, id, argc, argv, body, flags) VALUE klass, recv; @@ -4356,3 +4362,3 @@ NODE *body; /* OK */ - int nosuper; + int flags; { @@ -4363,2 +4369,3 @@ TMP_PROTECT; + volatile int safe = -1; @@ -4382,3 +4389,3 @@ ruby_frame->last_func = id; - ruby_frame->last_class = nosuper?0:klass; + ruby_frame->last_class = (flags & NOEX_UNDEF)?0:klass; ruby_frame->self = recv; @@ -4446,3 +4453,2 @@ PUSH_SCOPE(); - if (body->nd_rval) { @@ -4466,5 +4472,12 @@ + if (NOEX_SAFE(flags) > ruby_safe_level) { + if (!(flags&NOEX_TAINTED) && ruby_safe_level == 0 && NOEX_SAFE(flags) > 2) { + rb_raise(rb_eSecurityError, "calling insecure method: %s", + rb_id2name(id)); + } + safe = ruby_safe_level; + ruby_safe_level = NOEX_SAFE(flags); + } PUSH_VARS(); PUSH_TAG(PROT_FUNC); - if ((state = EXEC_TAG()) == 0) { @@ -4552,2 +4565,3 @@ } + if (safe >= 0) ruby_safe_level = safe; POP_TAG(); @@ -4639,3 +4653,3 @@ - return rb_call0(klass, recv, id, argc, argv, body, noex & NOEX_UNDEF); + return rb_call0(klass, recv, id, argc, argv, body, noex); } @@ -6632,2 +6648,3 @@ ID id, oid; + int safe_level; NODE *body; @@ -6674,2 +6691,3 @@ data->oid = oid; + data->safe_level = NOEX_WITH_SAFE(0); OBJ_INFECT(method, klass); @@ -6694,2 +6712,3 @@ data->oid = orig->oid; + data->safe_level = NOEX_WITH_SAFE(0); OBJ_INFECT(method, obj); @@ -6745,18 +6764,14 @@ struct METHOD *data; - int state; - volatile int safe = ruby_safe_level; + int safe; Data_Get_Struct(method, struct METHOD, data); - PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT); - PUSH_TAG(PROT_NONE); - if (OBJ_TAINTED(method) && ruby_safe_level < 4) { - ruby_safe_level = 4; + if (OBJ_TAINTED(method)) { + safe = NOEX_WITH(data->safe_level, 4)|NOEX_TAINTED; } - if ((state = EXEC_TAG()) == 0) { - result = rb_call0(data->klass,data->recv,data->id,argc,argv,data->body,0); + else { + safe = data->safe_level; } - POP_TAG(); + PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT); + result = rb_call0(data->klass,data->recv,data->id,argc,argv,data->body,safe); POP_ITER(); - ruby_safe_level = safe; - if (state) JUMP_TAG(state); return result; @@ -6826,2 +6841,5 @@ return INT2FIX(0); + case NODE_BMETHOD: + case NODE_DMETHOD: + return proc_arity(method); default: