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.
This commit is contained in:
Jean Boussier 2024-04-11 12:24:05 +02:00 коммит произвёл Kevin Newton
Родитель b2f8de3d9d
Коммит 9183101aa7
2 изменённых файлов: 79 добавлений и 1 удалений

Просмотреть файл

@ -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);

Просмотреть файл

@ -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