ruby-changes:31863
From: glass <ko1@a...>
Date: Sun, 1 Dec 2013 14:29:01 +0900 (JST)
Subject: [ruby-changes:31863] glass:r43942 (trunk): * hash.c (rb_hash_rehash): fix to free new st_table when exception
glass 2013-12-01 14:28:54 +0900 (Sun, 01 Dec 2013) New Revision: 43942 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=43942 Log: * hash.c (rb_hash_rehash): fix to free new st_table when exception is raised in do_hash(). [Bug #9187] Modified files: trunk/ChangeLog trunk/hash.c Index: ChangeLog =================================================================== --- ChangeLog (revision 43941) +++ ChangeLog (revision 43942) @@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Sun Dec 1 14:15:36 2013 Masaki Matsushita <glass.saga@g...> + + * hash.c (rb_hash_rehash): fix to free new st_table when exception + is raised in do_hash(). [Bug #9187] + Sun Dec 1 11:57:59 2013 Zachary Scott <e@z...> * ext/openssl/lib/openssl/buffering.rb: Fix warning in copyright Index: hash.c =================================================================== --- hash.c (revision 43941) +++ hash.c (revision 43942) @@ -576,6 +576,11 @@ rb_hash_s_try_convert(VALUE dummy, VALUE https://github.com/ruby/ruby/blob/trunk/hash.c#L576 return rb_check_hash_type(hash); } +struct rehash_arg { + VALUE hash; + st_table *tbl; +}; + static int rb_hash_rehash_i(VALUE key, VALUE value, VALUE arg) { @@ -585,6 +590,14 @@ rb_hash_rehash_i(VALUE key, VALUE value, https://github.com/ruby/ruby/blob/trunk/hash.c#L590 return ST_CONTINUE; } +static VALUE +rehash_func(VALUE arg) +{ + struct rehash_arg *p = (struct rehash_arg *)arg; + rb_hash_foreach(p->hash, rb_hash_rehash_i, (VALUE)p->tbl); + return Qnil; +} + /* * call-seq: * hsh.rehash -> hsh @@ -608,18 +621,30 @@ rb_hash_rehash_i(VALUE key, VALUE value, https://github.com/ruby/ruby/blob/trunk/hash.c#L621 static VALUE rb_hash_rehash(VALUE hash) { - st_table *tbl; + int state; + struct rehash_arg arg; + st_table *new_tbl, *old_tbl = RHASH(hash)->ntbl; if (RHASH_ITER_LEV(hash) > 0) { rb_raise(rb_eRuntimeError, "rehash during iteration"); } rb_hash_modify_check(hash); - if (!RHASH(hash)->ntbl) - return hash; - tbl = st_init_table_with_size(RHASH(hash)->ntbl->type, RHASH(hash)->ntbl->num_entries); - rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tbl); - st_free_table(RHASH(hash)->ntbl); - RHASH(hash)->ntbl = tbl; + if (!old_tbl) return hash; + + new_tbl = st_init_table_with_size(old_tbl->type, old_tbl->num_entries); + arg.hash = hash; + arg.tbl = new_tbl; + + rb_protect(rehash_func, (VALUE)&arg, &state); + + if (state) { + st_free_table(new_tbl); + rb_jump_tag(state); + } + else { + st_free_table(RHASH(hash)->ntbl); + RHASH(hash)->ntbl = new_tbl; + } return hash; } -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/