summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSatoshi Tagomori <s-tagomori@sakura.ad.jp>2025-08-10 18:45:44 +0900
committerSatoshi Tagomori <tagomoris@gmail.com>2025-09-29 01:15:38 +0900
commit32f58628e900894b48b9e8630c250dedbbb1c126 (patch)
treeb3d0b26380b16d50aa818ca1ff06b15f7208c606
parent20c73b17232cc5bd0f8a3c13507d56b5f11ab2ed (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.c15
-rw-r--r--iseq.h1
-rw-r--r--namespace.c18
3 files changed, 25 insertions, 9 deletions
diff --git a/iseq.c b/iseq.c
index ad9149ef98..ae30d60ced 100644
--- a/iseq.c
+++ b/iseq.c
@@ -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)
diff --git a/iseq.h b/iseq.h
index c7f091a0b4..a8ad8ef9b0 100644
--- a/iseq.h
+++ b/iseq.h
@@ -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;