diff options
| author | Satoshi Tagomori <s-tagomori@sakura.ad.jp> | 2025-08-10 18:45:44 +0900 |
|---|---|---|
| committer | Satoshi Tagomori <tagomoris@gmail.com> | 2025-09-29 01:15:38 +0900 |
| commit | 32f58628e900894b48b9e8630c250dedbbb1c126 (patch) | |
| tree | b3d0b26380b16d50aa818ca1ff06b15f7208c606 | |
| parent | 20c73b17232cc5bd0f8a3c13507d56b5f11ab2ed (diff) | |
Update Namespace#eval to use control frames instead of namespace_push/pop
With this change, the argument code of Namespace#eval cannot refer local
variables around the calling line, but it should not be able to refer
these values. The code is evaluated in the receiver namespace, independently
from the local context.
| -rw-r--r-- | iseq.c | 15 | ||||
| -rw-r--r-- | iseq.h | 1 | ||||
| -rw-r--r-- | namespace.c | 18 |
3 files changed, 25 insertions, 9 deletions
@@ -1161,6 +1161,21 @@ rb_iseq_load_iseq(VALUE fname) return NULL; } +const rb_iseq_t * +rb_iseq_compile_iseq(VALUE str, VALUE fname) +{ + VALUE args[] = { + str, fname + }; + VALUE iseqv = rb_check_funcall(rb_cISeq, rb_intern("compile"), 2, args); + + if (!SPECIAL_CONST_P(iseqv) && RBASIC_CLASS(iseqv) == rb_cISeq) { + return iseqw_check(iseqv); + } + + return NULL; +} + #define CHECK_ARRAY(v) rb_to_array_type(v) #define CHECK_HASH(v) rb_to_hash_type(v) #define CHECK_STRING(v) rb_str_to_str(v) @@ -192,6 +192,7 @@ void rb_iseq_init_trace(rb_iseq_t *iseq); int rb_iseq_add_local_tracepoint_recursively(const rb_iseq_t *iseq, rb_event_flag_t turnon_events, VALUE tpval, unsigned int target_line, bool target_bmethod); int rb_iseq_remove_local_tracepoint_recursively(const rb_iseq_t *iseq, VALUE tpval); const rb_iseq_t *rb_iseq_load_iseq(VALUE fname); +const rb_iseq_t *rb_iseq_compile_iseq(VALUE str, VALUE fname); int rb_iseq_opt_frozen_string_literal(void); #if VM_INSN_INFO_TABLE_IMPL == 2 diff --git a/namespace.c b/namespace.c index 82bacd4108..3b7185e9aa 100644 --- a/namespace.c +++ b/namespace.c @@ -12,6 +12,7 @@ #include "internal/namespace.h" #include "internal/st.h" #include "internal/variable.h" +#include "iseq.h" #include "ruby/internal/globals.h" #include "ruby/util.h" #include "vm_core.h" @@ -843,20 +844,19 @@ initialize_root_namespace(void) } static VALUE -rb_namespace_eval_string(VALUE str) -{ - return rb_eval_string(RSTRING_PTR(str)); -} - -static VALUE rb_namespace_eval(VALUE namespace, VALUE str) { - rb_thread_t *th = GET_THREAD(); + const rb_iseq_t *iseq; + const rb_namespace_t *ns; StringValue(str); - namespace_push(th, namespace); - return rb_ensure(rb_namespace_eval_string, str, namespace_pop, (VALUE)th); + iseq = rb_iseq_compile_iseq(str, rb_str_new_cstr("eval")); + VM_ASSERT(iseq); + + ns = (const rb_namespace_t *)rb_get_namespace_t(namespace); + + return rb_iseq_eval(iseq, ns); } static int namespace_experimental_warned = 0; |
