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; i<RARRAY(member)->len; 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; i<len; i++) {
if (SYM2ID(RARRAY(member)->ptr[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