From: ts Date: 2001-08-05T23:22:05+09:00 Subject: [ruby-talk:19167] struct and $SAFE This is normal ? pigeon% cat b.rb #!/usr/bin/ruby cat = Struct.new("Cat", :name, :age, :life) a = cat.new("cat", 12, 7) Thread.new do abort_on_exception = true $SAFE = 4 a.life -= 1 end.join p a.life pigeon% pigeon% b.rb 6 pigeon% It's possible to modify a struct with $SAFE >= 4 (this is very dangerous for cats :-)) pigeon% diff -u struct.c.old struct.c --- struct.c.old Sun Aug 5 15:17:44 2001 +++ struct.c Sun Aug 5 15:35:03 2001 @@ -124,6 +124,15 @@ rb_struct_ref9, }; +static void +rb_struct_modify(s) + VALUE s; +{ + if (OBJ_FROZEN(s)) rb_error_frozen("Struct"); + if (!OBJ_TAINTED(s) && rb_safe_level() >= 4) + rb_raise(rb_eSecurityError, "Insecure: can't modify Struct"); +} + static VALUE rb_struct_set(obj, val) VALUE obj, val; @@ -135,6 +144,7 @@ if (NIL_P(member)) { rb_bug("non-initialized struct"); } + rb_struct_modify(obj); for (i=0; ilen; i++) { slot = RARRAY(member)->ptr[i]; if (rb_id_attrset(SYM2ID(slot)) == rb_frame_last_func()) { @@ -253,6 +263,7 @@ VALUE size; long n; + rb_struct_modify(self); size = iv_get(klass, "__size__"); n = FIX2LONG(size); if (n < RARRAY(values)->len) { @@ -473,7 +484,7 @@ rb_bug("non-initialized struct"); } - if (OBJ_FROZEN(s)) rb_error_frozen("Struct"); + rb_struct_modify(s); len = RARRAY(member)->len; for (i=0; iptr[i]) == id) { @@ -504,7 +515,7 @@ rb_raise(rb_eIndexError, "offset %d too large for struct(size:%d)", i, RSTRUCT(s)->len); } - if (OBJ_FROZEN(s)) rb_error_frozen("Struct"); + rb_struct_modify(s); return RSTRUCT(s)->ptr[i] = val; } pigeon% pigeon% ruby b.rb b.rb:7:in `life=': Insecure: can't modify Struct (SecurityError) from b.rb:4:in `join' from b.rb:4 pigeon% Guy Decoux