Bug #1137
closedI can modify literals
Description
=begin
遠藤です。
ObjectSpace を使うと種々のリテラルを書き換えることができてしまうようですが、
仕様でしょうか。
def foo
"foobarbaz"
end
ObjectSpace.each_object(String) do |s|
s.replace("evil") if /foobarbaz/ =~ s && !s.frozen?
end
p foo #=> "evil"
def bar
ls -l
end
ObjectSpace.each_object(String) do |s|
s.replace("echo rm -rf /") if /ls -l/ =~ s && !s.frozen?
end
p bar #=> "rm -rf /\n"
バグだとして、リテラルを freeze するパッチを書きましたが、IRC では
- freeze で解決するのが正しいやり方なのか
- freeze しても finalizer が付け替えできるのではないか
という感じの指摘がありました。どう直すのがよいでしょう。
Index: compile.c¶
--- compile.c (revision 22217)
+++ compile.c (working copy)
@@ -2120,7 +2120,7 @@
int cnt = 1;
debugp_param("nd_lit", lit);
- ADD_INSN1(ret, nd_line(node), putobject, node->nd_lit);
-
ADD_INSN1(ret, nd_line(node), putobject, rb_obj_freeze(node->nd_lit));
while (list) {
COMPILE(ret, "each string", list->nd_head);
@@ -2236,6 +2236,7 @@
rb_ary_push(ary, node->nd_head->nd_lit);
node = node->nd_next;
} -
rb_obj_freeze(ary); iseq_add_mark_object_compile_time(iseq, ary); ADD_INSN1(ret, nd_line(node_root), duparray, ary);
@@ -2708,7 +2709,7 @@
if (estr != 0) {
if (needstr != Qfalse) {
-
VALUE str = rb_str_new2(estr);
-
}VALUE str = rb_obj_freeze(rb_str_new2(estr)); ADD_INSN1(ret, nd_line(node), putstring, str); iseq_add_mark_object_compile_time(iseq, str);
@@ -4353,7 +4354,7 @@
case NODE_STR:{
debugp_param("nd_lit", node->nd_lit);
if (!poped) {
-
ADD_INSN1(ret, nd_line(node), putstring, node->nd_lit);
-
}ADD_INSN1(ret, nd_line(node), putstring, rb_obj_freeze(node->nd_lit));
break;
}
@@ -4367,7 +4368,7 @@
}
case NODE_XSTR:{
ADD_CALL_RECEIVER(ret, nd_line(node));
- ADD_INSN1(ret, nd_line(node), putobject, node->nd_lit);
-
ADD_INSN1(ret, nd_line(node), putobject, rb_obj_freeze(node->nd_lit));
ADD_CALL(ret, nd_line(node), ID2SYM(idBackquote), INT2FIX(1));if (poped) {
--
Yusuke ENDOH mame@tsg.ne.jp
=end