ruby-changes:28927
From: ko1 <ko1@a...>
Date: Wed, 29 May 2013 10:39:09 +0900 (JST)
Subject: [ruby-changes:28927] ko1:r40979 (trunk): * hash.c: fix WB bug.
ko1 2013-05-29 10:38:52 +0900 (Wed, 29 May 2013) New Revision: 40979 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=40979 Log: * hash.c: fix WB bug. (1) Hash's key also needs WB. (2) callback parameter *key and *value of st_update() is not a storage of st_table itself (only local variable). So that OBJ_WRITE() is not suitable, especially for `!exsinting'. OBJ_WRITTEN() is used instead of OBJ_WRITE(). Modified files: trunk/ChangeLog trunk/hash.c Index: ChangeLog =================================================================== --- ChangeLog (revision 40978) +++ ChangeLog (revision 40979) @@ -1,3 +1,12 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Wed May 29 10:33:27 2013 Koichi Sasada <ko1@a...> + + * hash.c: fix WB bug. + (1) Hash's key also needs WB. + (2) callback parameter *key and *value of st_update() is not a + storage of st_table itself (only local variable). So that + OBJ_WRITE() is not suitable, especially for `!exsinting'. + OBJ_WRITTEN() is used instead of OBJ_WRITE(). + Tue May 28 12:31:21 2013 Koichi Sasada <ko1@a...> * ext/objspace/object_tracing.c: fix a bug reported at Index: hash.c =================================================================== --- hash.c (revision 40978) +++ hash.c (revision 40979) @@ -1193,14 +1193,23 @@ rb_hash_clear(VALUE hash) https://github.com/ruby/ruby/blob/trunk/hash.c#L1193 static int hash_aset(VALUE hash, st_data_t *key, st_data_t *val, st_data_t arg, int existing) { - OBJ_WRITE(hash, (VALUE *)val, arg); + if (existing) { + OBJ_WRITTEN(hash, *val, arg); + } + else { + OBJ_WRITTEN(hash, Qundef, *key); + OBJ_WRITTEN(hash, Qundef, arg); + } + *val = arg; return ST_CONTINUE; } static int hash_aset_str(VALUE hash, st_data_t *key, st_data_t *val, st_data_t arg, int existing) { - OBJ_WRITE(hash, (VALUE *)key, rb_str_new_frozen((VALUE)*key)); + if (!existing) { + *key = rb_str_new_frozen((VALUE)*key); + } return hash_aset(hash, key, val, arg, existing); } @@ -1879,7 +1888,14 @@ rb_hash_invert(VALUE hash) https://github.com/ruby/ruby/blob/trunk/hash.c#L1888 static int rb_hash_update_callback(VALUE hash, st_data_t *key, st_data_t *value, st_data_t arg, int existing) { - OBJ_WRITE(hash, (VALUE *)value, (VALUE)arg); + if (existing) { + OBJ_WRITTEN(hash, *value, arg); + } + else { + OBJ_WRITTEN(hash, Qundef, *key); + OBJ_WRITTEN(hash, Qundef, arg); + } + *value = arg; return ST_CONTINUE; } @@ -1896,10 +1912,16 @@ static int https://github.com/ruby/ruby/blob/trunk/hash.c#L1912 rb_hash_update_block_callback(VALUE hash, st_data_t *key, st_data_t *value, st_data_t arg, int existing) { VALUE newvalue = (VALUE)arg; + if (existing) { newvalue = rb_yield_values(3, (VALUE)*key, (VALUE)*value, newvalue); + OBJ_WRITTEN(hash, *value, newvalue); } - OBJ_WRITE(hash, (VALUE *)value, newvalue); + else { + OBJ_WRITTEN(hash, Qundef, *key); + OBJ_WRITTEN(hash, Qundef, newvalue); + } + *value = newvalue; return ST_CONTINUE; } @@ -1962,8 +1984,13 @@ rb_hash_update_func_callback(VALUE hash, https://github.com/ruby/ruby/blob/trunk/hash.c#L1984 VALUE newvalue = arg->value; if (existing) { newvalue = (*arg->func)((VALUE)*key, (VALUE)*value, newvalue); + OBJ_WRITTEN(hash, *value, newvalue); + } + else { + OBJ_WRITTEN(hash, Qundef, *key); + OBJ_WRITTEN(hash, Qundef, newvalue); } - OBJ_WRITE(hash, (VALUE *)value, (VALUE)newvalue); + *value = newvalue; return ST_CONTINUE; } -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/