From 0aa1d61ab95befe0d8e68ebe86e238a09a8c11c5 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 4 Apr 2024 14:51:49 -0400 Subject: [PATCH] [PRISM] Ensure unfrozen when interpolation is present in string literal --- prism_compile.c | 62 ++++++++++++++++++-------------- test/.excludes-prism/TestISeq.rb | 1 - 2 files changed, 36 insertions(+), 27 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 4ed37be840..a26962cb94 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -322,6 +322,7 @@ pm_interpolated_node_compile(rb_iseq_t *iseq, const pm_node_list_t *parts, const { int stack_size = 0; size_t parts_size = parts->size; + bool interpolated = false; if (parts_size > 0) { VALUE current_string = Qnil; @@ -340,41 +341,51 @@ pm_interpolated_node_compile(rb_iseq_t *iseq, const pm_node_list_t *parts, const current_string = string_value; } } - else if ( - PM_NODE_TYPE_P(part, PM_EMBEDDED_STATEMENTS_NODE) && - ((const pm_embedded_statements_node_t *) part)->statements != NULL && - ((const pm_embedded_statements_node_t *) part)->statements->body.size == 1 && - PM_NODE_TYPE_P(((const pm_embedded_statements_node_t *) part)->statements->body.nodes[0], PM_STRING_NODE) - ) { - const pm_string_node_t *string_node = (const pm_string_node_t *) ((const pm_embedded_statements_node_t *) part)->statements->body.nodes[0]; - VALUE string_value = parse_string_encoded(scope_node, (const pm_node_t *) string_node, &string_node->unescaped); + else { + interpolated = true; - if (RTEST(current_string)) { - current_string = rb_str_concat(current_string, string_value); + if ( + PM_NODE_TYPE_P(part, PM_EMBEDDED_STATEMENTS_NODE) && + ((const pm_embedded_statements_node_t *) part)->statements != NULL && + ((const pm_embedded_statements_node_t *) part)->statements->body.size == 1 && + PM_NODE_TYPE_P(((const pm_embedded_statements_node_t *) part)->statements->body.nodes[0], PM_STRING_NODE) + ) { + const pm_string_node_t *string_node = (const pm_string_node_t *) ((const pm_embedded_statements_node_t *) part)->statements->body.nodes[0]; + VALUE string_value = parse_string_encoded(scope_node, (const pm_node_t *) string_node, &string_node->unescaped); + + if (RTEST(current_string)) { + current_string = rb_str_concat(current_string, string_value); + } + else { + current_string = string_value; + } } else { - current_string = string_value; - } - } - else { - if (!RTEST(current_string)) { - current_string = rb_enc_str_new(NULL, 0, scope_node->encoding); - } + if (!RTEST(current_string)) { + current_string = rb_enc_str_new(NULL, 0, scope_node->encoding); + } - PUSH_INSN1(ret, *node_location, putobject, rb_fstring(current_string)); - PM_COMPILE_NOT_POPPED(part); - PUSH_INSN(ret, *node_location, dup); - PUSH_INSN1(ret, *node_location, objtostring, new_callinfo(iseq, idTo_s, 0, VM_CALL_FCALL | VM_CALL_ARGS_SIMPLE , NULL, FALSE)); - PUSH_INSN(ret, *node_location, anytostring); + PUSH_INSN1(ret, *node_location, putobject, rb_fstring(current_string)); + PM_COMPILE_NOT_POPPED(part); + PUSH_INSN(ret, *node_location, dup); + PUSH_INSN1(ret, *node_location, objtostring, new_callinfo(iseq, idTo_s, 0, VM_CALL_FCALL | VM_CALL_ARGS_SIMPLE , NULL, FALSE)); + PUSH_INSN(ret, *node_location, anytostring); - current_string = Qnil; - stack_size += 2; + current_string = Qnil; + stack_size += 2; + } } } if (RTEST(current_string)) { current_string = rb_fstring(current_string); - PUSH_INSN1(ret, *node_location, putobject, current_string); + + if (stack_size == 0 && interpolated) { + PUSH_INSN1(ret, *node_location, putstring, current_string); + } + else { + PUSH_INSN1(ret, *node_location, putobject, current_string); + } current_string = Qnil; stack_size++; @@ -6231,7 +6242,6 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, else { const pm_interpolated_string_node_t *cast = (const pm_interpolated_string_node_t *) node; int length = pm_interpolated_node_compile(iseq, &cast->parts, &location, ret, popped, scope_node); - if (length > 1) PUSH_INSN1(ret, location, concatstrings, INT2FIX(length)); if (popped) PUSH_INSN(ret, location, pop); } diff --git a/test/.excludes-prism/TestISeq.rb b/test/.excludes-prism/TestISeq.rb index b46047bc9e..3768d8fc05 100644 --- a/test/.excludes-prism/TestISeq.rb +++ b/test/.excludes-prism/TestISeq.rb @@ -1,4 +1,3 @@ exclude(:test_each_child, "https://github.com/ruby/prism/issues/2660") -exclude(:test_frozen_string_literal_compile_option, "https://github.com/ruby/prism/issues/2661") exclude(:test_syntax_error_message, "Assertion checks against specific error format") exclude(:test_trace_points, "https://github.com/ruby/prism/issues/2660")