symbol.c: fix dynamic attrset ID

* symbol.c (rb_str_dynamic_intern): check if the stem ID of
  attrset ID is already registered as a static ID.
  [ruby-dev:48559] [Bug #10259]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@47643 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2014-09-19 11:06:04 +00:00
Родитель 3558e886bd
Коммит ac3c851bde
3 изменённых файлов: 49 добавлений и 17 удалений

Просмотреть файл

@ -1,3 +1,9 @@
Fri Sep 19 20:06:00 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
* symbol.c (rb_str_dynamic_intern): check if the stem ID of
attrset ID is already registered as a static ID.
[ruby-dev:48559] [Bug #10259]
Fri Sep 19 15:48:09 2014 NAKAMURA Usaku <usa@ruby-lang.org>
* win32/win32.c (VCSUP): nothing to do if this worktree is not under

Просмотреть файл

@ -103,13 +103,14 @@ Init_sym(void)
Init_id();
}
WARN_UNUSED_RESULT(static VALUE dsymbol_alloc(const VALUE klass, const VALUE str, rb_encoding *const enc));
WARN_UNUSED_RESULT(static VALUE dsymbol_alloc(const VALUE klass, const VALUE str, rb_encoding *const enc, const ID type));
WARN_UNUSED_RESULT(static VALUE dsymbol_check(const VALUE sym));
WARN_UNUSED_RESULT(static ID dsymbol_pindown(VALUE sym));
WARN_UNUSED_RESULT(static ID lookup_str_id(VALUE str));
WARN_UNUSED_RESULT(static VALUE lookup_str_sym(const VALUE str));
WARN_UNUSED_RESULT(static VALUE lookup_id_str(ID id));
WARN_UNUSED_RESULT(static ID attrsetname_to_attr(VALUE name));
WARN_UNUSED_RESULT(static ID attrsetname_to_attr_id(VALUE name));
ID
rb_id_attrset(ID id)
@ -416,10 +417,9 @@ must_be_dynamic_symbol(VALUE x)
}
static VALUE
dsymbol_alloc(const VALUE klass, const VALUE str, rb_encoding * const enc)
dsymbol_alloc(const VALUE klass, const VALUE str, rb_encoding * const enc, const ID type)
{
const VALUE dsym = rb_newobj_of(klass, T_SYMBOL | FL_WB_PROTECTED);
const ID type = rb_str_symname_type(str, IDSET_ATTRSET_FOR_INTERN);
rb_enc_associate(dsym, enc);
OBJ_FREEZE(dsym);
@ -441,10 +441,11 @@ dsymbol_check(const VALUE sym)
{
if (UNLIKELY(rb_objspace_garbage_object_p(sym))) {
const VALUE fstr = RSYMBOL(sym)->fstr;
const ID type = RSYMBOL(sym)->type;
RSYMBOL(sym)->fstr = 0;
unregister_sym(fstr, sym);
return dsymbol_alloc(rb_cSymbol, fstr, rb_enc_get(fstr));
return dsymbol_alloc(rb_cSymbol, fstr, rb_enc_get(fstr), type);
}
else {
return sym;
@ -737,6 +738,7 @@ rb_str_dynamic_intern(VALUE str)
#if USE_SYMBOL_GC
rb_encoding *enc, *ascii;
VALUE sym = lookup_str_sym(str);
ID type;
if (sym) {
return sym;
@ -753,7 +755,16 @@ rb_str_dynamic_intern(VALUE str)
}
}
return dsymbol_alloc(rb_cSymbol, rb_fstring(str), enc);
type = rb_str_symname_type(str, IDSET_ATTRSET_FOR_INTERN);
if (type == ID_ATTRSET) {
ID attr_id = attrsetname_to_attr_id(str);
if (attr_id && !ID_DYNAMIC_SYM_P(attr_id)) {
attr_id = rb_id_attrset(attr_id);
return ID2SYM(attr_id);
}
}
return dsymbol_alloc(rb_cSymbol, rb_fstring(str), enc, type);
#else
return rb_str_intern(str);
#endif
@ -1082,22 +1093,29 @@ rb_check_symbol_cstr(const char *ptr, long len, rb_encoding *enc)
return Qnil;
}
static ID
attrsetname_to_attr_id(VALUE name)
{
ID id;
struct RString fake_str;
/* make local name by chopping '=' */
const VALUE localname = rb_setup_fake_str(&fake_str,
RSTRING_PTR(name), RSTRING_LEN(name) - 1,
rb_enc_get(name));
OBJ_FREEZE(localname);
if ((id = lookup_str_id(localname)) != 0) {
return id;
}
RB_GC_GUARD(name);
return (ID)0;
}
static ID
attrsetname_to_attr(VALUE name)
{
if (rb_is_attrset_name(name)) {
ID id;
struct RString fake_str;
/* make local name by chopping '=' */
const VALUE localname = rb_setup_fake_str(&fake_str,
RSTRING_PTR(name), RSTRING_LEN(name) - 1,
rb_enc_get(name));
OBJ_FREEZE(localname);
if ((id = lookup_str_id(localname)) != 0) {
return id;
}
RB_GC_GUARD(name);
return attrsetname_to_attr_id(name);
}
return (ID)0;

Просмотреть файл

@ -222,4 +222,12 @@ class TestSymbol < Test::Unit::TestCase
'',
child_env: '--disable-gems')
end
def test_dynamic_attrset_id
bug10259 = '[ruby-dev:48559] [Bug #10259]'
class << (obj = Object.new)
attr_writer :unagi
end
assert_nothing_raised(NoMethodError, bug10259) {obj.send("unagi=".intern, 1)}
end
end