Skip to content

Commit da09b30

Browse files
committed
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 7dbd9c2 commit da09b30

File tree

3 files changed

+15
-6
lines changed

3 files changed

+15
-6
lines changed

prism/prism.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5279,6 +5279,10 @@ pm_interpolated_string_node_append(pm_interpolated_string_node_t *node, pm_node_
52795279

52805280
switch (PM_NODE_TYPE(part)) {
52815281
case PM_STRING_NODE:
5282+
// If inner string is not frozen, clear flags for this string
5283+
if (!PM_NODE_FLAG_P(part, PM_STRING_FLAGS_FROZEN)) {
5284+
CLEAR_FLAGS(node);
5285+
}
52825286
part->flags = (pm_node_flags_t) ((part->flags | PM_NODE_FLAG_STATIC_LITERAL | PM_STRING_FLAGS_FROZEN) & ~PM_STRING_FLAGS_MUTABLE);
52835287
break;
52845288
case PM_INTERPOLATED_STRING_NODE:

prism_compile.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ parse_regexp_concat(rb_iseq_t *iseq, const pm_scope_node_t *scope_node, const pm
556556
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);
557557

558558
static int
559-
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)
559+
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)
560560
{
561561
int stack_size = 0;
562562
size_t parts_size = parts->size;
@@ -666,7 +666,7 @@ pm_interpolated_node_compile(rb_iseq_t *iseq, const pm_node_list_t *parts, const
666666
if (RTEST(current_string)) {
667667
current_string = rb_fstring(current_string);
668668

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

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

@@ -9637,7 +9637,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
96379637
}
96389638
else {
96399639
const pm_interpolated_string_node_t *cast = (const pm_interpolated_string_node_t *) node;
9640-
int length = pm_interpolated_node_compile(iseq, &cast->parts, &location, ret, popped, scope_node, NULL, NULL);
9640+
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));
96419641
if (length > 1) PUSH_INSN1(ret, location, concatstrings, INT2FIX(length));
96429642
if (popped) PUSH_INSN(ret, location, pop);
96439643
}
@@ -9648,7 +9648,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
96489648
// :"foo #{bar}"
96499649
// ^^^^^^^^^^^^^
96509650
const pm_interpolated_symbol_node_t *cast = (const pm_interpolated_symbol_node_t *) node;
9651-
int length = pm_interpolated_node_compile(iseq, &cast->parts, &location, ret, popped, scope_node, NULL, NULL);
9651+
int length = pm_interpolated_node_compile(iseq, &cast->parts, &location, ret, popped, scope_node, NULL, NULL, false);
96529652

96539653
if (length > 1) {
96549654
PUSH_INSN1(ret, location, concatstrings, INT2FIX(length));
@@ -9670,7 +9670,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
96709670

96719671
PUSH_INSN(ret, location, putself);
96729672

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

96769676
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy