Skip to content

Commit a956a20

Browse files
tenderlovek0kubun
authored andcommitted
Interpolated strings must not be frozen
Strings concatenated with backslash may end up being frozen when they shouldn't be. This commit fixes the issue. It required a change upstream in Prism, but also a change to the Prism compiler in CRuby. ruby/prism#3606 [Bug #21187]
1 parent cfdf428 commit a956a20

2 files changed

Lines changed: 11 additions & 6 deletions

File tree

prism_compile.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@ parse_regexp_concat(rb_iseq_t *iseq, const pm_scope_node_t *scope_node, const pm
557557
static void pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node);
558558

559559
static int
560-
pm_interpolated_node_compile(rb_iseq_t *iseq, const pm_node_list_t *parts, const pm_node_location_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node, rb_encoding *implicit_regexp_encoding, rb_encoding *explicit_regexp_encoding)
560+
pm_interpolated_node_compile(rb_iseq_t *iseq, const pm_node_list_t *parts, const pm_node_location_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node, rb_encoding *implicit_regexp_encoding, rb_encoding *explicit_regexp_encoding, bool mutable_result)
561561
{
562562
int stack_size = 0;
563563
size_t parts_size = parts->size;
@@ -667,7 +667,7 @@ pm_interpolated_node_compile(rb_iseq_t *iseq, const pm_node_list_t *parts, const
667667
if (RTEST(current_string)) {
668668
current_string = rb_fstring(current_string);
669669

670-
if (stack_size == 0 && interpolated) {
670+
if (stack_size == 0 && (interpolated || mutable_result)) {
671671
PUSH_INSN1(ret, current_location, putstring, current_string);
672672
}
673673
else {
@@ -691,7 +691,7 @@ pm_compile_regexp_dynamic(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_
691691
rb_encoding *explicit_regexp_encoding = parse_regexp_encoding(scope_node, node);
692692
rb_encoding *implicit_regexp_encoding = explicit_regexp_encoding != NULL ? explicit_regexp_encoding : scope_node->encoding;
693693

694-
int length = pm_interpolated_node_compile(iseq, parts, node_location, ret, popped, scope_node, implicit_regexp_encoding, explicit_regexp_encoding);
694+
int length = pm_interpolated_node_compile(iseq, parts, node_location, ret, popped, scope_node, implicit_regexp_encoding, explicit_regexp_encoding, false);
695695
PUSH_INSN2(ret, *node_location, toregexp, INT2FIX(parse_regexp_flags(node) & 0xFF), INT2FIX(length));
696696
}
697697

@@ -9575,7 +9575,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
95759575
}
95769576
else {
95779577
const pm_interpolated_string_node_t *cast = (const pm_interpolated_string_node_t *) node;
9578-
int length = pm_interpolated_node_compile(iseq, &cast->parts, &location, ret, popped, scope_node, NULL, NULL);
9578+
int length = pm_interpolated_node_compile(iseq, &cast->parts, &location, ret, popped, scope_node, NULL, NULL, !PM_NODE_FLAG_P(cast, PM_INTERPOLATED_STRING_NODE_FLAGS_FROZEN));
95799579
if (length > 1) PUSH_INSN1(ret, location, concatstrings, INT2FIX(length));
95809580
if (popped) PUSH_INSN(ret, location, pop);
95819581
}
@@ -9586,7 +9586,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
95869586
// :"foo #{bar}"
95879587
// ^^^^^^^^^^^^^
95889588
const pm_interpolated_symbol_node_t *cast = (const pm_interpolated_symbol_node_t *) node;
9589-
int length = pm_interpolated_node_compile(iseq, &cast->parts, &location, ret, popped, scope_node, NULL, NULL);
9589+
int length = pm_interpolated_node_compile(iseq, &cast->parts, &location, ret, popped, scope_node, NULL, NULL, false);
95909590

95919591
if (length > 1) {
95929592
PUSH_INSN1(ret, location, concatstrings, INT2FIX(length));
@@ -9608,7 +9608,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
96089608

96099609
PUSH_INSN(ret, location, putself);
96109610

9611-
int length = pm_interpolated_node_compile(iseq, &cast->parts, &location, ret, false, scope_node, NULL, NULL);
9611+
int length = pm_interpolated_node_compile(iseq, &cast->parts, &location, ret, false, scope_node, NULL, NULL, false);
96129612
if (length > 1) PUSH_INSN1(ret, location, concatstrings, INT2FIX(length));
96139613

96149614
PUSH_SEND_WITH_FLAG(ret, location, idBackquote, INT2NUM(1), INT2FIX(VM_CALL_FCALL | VM_CALL_ARGS_SIMPLE));

test/prism/result/static_literals_test.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44

55
module Prism
66
class StaticLiteralsTest < TestCase
7+
def test_concatenanted_string_literal_is_not_static
8+
node = Prism.parse_statement("'a' 'b'")
9+
refute_predicate node, :static_literal?
10+
end
11+
712
def test_static_literals
813
assert_warning("1")
914
assert_warning("0xA", "10", "10")

0 commit comments

Comments
 (0)