[Bug:trunk] I can modify literals

e$B1sF#$G$9!#e(B

ObjectSpace
e$B$r;H$&$H<o!9$N%j%F%i%k$r=q$-49$($k$3$H$,$G$-$F$7$^$&$h$&$G$9$,!"e(B
e$B;EMM$G$7$g$&$+!#e(B

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”

e$B%P%0$@$H$7$F!"%j%F%i%k$re(B freeze
e$B$9$k%Q%C%A$r=q$-$^$7$?$,!"e(BIRC e$B$G$Oe(B

  • freeze e$B$G2r7h$9$k$N$,@5$7$$$d$jJ}$J$N$+e(B
  • freeze e$B$7$F$be(B finalizer e$B$,IU$1BX$($G$-$k$N$G$O$J$$$+e(B

e$B$H$$$&46$8$N;XE&$,$"$j$^$7$?!#$I$&D>$9$N$,$h$$$G$7$g$&!#e(B

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) {

e$B!!$5$5$@$G$9!%e(B

Yusuke ENDOH wrote::

ObjectSpace e$B$r;H$&$H<o!9$N%j%F%i%k$r=q$-49$($k$3$H$,$G$-$F$7$^$&$h$&$G$9$,!"e(B
e$B;EMM$G$7$g$&$+!#e(B

e$B!!B>$K$b!$e(BRegexp e$B$J$I$Ne(B Immutable
e$B$H8@$o$l$F$k%%V%8%’%/%H$K>!<j$KFC0[%ae(B
e$B%=%C%I$J$j$rDI2C$G$-$A$c$&!$$H$+$b$"$j$^$9!%e(BRegexp
e$B$J$s$+$O!$%j%F%i%k$Ge(B
e$BKh2sF1$8%
%V%8%’%/%H$rJV$9$N$G!$;EMME*$K$O$I$&2r7h$7$?$b$N$@$+!J$3$l$O$=e(B
e$B$N$^$^$H$9$k$N$,;EMM$+$b$7$l$J$$!K!%1F6A$H$7$F$Q$C$H;W$$$D$/$N$O!$62$/$Je(B
e$B$$$s$G$9$,e(B Marshal e$B$r$5$;$J$$$h$&$K$9$k$h$&$J7y$,$i$;$G$9!%e(B

def xyzzy
p Marshal.dump(/xyzzy/)
end

ObjectSpace.each_object(Regexp){|e|
if /xyzzy/ =~ e.to_s
unless e.frozen?
begin
def e.foo
end
rescue TypeError
p e
end
e.instance_eval{
@a = 1
}
end
end
}

xyzzy #=> singleton can’t be dumped (TypeError)

e$B!!$J$*!$$$$?$@$$$?%Q%C%A$K$D$$$F$O!$0J2<$N$h$&$J$[$&$,3N<B$+$J$!!$$J$s$Fe(B
e$B;W$$$^$7$?!%e(B

Index: compile.c

— compile.c (e$B%j%S%8%g%se(B 22118)
+++ compile.c (e$B:n6H%3%T!<e(B)
@@ -398,6 +398,13 @@
iseq_add_mark_object(rb_iseq_t *iseq, VALUE v)
{
if (!SPECIAL_CONST_P(v)) {

  • switch (BUILTIN_TYPE(v)) {
  • case T_STRING:
  • case T_ARRAY:
  •  dp(v);
    
  •  rb_obj_freeze(v);
    
  • }
  • rb_ary_push(iseq->mark_ary, v);
    }
    return COMPILE_OK;

e$B!!$5$5$@$G$9!%e(B

SASADA Koichi wrote::

  • case T_ARRAY:
  •  dp(v);
    

e$B!!$3$N9T!$>C$7K:$l$^$7$?!%e(B

e$B$3$s$K$A$O!"$J$+$`$ie(B(e$B$&e(B)e$B$G$9!#e(B

In message “[ruby-dev:37959] [Bug:trunk] I can modify literals”
on Feb.11,2009 02:16:05, [email protected] wrote:

e$B%P%0$@$H$7$F!"%j%F%i%k$re(B freeze e$B$9$k%Q%C%A$r=q$-$^$7$?$,!"e(BIRC e$B$G$Oe(B

  • freeze e$B$G2r7h$9$k$N$,@5$7$$$d$jJ}$J$N$+e(B
  • freeze e$B$7$F$be(B finalizer e$B$,IU$1BX$($G$-$k$N$G$O$J$$$+e(B

e$B$H$$$&46$8$N;XE&$,$"$j$^$7$?!#$I$&D>$9$N$,$h$$$G$7$g$&!#e(B

e$B85$NLdBj$b5$$K$J$j$^$9$,!“e(Bfrozene$B$J%%V%8%'%/%H$KBP$7$Fe(Bfinalizer
e$B$rIU$1BX$($G$-$F$7$^$&$3$H$,5$$K$J$j$^$9!#e(B
e$B<B:]$K$Oe(BObjectSpacee$B$NA:n$G$"$k$3$H$d!"e(Bfinalizere$B$+$i$O85$N%*e(B e$B%V%8%'%/%H$=$N$b$N$NA:n$,$G$-$k$o$1$G$O$J$$$3$H$J$I$,M}M3$Je(B
e$B$N$G$O$J$$$+$H$O;W$$$^$9$,!"IU$1BX$($NA`:n<+BN$O%
%V%8%'%/%He(B
e$B$NFbIt%U%i%0$rJQ99$7$F$$$k$N$Ge(B(e$B$”$l!"<h$j=|$/$H$-JQ99$7$F$J$$e(B
e$B$Je(B)e$B!"6X;_$7$F$b$$$$$N$G$O$J$$$+$H$$$&5$$b$7$^$9!#e(B

Index: gc.c

— gc.c (revision 22185)
+++ gc.c (working copy)
@@ -2261,9 +2261,11 @@ static VALUE
undefine_final(VALUE os, VALUE obj)
{
rb_objspace_t *objspace = &rb_objspace;

  • if (OBJ_FROZEN(obj)) rb_error_frozen(“object”);
    if (finalizer_table) {
    st_delete(finalizer_table, (st_data_t*)&obj, 0);
    }
  • FL_UNSET(obj, FL_FINALIZE);
    return obj;
    }

@@ -2283,6 +2285,7 @@ define_final(int argc, VALUE *argv, VALU
VALUE obj, block, table;

 rb_scan_args(argc, argv, "11", &obj, &block);
  • if (OBJ_FROZEN(obj)) rb_error_frozen(“object”);
    if (argc == 1) {
    block = rb_block_proc();
    }

e$B$=$l$G$O!#e(B

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:37964] Re: [Bug:trunk] I can modify literals”
on Wed, 11 Feb 2009 16:11:06 +0900, “U.Nakamura”
[email protected] writes:

|e$B85$NLdBj$b5$$K$J$j$^$9$,!“e(Bfrozene$B$J%%V%8%'%/%H$KBP$7$Fe(Bfinalizer
|e$B$rIU$1BX$($G$-$F$7$^$&$3$H$,5$$K$J$j$^$9!#e(B
|e$B<B:]$K$Oe(BObjectSpacee$B$NA:n$G$"$k$3$H$d!"e(Bfinalizere$B$+$i$O85$N%*e(B |e$B%V%8%'%/%H$=$N$b$N$NA:n$,$G$-$k$o$1$G$O$J$$$3$H$J$I$,M}M3$Je(B
|e$B$N$G$O$J$$$+$H$O;W$$$^$9$,!"IU$1BX$($NA`:n<+BN$O%
%V%8%'%/%He(B
|e$B$NFbIt%U%i%0$rJQ99$7$F$$$k$N$Ge(B(e$B$”$l!"<h$j=|$/$H$-JQ99$7$F$J$$e(B
|e$B$Je(B)e$B!"6X;_$7$F$b$$$$$N$G$O$J$$$+$H$$$&5$$b$7$^$9!#e(B

e$B$=$&$G$7$g$&$M!#%3%_%C%H$7$F$/$@$5$$!#85$NLdBj$NJ}$Oe(B…e$B$&!<e(B
e$B$s!"$I$&$7$h$&!#e(B

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:37959] [Bug:trunk] I can modify literals”
on Wed, 11 Feb 2009 02:16:05 +0900, Yusuke ENDOH [email protected]
writes:

|ObjectSpace e$B$r;H$&$H<o!9$N%j%F%i%k$r=q$-49$($k$3$H$,$G$-$F$7$^$&$h$&$G$9$,!"e(B
|e$B;EMM$G$7$g$&$+!#e(B

e$B$&!<$s!“e(BObjectSpacee$B$C$F$N$O$+$J$jN"5;$J$s$G!”$=$l$r;H$C$Fe(B
e$B!V$^$:$$$3$H!W$,$G$-$?>l9g!“$=$l$r;EMM$H8F$V$N$b%P%0$H8F$V$Ne(B
e$B$bDq93$,$”$j$^$9!#e(B

|e$B%P%0$@$H$7$F!"%j%F%i%k$re(B freeze e$B$9$k%Q%C%A$r=q$-$^$7$?$,!“e(BIRC e$B$G$Oe(B
|
| - freeze e$B$G2r7h$9$k$N$,@5$7$$$d$jJ}$J$N$+e(B
| - freeze e$B$7$F$be(B finalizer e$B$,IU$1BX$($G$-$k$N$G$O$J$$$+e(B
|
|e$B$H$$$&46$8$N;XE&$,$”$j$^$7$?!#$I$&D>$9$N$,$h$$$G$7$g$&!#e(B

e$B8e<T$O$&$5$5$s$KD>$7$F$b$i$$$^$7$?!#A0<T$K$D$$$F$Oe(B

  • ObjectSpacee$B$ON"5;!#$d$kJ}$,0-$$e(B(e$B$+$i%P%0$8$c$J$$e(B)
  • e$B6X;$G$-$k$b$N$J$i6X;$7$?J}$,$h$$e(B(e$B$+$i%P%0e(B)

e$B$NN>J}$N9M$(J}$,$G$-$k$H;W$$$^$9!#e(B

e$B$$$m$$$m9M$($^$7$?$,!“2a5n$K$be(BObjectSpacee$B$N!V$^$:$$$3$H!W$Ke(B
e$B<jEv$F$7$F$-$?7P0^$,$”$j$^$9$7!"%P%0$H$_$J$9$3$H$K$7$^$9!#$G!"e(B
e$B$=$N>l9g$N=$@5J}K!$G$9$,!"e(Bfreezee$B$G9=$o$J$$$H;W$$$^$9!#e(B

e$B%Q%C%A$r%3%_%C%H$7$F$/$@$5$$!#e(B

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:37971] Re: [Bug:trunk] I can modify literals”
on Thu, 12 Feb 2009 11:35:16 +0900, Nobuyoshi N.
[email protected] writes:

|freezee$B0JA0$K!“e(BObjectSpacee$B$+$iIT2D;k$G$”$k$Y$-$G$O$J$$$+$H;W$$$^e(B
|e$B$9!#$^$?!“1#$7%*%V%8%'%/%H$+$iDL>o$Ne(BStringe$B$r:n$k$?$a$Ke(B
|rb_str_replace()e$B$r;H$C$F$$$^$9$,!”$3$l$Oe(Bintern.he$B$G8x3+$7$F$b$+$^e(B
|e$B$o$J$$$s$G$O$J$$$G$7$g$&$+!#e(B

e$B$&!<$s!“$=$&$+$”!#$s$8$c$“!”$H$j$"$($:IT2D;k$K$7$F$*$$$F$/$@e(B
e$B$5$$!#$=$l$O$=$l$H$7$Fe(Bfreezee$B$7$F$bNI$$$h$&$J5$$b$7$^$9$,!#e(B

e$B$J$+$@$G$9!#e(B

At Thu, 12 Feb 2009 10:34:51 +0900,
Yukihiro M. wrote in [ruby-dev:37969]:

  • ObjectSpacee$B$ON"5;!#$d$kJ}$,0-$$e(B(e$B$+$i%P%0$8$c$J$$e(B)
  • e$B6X;$G$-$k$b$N$J$i6X;$7$?J}$,$h$$e(B(e$B$+$i%P%0e(B)

e$B$NN>J}$N9M$(J}$,$G$-$k$H;W$$$^$9!#e(B

e$B$$$m$$$m9M$($^$7$?$,!“2a5n$K$be(BObjectSpacee$B$N!V$^$:$$$3$H!W$Ke(B
e$B<jEv$F$7$F$-$?7P0^$,$”$j$^$9$7!"%P%0$H$_$J$9$3$H$K$7$^$9!#$G!"e(B
e$B$=$N>l9g$N=$@5J}K!$G$9$,!"e(Bfreezee$B$G9=$o$J$$$H;W$$$^$9!#e(B

freezee$B0JA0$K!“e(BObjectSpacee$B$+$iIT2D;k$G$”$k$Y$-$G$O$J$$$+$H;W$$$^e(B
e$B$9!#$^$?!“1#$7%*%V%8%’%/%H$+$iDL>o$Ne(BStringe$B$r:n$k$?$a$Ke(B
rb_str_replace()e$B$r;H$C$F$$$^$9$,!”$3$l$Oe(Bintern.he$B$G8x3+$7$F$b$+$^e(B
e$B$o$J$$$s$G$O$J$$$G$7$g$&$+!#e(B

Index: compile.c

— compile.c (revision 22249)
+++ compile.c (working copy)
@@ -296,4 +296,5 @@ PRINTF_ARGS(void ruby_debug_printf(const
(name##body_.last = &name##body_.anchor, name = &name##body_)

+#define hide_obj(obj) (void)(RBASIC(obj)->klass = 0)

#include “optinsn.inc”
@@ -2231,5 +2232,5 @@ compile_array_(rb_iseq_t *iseq, LINK_ANC
if (opt_p == Qtrue) {
if (!poped) {

  •  VALUE ary = rb_ary_new();
    
  •  VALUE ary = rb_ary_tmp_new(len);
     node = node_root;
     while (node) {
    

@@ -2710,4 +2711,5 @@ defined_expr(rb_iseq_t *iseq, LINK_ANCHO
if (needstr != Qfalse) {
VALUE str = rb_str_new2(estr);

  •  hide_obj(str);
     ADD_INSN1(ret, nd_line(node), putstring, str);
     iseq_add_mark_object_compile_time(iseq, str);
    

@@ -4354,4 +4356,5 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_
debugp_param(“nd_lit”, node->nd_lit);
if (!poped) {

  •  hide_obj(node->nd_lit);
     ADD_INSN1(ret, nd_line(node), putstring, node->nd_lit);
    
    }
    Index: string.c
    ===================================================================
    — string.c (revision 22249)
    +++ string.c (working copy)
    @@ -816,6 +816,4 @@ rb_obj_as_string(VALUE obj)
    }

-static VALUE rb_str_replace(VALUE, VALUE);

VALUE
rb_str_dup(VALUE str)
@@ -3723,5 +3721,5 @@ rb_str_gsub(int argc, VALUE *argv, VALUE
*/

-static VALUE
+VALUE
rb_str_replace(VALUE str, VALUE str2)
{
Index: insns.def

— insns.def (revision 22249)
+++ insns.def (working copy)
@@ -374,5 +374,6 @@ putstring
(VALUE val)
{

  • val = rb_str_new3(str);
  • VALUE rb_str_replace(VALUE, VALUE);
  • val = rb_str_replace(rb_str_new(0, 0), str);
    }

@@ -461,5 +462,5 @@ duparray
(VALUE val)
{

  • val = rb_ary_dup(ary);
  • val = rb_ary_replace(rb_ary_new2(0), ary);
    }

Index: include/ruby/intern.h

— include/ruby/intern.h (revision 22249)
+++ include/ruby/intern.h (working copy)
@@ -618,4 +618,5 @@ VALUE rb_str_equal(VALUE str1, VALUE str
VALUE rb_str_drop_bytes(VALUE, long);
void rb_str_update(VALUE, long, long, VALUE);
+VALUE rb_str_replace(VALUE, VALUE);
VALUE rb_str_inspect(VALUE);
VALUE rb_str_dump(VALUE);

e$B%A%1%C%He(B #1137 e$B$,99?7$5$l$^$7$?!#e(B (by Nobuyoshi N.)

e$B%9%F!<%?%9e(B Opene$B$+$ie(BClosede$B$KJQ99e(B
e$B?JD=e(B % 0e$B$+$ie(B100e$B$KJQ99e(B

Applied in changeset r22255.

http://redmine.ruby-lang.org/issues/show/1137

e$B!!$5$5$@$G$9!%e(B

e$B!!e(Brb_replace e$B$r;H$&$s$8$c$J$/$F!$?7$7$$e(B API
e$B$r:n$k$N$O$I$&$G$7$g$&!%e(B
rb
_from()
e$B$H$$$&L>A0$O!$8e$G8e2y$7$=$&$J5$$O$7$^$9!%$b$C$HE%=-$$L>A0$Ne(B
e$BJ}$,$$$$$+$b!%e(B

Index: array.c

— array.c (e$B%j%S%8%g%se(B 22272)
+++ array.c (e$B:n6H%3%T!<e(B)
@@ -1468,6 +1468,12 @@ rb_ary_dup(VALUE ary)
return dup;
}

+VALUE
+rb_ary_new_from(VALUE ary)
+{

  • return rb_ary_new4(RARRAY_LEN(ary), RARRAY_PTR(ary));
    +}

extern VALUE rb_output_fs;

static VALUE
Index: insns.def

— insns.def (e$B%j%S%8%g%se(B 22272)
+++ insns.def (e$B:n6H%3%T!<e(B)
@@ -373,7 +373,7 @@ putstring
()
(VALUE val)
{

  • val = rb_str_replace(rb_str_new(0, 0), str);
  • val = rb_str_new_from(str);
    }

/**
@@ -460,7 +460,7 @@ duparray
()
(VALUE val)
{

  • val = rb_ary_replace(rb_ary_new2(0), ary);
  • val = rb_ary_new_from(ary);
    }

/**
Index: vm_core.h

— vm_core.h (e$B%j%S%8%g%se(B 22272)
+++ vm_core.h (e$B:n6H%3%T!<e(B)
@@ -598,6 +598,9 @@ NOINLINE(void rb_gc_save_machine_context

#define sysstack_error
GET_VM()->special_exceptions[ruby_error_sysstack]

+VALUE rb_str_new_from(VALUE str);
+VALUE rb_ary_new_from(VALUE ary);
+
/* for thread */

#if RUBY_VM_THREAD_MODEL == 2
Index: iseq.c

— iseq.c (e$B%j%S%8%g%se(B 22272)
+++ iseq.c (e$B:n6H%3%T!<e(B)
@@ -704,7 +704,7 @@ insn_operand_intern(rb_iseq_t *iseq,
if (hidden_obj_p(op)) {
switch (BUILTIN_TYPE(op)) {
case T_STRING:

  • op = rb_str_replace(rb_str_new(0, 0), op);
  • op = rb_str_new_from(op);
    break;
    case T_ARRAY:
    op = rb_ary_replace(rb_ary_new2(0), op);
    Index: string.c
    ===================================================================
    — string.c (e$B%j%S%8%g%se(B 22272)
    +++ string.c (e$B:n6H%3%T!<e(B)
    @@ -829,6 +829,11 @@ rb_str_dup(VALUE str)
    return str_duplicate(rb_obj_class(str), str);
    }

+VALUE
+rb_str_new_from(VALUE str)
+{

  • return rb_str_replace(str_alloc(rb_cString), str);
    +}

/*

  • call-seq:

e$B!!$5$5$@$G$9!%e(B

Yukihiro M. wrote::

|freezee$B0JA0$K!“e(BObjectSpacee$B$+$iIT2D;k$G$”$k$Y$-$G$O$J$$$+$H;W$$$^e(B
|e$B$9!#$^$?!“1#$7%*%V%8%’%/%H$+$iDL>o$Ne(BStringe$B$r:n$k$?$a$Ke(B
|rb_str_replace()e$B$r;H$C$F$$$^$9$,!”$3$l$Oe(Bintern.he$B$G8x3+$7$F$b$+$^e(B
|e$B$o$J$$$s$G$O$J$$$G$7$g$&$+!#e(B

e$B$&!<$s!"$=$&$+$"!#$s$8$c$"!"$H$j$"$($:IT2D;k$K$7$F$*$$$F$/$@e(B
e$B$5$$!#$=$l$O$=$l$H$7$Fe(Bfreezee$B$7$F$bNI$$$h$&$J5$$b$7$^$9$,!#e(B

e$B!!$5$i$Ke(B freeze
e$B$9$kM}M3$O$J$s$G$7$g$&$+!%$7$J$$M}M3$b$J$$$H;W$$$^$9$,!$e(B
e$B$9$kM}M3$b$J$$$h$&$J!%e(B

SASADA Koichi wrote::

e$B$9$kM}M3$b$J$$$h$&$J!%e(B
e$B!!$"$H!$5U$Ke(B freeze
e$B$9$l$PIT2D;k$K$9$kI,MW$b$J$$$+$J!<$H$b;W$$$^$9$,!$$Ie(B
e$B$s$J$b$s$G$9$+$M!JIT2D;k$K$9$k$Y$-%%V%8%’%/%H$b$"$C$?$1$l$I$b!K!%<B9T%3e(B
e$B%9%HE
$K$Oe(B freeze e$B$N$[$&$,7Z$=$&$G$9$,!%e(B

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:37985] Re: [Bug:trunk] I can modify literals”
on Fri, 13 Feb 2009 06:36:47 +0900, SASADA Koichi [email protected]
writes:

|> e$B!!$5$i$Ke(B freeze e$B$9$kM}M3$O$J$s$G$7$g$&$+!%$7$J$$M}M3$b$J$$$H;W$$$^$9$,!$e(B
|> e$B$9$kM}M3$b$J$$$h$&$J!%e(B
|
|e$B!!$"$H!$5U$Ke(B freeze e$B$9$l$PIT2D;k$K$9$kI,MW$b$J$$$+$J!<$H$b;W$$$^$9$,!$$Ie(B
|e$B$s$J$b$s$G$9$+$M!JIT2D;k$K$9$k$Y$-%%V%8%'%/%H$b$"$C$?$1$l$I$b!K!%<B9T%3e(B
|e$B%9%HE
$K$Oe(B freeze e$B$N$[$&$,7Z$=$&$G$9$,!%e(B

e$B$^$:IT2D;k$K$9$kJ}$,!V$+$C$3$$$$!W$N$G$=$C$A$NJ}$rA*$S$?$$$He(B
e$B$3$m$G$9!#:G=i$+$i;W$$$D$/$Y$-$@$C$?$+$b$7$l$^$;$s!#e(Bfreezee$B$9e(B
e$B$k$N$O!"$^$"4V0c$$$rAa$a$K8+$D$1$i$l$?$i$$$$$s$8$c$J$$!"DxEYe(B
e$B$NM}M3$G$9!#e(B