--- eval.c.orig 2004-12-18 11:07:29.000000000 +0900 +++ eval.c 2005-09-21 16:53:31.127896405 +0900 @@ -254,2 +254,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 @@ -346,3 +351,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, (st_data_t)body); @@ -5458,3 +5463,3 @@ static VALUE -rb_call0(klass, recv, id, oid, argc, argv, body, nosuper) +rb_call0(klass, recv, id, oid, argc, argv, body, flags) VALUE klass, recv; @@ -5465,3 +5470,3 @@ NODE *body; /* OK */ - int nosuper; + int flags; { @@ -5472,2 +5477,3 @@ TMP_PROTECT; + volatile int safe = -1; @@ -5493,3 +5499,3 @@ ruby_frame->orig_func = oid; - ruby_frame->last_class = nosuper?0:klass; + ruby_frame->last_class = (flags & NOEX_UNDEF)?0:klass; ruby_frame->self = recv; @@ -5555,3 +5561,2 @@ PUSH_SCOPE(); - if (body->nd_rval) { @@ -5574,5 +5579,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) { @@ -5655,2 +5667,3 @@ } + if (safe >= 0) ruby_safe_level = safe; POP_TAG(); @@ -5742,3 +5755,3 @@ - return rb_call0(klass, recv, mid, id, argc, argv, body, noex & NOEX_NOSUPER); + return rb_call0(klass, recv, mid, id, argc, argv, body, noex); } @@ -8532,2 +8545,3 @@ ID id, oid; + int safe_level; NODE *body; @@ -8579,2 +8593,3 @@ data->oid = oid; + data->safe_level = NOEX_WITH_SAFE(0); OBJ_INFECT(method, klass); @@ -8663,2 +8678,3 @@ data->oid = orig->oid; + data->safe_level = NOEX_WITH_SAFE(0); OBJ_INFECT(method, obj); @@ -8784,4 +8800,3 @@ struct METHOD *data; - int state; - volatile int safe = -1; + int safe; @@ -8791,15 +8806,11 @@ } - PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT); - PUSH_TAG(PROT_NONE); if (OBJ_TAINTED(method)) { - safe = ruby_safe_level; - if (ruby_safe_level < 4) ruby_safe_level = 4; + safe = NOEX_WITH(data->safe_level, 4)|NOEX_TAINTED; } - if ((state = EXEC_TAG()) == 0) { - result = rb_call0(data->klass,data->recv,data->id,data->oid,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,data->oid,argc,argv,data->body,safe); POP_ITER(); - if (safe >= 0) ruby_safe_level = safe; - if (state) JUMP_TAG(state); return result; --- lib/xmlrpc/utils.rb.orig 2003-08-15 02:20:14.000000000 +0900 +++ lib/xmlrpc/utils.rb 2005-07-01 16:33:19.243521736 +0900 @@ -138,7 +138,7 @@ def get_methods(obj, delim=".") prefix = @prefix + delim - obj.class.public_instance_methods.collect { |name| + obj.class.public_instance_methods(false).collect { |name| [prefix + name, obj.method(name).to_proc, nil, nil] } end