зеркало из https://github.com/github/ruby.git
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:
Родитель
3558e886bd
Коммит
ac3c851bde
|
@ -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
|
||||
|
|
52
symbol.c
52
symbol.c
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче