summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean Boussier <byroot@ruby-lang.org>2024-04-11 12:24:05 +0200
committerKevin Newton <kddnewton@gmail.com>2024-04-11 08:08:30 -0400
commit9183101aa7399a56a93045cc85220707bb413218 (patch)
treea19c5643b2d6d6297e03e53de49b7c114a324aac
parentb2f8de3d9d7af9af547c1e290c6e3a4d2658a62e (diff)
prism_compile.c: X_STRING should be frozen
The backtick method recieves a frozen string unless it is interpolated. Otherwise the string held in the ISeq could be mutated by a custom backtick method.
-rw-r--r--prism_compile.c2
-rw-r--r--spec/ruby/language/execution_spec.rb78
2 files changed, 79 insertions, 1 deletions
diff --git a/prism_compile.c b/prism_compile.c
index a26962cb94..3a2f271dd6 100644
--- a/prism_compile.c
+++ b/prism_compile.c
@@ -8352,7 +8352,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
// `foo`
// ^^^^^
const pm_x_string_node_t *cast = (const pm_x_string_node_t *) node;
- VALUE value = parse_string_encoded(scope_node, node, &cast->unescaped);
+ VALUE value = rb_fstring(parse_string_encoded(scope_node, node, &cast->unescaped));
PUSH_INSN(ret, location, putself);
PUSH_INSN1(ret, location, putobject, value);
diff --git a/spec/ruby/language/execution_spec.rb b/spec/ruby/language/execution_spec.rb
index 4e0310946d..ef1de38899 100644
--- a/spec/ruby/language/execution_spec.rb
+++ b/spec/ruby/language/execution_spec.rb
@@ -5,6 +5,45 @@ describe "``" do
ip = 'world'
`echo disc #{ip}`.should == "disc world\n"
end
+
+ it "can be redefined and receive a frozen string as argument" do
+ called = false
+ runner = Object.new
+
+ runner.singleton_class.define_method(:`) do |str|
+ called = true
+
+ str.should == "test command"
+ str.frozen?.should == true
+ end
+
+ runner.instance_exec do
+ `test command`
+ end
+
+ called.should == true
+ end
+
+ it "the argument isn't frozen if it contains interpolation" do
+ called = false
+ runner = Object.new
+
+ runner.singleton_class.define_method(:`) do |str|
+ called = true
+
+ str.should == "test command"
+ str.frozen?.should == false
+ str << "mutated"
+ end
+
+ 2.times do
+ runner.instance_exec do
+ `test #{:command}`
+ end
+ end
+
+ called.should == true
+ end
end
describe "%x" do
@@ -12,4 +51,43 @@ describe "%x" do
ip = 'world'
%x(echo disc #{ip}).should == "disc world\n"
end
+
+ it "can be redefined and receive a frozen string as argument" do
+ called = false
+ runner = Object.new
+
+ runner.singleton_class.define_method(:`) do |str|
+ called = true
+
+ str.should == "test command"
+ str.frozen?.should == true
+ end
+
+ runner.instance_exec do
+ %x{test command}
+ end
+
+ called.should == true
+ end
+
+ it "the argument isn't frozen if it contains interpolation" do
+ called = false
+ runner = Object.new
+
+ runner.singleton_class.define_method(:`) do |str|
+ called = true
+
+ str.should == "test command"
+ str.frozen?.should == false
+ str << "mutated"
+ end
+
+ 2.times do
+ runner.instance_exec do
+ %x{test #{:command}}
+ end
+ end
+
+ called.should == true
+ end
end