Skip to content

Commit 32f5862

Browse files
committed
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.
1 parent 20c73b1 commit 32f5862

File tree

3 files changed

+25
-9
lines changed

3 files changed

+25
-9
lines changed

iseq.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,6 +1161,21 @@ rb_iseq_load_iseq(VALUE fname)
11611161
return NULL;
11621162
}
11631163

1164+
const rb_iseq_t *
1165+
rb_iseq_compile_iseq(VALUE str, VALUE fname)
1166+
{
1167+
VALUE args[] = {
1168+
str, fname
1169+
};
1170+
VALUE iseqv = rb_check_funcall(rb_cISeq, rb_intern("compile"), 2, args);
1171+
1172+
if (!SPECIAL_CONST_P(iseqv) && RBASIC_CLASS(iseqv) == rb_cISeq) {
1173+
return iseqw_check(iseqv);
1174+
}
1175+
1176+
return NULL;
1177+
}
1178+
11641179
#define CHECK_ARRAY(v) rb_to_array_type(v)
11651180
#define CHECK_HASH(v) rb_to_hash_type(v)
11661181
#define CHECK_STRING(v) rb_str_to_str(v)

iseq.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ void rb_iseq_init_trace(rb_iseq_t *iseq);
192192
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);
193193
int rb_iseq_remove_local_tracepoint_recursively(const rb_iseq_t *iseq, VALUE tpval);
194194
const rb_iseq_t *rb_iseq_load_iseq(VALUE fname);
195+
const rb_iseq_t *rb_iseq_compile_iseq(VALUE str, VALUE fname);
195196
int rb_iseq_opt_frozen_string_literal(void);
196197

197198
#if VM_INSN_INFO_TABLE_IMPL == 2

namespace.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "internal/namespace.h"
1313
#include "internal/st.h"
1414
#include "internal/variable.h"
15+
#include "iseq.h"
1516
#include "ruby/internal/globals.h"
1617
#include "ruby/util.h"
1718
#include "vm_core.h"
@@ -842,21 +843,20 @@ initialize_root_namespace(void)
842843
}
843844
}
844845

845-
static VALUE
846-
rb_namespace_eval_string(VALUE str)
847-
{
848-
return rb_eval_string(RSTRING_PTR(str));
849-
}
850-
851846
static VALUE
852847
rb_namespace_eval(VALUE namespace, VALUE str)
853848
{
854-
rb_thread_t *th = GET_THREAD();
849+
const rb_iseq_t *iseq;
850+
const rb_namespace_t *ns;
855851

856852
StringValue(str);
857853

858-
namespace_push(th, namespace);
859-
return rb_ensure(rb_namespace_eval_string, str, namespace_pop, (VALUE)th);
854+
iseq = rb_iseq_compile_iseq(str, rb_str_new_cstr("eval"));
855+
VM_ASSERT(iseq);
856+
857+
ns = (const rb_namespace_t *)rb_get_namespace_t(namespace);
858+
859+
return rb_iseq_eval(iseq, ns);
860860
}
861861

862862
static int namespace_experimental_warned = 0;

0 commit comments

Comments
 (0)