From: Yusuke ENDOH Date: 2009-07-12T15:29:05+09:00 Subject: [ruby-core:24292] Re: [Bug #1747] Immediate Values Can be Frozen Hi, 2009/7/11 Run Paint Run Run : > Defining instance methods on Fixnum instances seems a particularly contrived case, even for ruby-core. ;-) Please don't count on me so much ;-) > Triskadekaphobiacs are presumably upset that, although 13.untrust appears to succeed and reinforce their beliefs, the state doesn't stick; 13.untrusted? subsequently returns false. Similarly, logicians and cynics alike must, respectively, rejoice and despair that `true.untrust.untrusted?` is perpetually false. Whoa! The current behavior of 1.9 is never reasonable. Here is a patch: Index: object.c =================================================================== --- object.c (revision 24034) +++ object.c (working copy) @@ -641,6 +641,8 @@ return Qnil; } +static st_table *immediate_tainted_tbl = 0; + /* * call-seq: * obj.tainted? => true or false @@ -653,6 +655,10 @@ { if (OBJ_TAINTED(obj)) return Qtrue; + if (SPECIAL_CONST_P(obj)) { + if (!immediate_tainted_tbl) return Qfalse; + if (st_lookup(immediate_tainted_tbl, obj, 0)) return Qtrue; + } return Qfalse; } @@ -674,6 +680,12 @@ rb_error_frozen("object"); } OBJ_TAINT(obj); + if (SPECIAL_CONST_P(obj)) { + if (!immediate_tainted_tbl) { + immediate_tainted_tbl = st_init_numtable(); + } + st_insert(immediate_tainted_tbl, obj, (st_data_t)Qtrue); + } } return obj; } @@ -696,9 +708,14 @@ } FL_UNSET(obj, FL_TAINT); } + if (SPECIAL_CONST_P(obj) && immediate_tainted_tbl) { + st_delete(immediate_tainted_tbl, &obj, NULL); + } return obj; } +static st_table *immediate_untrusted_tbl = 0; + /* * call-seq: * obj.untrusted? => true or false @@ -711,6 +728,10 @@ { if (OBJ_UNTRUSTED(obj)) return Qtrue; + if (SPECIAL_CONST_P(obj)) { + if (!immediate_untrusted_tbl) return Qfalse; + if (st_lookup(immediate_untrusted_tbl, obj, 0)) return Qtrue; + } return Qfalse; } @@ -730,6 +751,12 @@ rb_error_frozen("object"); } OBJ_UNTRUST(obj); + if (SPECIAL_CONST_P(obj)) { + if (!immediate_untrusted_tbl) { + immediate_untrusted_tbl = st_init_numtable(); + } + st_insert(immediate_untrusted_tbl, obj, (st_data_t)Qtrue); + } } return obj; } @@ -752,6 +779,9 @@ } FL_UNSET(obj, FL_UNTRUSTED); } + if (SPECIAL_CONST_P(obj) && immediate_untrusted_tbl) { + st_delete(immediate_untrusted_tbl, &obj, NULL); + } return obj; } Maybe it is best to freeze all immediates (+ bignum) by default. If Gary's example is needed at any cost, it can probably be rewrited without using instance variables. class Fixnum h = {} define_method(:note=) {|x| h[self] = x } define_method(:note) { h[self] } end 42.note = "the answer" p 42.note At any rate, I think that this is a talk about the future, perhaps after Ruby 2.0. -- Yusuke ENDOH