diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2014-04-30 08:06:51 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2014-04-30 08:06:51 +0000 |
commit | 48384bbab7acd23742cd6c516811573eb3ef3c83 (patch) | |
tree | 0143c731047727360a49c10842c6e99667385093 | |
parent | b6d7233d53ac1e12914c705d6811d9ffccc50be1 (diff) | |
download | ruby-48384bbab7acd23742cd6c516811573eb3ef3c83.tar.gz |
parse.y: pin down dynamic symbol only
* parse.y (rb_id_attrset): pin down dynamic symbol only. it is
possibe that attrset ID can be registered as a static symbol
after the corresponding attrget ID has been registered as a
dynamic, and then the latter may be collected.
[ruby-core:62226] [Bug #9787]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@45756 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | parse.y | 29 | ||||
-rw-r--r-- | test/ruby/test_symbol.rb | 18 |
3 files changed, 42 insertions, 13 deletions
@@ -1,3 +1,11 @@ +Wed Apr 30 17:06:49 2014 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * parse.y (rb_id_attrset): pin down dynamic symbol only. it is + possibe that attrset ID can be registered as a static symbol + after the corresponding attrget ID has been registered as a + dynamic, and then the latter may be collected. + [ruby-core:62226] [Bug #9787] + Tue Apr 29 14:17:57 2014 Tanaka Akira <akr@fsij.org> * lib/tmpdir.rb: Rescue LoadError on etc.so for miniruby. @@ -46,6 +46,7 @@ static ID register_static_symid_str(ID, VALUE); #define REGISTER_SYMID(id, name) register_static_symid((id), (name), strlen(name), enc) #include "id.c" #endif +#define ID_DYNAMIC_SYM_P(id) (!(id&ID_STATIC_SYM)&&id>tLAST_TOKEN) static inline int id_type(ID); #define is_notop_id(id) ((id)>tLAST_OP_ID) @@ -8863,7 +8864,11 @@ rb_id_attrset(ID id) str = rb_str_dup(RSYMBOL((VALUE)id)->fstr); rb_str_cat(str, "=", 1); id = (ID)rb_str_dynamic_intern(str); - rb_pin_dynamic_symbol((VALUE)id); + if (ID_DYNAMIC_SYM_P(id)) { + /* attrset ID may have been registered as a static + * symbol */ + rb_pin_dynamic_symbol((VALUE)id); + } } return id; } @@ -10450,6 +10455,15 @@ sym_check_asciionly(VALUE str) */ static ID intern_str(VALUE str); +static void +must_be_dynamic_symbol(VALUE x) +{ + if (SPECIAL_CONST_P(x) || BUILTIN_TYPE(x) != T_SYMBOL) { + rb_raise(rb_eTypeError, "wrong argument type %s (expected Symbol)", + rb_builtin_class_name(x)); + } +} + static VALUE setup_fake_str(struct RString *fake_str, const char *name, long len) { @@ -10461,11 +10475,10 @@ setup_fake_str(struct RString *fake_str, const char *name, long len) return (VALUE)fake_str; } -#define ID_DYNAMIC_SYM_P(id) (!(id&ID_STATIC_SYM)&&id>tLAST_TOKEN) - ID rb_pin_dynamic_symbol(VALUE sym) { + must_be_dynamic_symbol(sym); rb_gc_resurrect(sym); /* stick dynamic symbol */ if (!st_insert(global_symbols.pinned_dsym, sym, (st_data_t)sym)) { @@ -10770,15 +10783,6 @@ lookup_id_str(ID id, st_data_t *data) return FALSE; } -static void -must_be_dynamic_symbol(VALUE x) -{ - if (SPECIAL_CONST_P(x) || BUILTIN_TYPE(x) != T_SYMBOL) { - rb_raise(rb_eTypeError, "wrong argument type %s (expected Symbol)", - rb_builtin_class_name(x)); - } -} - ID rb_sym2id(VALUE x) { @@ -10786,7 +10790,6 @@ rb_sym2id(VALUE x) return RSHIFT((unsigned long)(x),RUBY_SPECIAL_SHIFT); } else { - must_be_dynamic_symbol(x); return rb_pin_dynamic_symbol(x); } } diff --git a/test/ruby/test_symbol.rb b/test/ruby/test_symbol.rb index 686b74d1e7..e74c41cd2d 100644 --- a/test/ruby/test_symbol.rb +++ b/test/ruby/test_symbol.rb @@ -237,4 +237,22 @@ class TestSymbol < Test::Unit::TestCase '', child_env: '--disable-gems') end + + def test_gc_attrset + bug9787 = '[ruby-core:62226] [Bug #9787]' + assert_normal_exit(<<-'end;', '', child_env: '--disable-gems') + def noninterned_name(prefix = "") + prefix += "_#{Thread.current.object_id.to_s(36).tr('-', '_')}" + begin + name = "#{prefix}_#{rand(0x1000).to_s(16)}_#{Time.now.usec}" + end while Symbol.find(name) or Symbol.find(name + "=") + name + end + n = noninterned_name("gc") + n.to_sym + GC.start(immediate_sweep: false) + eval(":#{n}=") + eval("proc{self.#{n} = nil}") + end; + end end |