diff options
author | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-05-29 01:38:52 +0000 |
---|---|---|
committer | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-05-29 01:38:52 +0000 |
commit | 68f96f6c3c05385a5b47395b82e619f9c06b0437 (patch) | |
tree | 452bc8b75a29b2bc5741cf183af37ea46cb02307 /hash.c | |
parent | 1999571e60d301e01dc4ff041f31ac58ae89fa38 (diff) | |
download | ruby-68f96f6c3c05385a5b47395b82e619f9c06b0437.tar.gz |
* 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
Diffstat (limited to 'hash.c')
-rw-r--r-- | hash.c | 37 |
1 files changed, 32 insertions, 5 deletions
@@ -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; } |