From 68f96f6c3c05385a5b47395b82e619f9c06b0437 Mon Sep 17 00:00:00 2001 From: ko1 Date: Wed, 29 May 2013 01:38:52 +0000 Subject: * 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(). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40979 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- hash.c | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) (limited to 'hash.c') diff --git a/hash.c b/hash.c index 67759b61cd..a8950efdce 100644 --- a/hash.c +++ b/hash.c @@ -1193,14 +1193,23 @@ rb_hash_clear(VALUE hash) 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) 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 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, st_data_t *key, st_data_t *value, st_da 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; } -- cgit v1.2.3