Skip to content

Commit 1369d05

Browse files
committed
Fixes [Bug #21522] eval isolation in Ractors for Prism
1 parent a9f24aa commit 1369d05

File tree

2 files changed

+52
-21
lines changed

2 files changed

+52
-21
lines changed

bootstraptest/test_ractor.rb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,37 @@ def ractor_local_globals
754754
end
755755
}
756756

757+
# eval with outer locals in a Ractor raises SyntaxError
758+
# [Bug #21522]
759+
assert_equal 'SyntaxError', %q{
760+
outer = 42
761+
r = Ractor.new do
762+
eval("outer")
763+
end
764+
begin
765+
r.value
766+
rescue Ractor::RemoteError => e
767+
e.cause.class
768+
end
769+
}
770+
771+
# eval of an undefined name in a Ractor raises NameError
772+
assert_equal 'NameError', %q{
773+
r = Ractor.new do
774+
eval("totally_undefined_name")
775+
end
776+
begin
777+
r.value
778+
rescue Ractor::RemoteError => e
779+
e.cause.class
780+
end
781+
}
782+
783+
# eval of a local defined inside the Ractor works
784+
assert_equal '99', %q{
785+
Ractor.new { inner = 99; eval("inner").to_s }.value
786+
}
787+
757788
# ivar in shareable-objects are not allowed to access from non-main Ractor
758789
assert_equal "can not get unshareable values from instance variables of classes/modules from non-main Ractors", <<~'RUBY', frozen_string_literal: false
759790
class C

vm_eval.c

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1669,6 +1669,24 @@ get_eval_default_path(void)
16691669
return eval_default_path;
16701670
}
16711671

1672+
static inline int
1673+
compute_isolated_depth_from_ep(const VALUE *ep)
1674+
{
1675+
int depth = 1;
1676+
while (1) {
1677+
if (VM_ENV_FLAGS(ep, VM_ENV_FLAG_ISOLATED)) return depth;
1678+
if (VM_ENV_LOCAL_P(ep)) return 0;
1679+
ep = VM_ENV_PREV_EP(ep);
1680+
depth++;
1681+
}
1682+
}
1683+
1684+
static inline int
1685+
compute_isolated_depth_from_block(const struct rb_block *blk)
1686+
{
1687+
return compute_isolated_depth_from_ep(vm_block_ep(blk));
1688+
}
1689+
16721690
static const rb_iseq_t *
16731691
pm_eval_make_iseq(VALUE src, VALUE fname, int line,
16741692
const struct rb_block *base_block)
@@ -1677,8 +1695,8 @@ pm_eval_make_iseq(VALUE src, VALUE fname, int line,
16771695
const rb_iseq_t *iseq = parent;
16781696
VALUE name = rb_fstring_lit("<compiled>");
16791697

1680-
// Conditionally enable coverage depending on the current mode:
16811698
int coverage_enabled = ((rb_get_coverage_mode() & COVERAGE_TARGET_EVAL) != 0) ? 1 : 0;
1699+
int isolated_depth = compute_isolated_depth_from_block(base_block);
16821700

16831701
if (!fname) {
16841702
fname = rb_source_location(&line);
@@ -1872,7 +1890,7 @@ pm_eval_make_iseq(VALUE src, VALUE fname, int line,
18721890
#undef FORWARDING_ALL_STR
18731891

18741892
int error_state;
1875-
iseq = pm_iseq_new_eval(&result.node, name, fname, Qnil, line, parent, 0, &error_state);
1893+
iseq = pm_iseq_new_eval(&result.node, name, fname, Qnil, line, parent, isolated_depth, &error_state);
18761894

18771895
pm_scope_node_t *prev = result.node.previous;
18781896
while (prev) {
@@ -1908,27 +1926,9 @@ eval_make_iseq(VALUE src, VALUE fname, int line,
19081926
rb_iseq_t *iseq = NULL;
19091927
VALUE ast_value;
19101928
rb_ast_t *ast;
1911-
int isolated_depth = 0;
19121929

1913-
// Conditionally enable coverage depending on the current mode:
19141930
int coverage_enabled = (rb_get_coverage_mode() & COVERAGE_TARGET_EVAL) != 0;
1915-
1916-
{
1917-
int depth = 1;
1918-
const VALUE *ep = vm_block_ep(base_block);
1919-
1920-
while (1) {
1921-
if (VM_ENV_FLAGS(ep, VM_ENV_FLAG_ISOLATED)) {
1922-
isolated_depth = depth;
1923-
break;
1924-
}
1925-
else if (VM_ENV_LOCAL_P(ep)) {
1926-
break;
1927-
}
1928-
ep = VM_ENV_PREV_EP(ep);
1929-
depth++;
1930-
}
1931-
}
1931+
int isolated_depth = compute_isolated_depth_from_block(base_block);
19321932

19331933
if (!fname) {
19341934
fname = rb_source_location(&line);

0 commit comments

Comments
 (0)