Project

General

Profile

Actions

Bug #1137

closed

I can modify literals

Added by mame (Yusuke Endoh) about 15 years ago. Updated about 13 years ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
Backport:
[ruby-dev:37959]

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
=end


Related issues 1 (0 open1 closed)

Related to Ruby master - Bug #2965: method `===' called on hidden T_STRING object (NotImplementedError)Closed03/15/2010Actions
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0