* object.c (rb_mod_{const,cvar}_defined, rb_obj_ivar_defined):
avoid inadvertent symbol creation in reflection methods. based on a patch by Jeremy Evans at [ruby-core:38367]. [Feature #5072] * vm_method.c (rb_mod_method_defined) (rb_mod_{public,private,protected}_method_defined) (obj_respond_to): ditto. * parse.y (rb_check_id): new function returns already interned ID or 0. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@32621 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
c276b73804
commit
34918aa832
13
ChangeLog
13
ChangeLog
@ -1,3 +1,16 @@
|
|||||||
|
Fri Jul 22 21:06:39 2011 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* object.c (rb_mod_{const,cvar}_defined, rb_obj_ivar_defined):
|
||||||
|
avoid inadvertent symbol creation in reflection methods. based
|
||||||
|
on a patch by Jeremy Evans at [ruby-core:38367]. [Feature #5072]
|
||||||
|
|
||||||
|
* vm_method.c (rb_mod_method_defined)
|
||||||
|
(rb_mod_{public,private,protected}_method_defined)
|
||||||
|
(obj_respond_to): ditto.
|
||||||
|
|
||||||
|
* parse.y (rb_check_id): new function returns already interned ID
|
||||||
|
or 0.
|
||||||
|
|
||||||
Fri Jul 22 20:44:49 2011 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
Fri Jul 22 20:44:49 2011 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* parse.y (rb_is_global_id, rb_is_attrset_id): add missing
|
* parse.y (rb_is_global_id, rb_is_attrset_id): add missing
|
||||||
|
@ -1098,6 +1098,7 @@ ID rb_intern(const char*);
|
|||||||
ID rb_intern2(const char*, long);
|
ID rb_intern2(const char*, long);
|
||||||
ID rb_intern_str(VALUE str);
|
ID rb_intern_str(VALUE str);
|
||||||
const char *rb_id2name(ID);
|
const char *rb_id2name(ID);
|
||||||
|
ID rb_check_id(VALUE);
|
||||||
ID rb_to_id(VALUE);
|
ID rb_to_id(VALUE);
|
||||||
VALUE rb_id2str(ID);
|
VALUE rb_id2str(ID);
|
||||||
|
|
||||||
|
@ -133,6 +133,14 @@ VALUE rb_obj_equal(VALUE obj1, VALUE obj2);
|
|||||||
/* parse.y */
|
/* parse.y */
|
||||||
VALUE rb_parser_get_yydebug(VALUE);
|
VALUE rb_parser_get_yydebug(VALUE);
|
||||||
VALUE rb_parser_set_yydebug(VALUE, VALUE);
|
VALUE rb_parser_set_yydebug(VALUE, VALUE);
|
||||||
|
int rb_is_const_name(VALUE name);
|
||||||
|
int rb_is_class_name(VALUE name);
|
||||||
|
int rb_is_global_name(VALUE name);
|
||||||
|
int rb_is_instance_name(VALUE name);
|
||||||
|
int rb_is_attrset_name(VALUE name);
|
||||||
|
int rb_is_local_name(VALUE name);
|
||||||
|
int rb_is_method_name(VALUE name);
|
||||||
|
int rb_is_junk_name(VALUE name);
|
||||||
|
|
||||||
/* proc.c */
|
/* proc.c */
|
||||||
VALUE rb_proc_location(VALUE self);
|
VALUE rb_proc_location(VALUE self);
|
||||||
|
9
object.c
9
object.c
@ -1833,7 +1833,8 @@ rb_mod_const_defined(int argc, VALUE *argv, VALUE mod)
|
|||||||
else {
|
else {
|
||||||
rb_scan_args(argc, argv, "11", &name, &recur);
|
rb_scan_args(argc, argv, "11", &name, &recur);
|
||||||
}
|
}
|
||||||
id = rb_to_id(name);
|
if (!(id = rb_check_id(name)) && rb_is_const_name(name))
|
||||||
|
return Qfalse;
|
||||||
if (!rb_is_const_id(id)) {
|
if (!rb_is_const_id(id)) {
|
||||||
rb_name_error(id, "wrong constant name %s", rb_id2name(id));
|
rb_name_error(id, "wrong constant name %s", rb_id2name(id));
|
||||||
}
|
}
|
||||||
@ -1923,8 +1924,9 @@ rb_obj_ivar_set(VALUE obj, VALUE iv, VALUE val)
|
|||||||
static VALUE
|
static VALUE
|
||||||
rb_obj_ivar_defined(VALUE obj, VALUE iv)
|
rb_obj_ivar_defined(VALUE obj, VALUE iv)
|
||||||
{
|
{
|
||||||
ID id = rb_to_id(iv);
|
ID id = rb_check_id(iv);
|
||||||
|
|
||||||
|
if (!id && rb_is_instance_name(iv)) return Qfalse;
|
||||||
if (!rb_is_instance_id(id)) {
|
if (!rb_is_instance_id(id)) {
|
||||||
rb_name_error(id, "`%s' is not allowed as an instance variable name", rb_id2name(id));
|
rb_name_error(id, "`%s' is not allowed as an instance variable name", rb_id2name(id));
|
||||||
}
|
}
|
||||||
@ -2002,8 +2004,9 @@ rb_mod_cvar_set(VALUE obj, VALUE iv, VALUE val)
|
|||||||
static VALUE
|
static VALUE
|
||||||
rb_mod_cvar_defined(VALUE obj, VALUE iv)
|
rb_mod_cvar_defined(VALUE obj, VALUE iv)
|
||||||
{
|
{
|
||||||
ID id = rb_to_id(iv);
|
ID id = rb_check_id(iv);
|
||||||
|
|
||||||
|
if (!id && rb_is_class_name(iv)) return Qfalse;
|
||||||
if (!rb_is_class_id(id)) {
|
if (!rb_is_class_id(id)) {
|
||||||
rb_name_error(id, "`%s' is not allowed as a class variable name", rb_id2name(id));
|
rb_name_error(id, "`%s' is not allowed as a class variable name", rb_id2name(id));
|
||||||
}
|
}
|
||||||
|
137
parse.y
137
parse.y
@ -9678,24 +9678,29 @@ rb_enc_symname_p(const char *name, rb_encoding *enc)
|
|||||||
return rb_enc_symname2_p(name, strlen(name), enc);
|
return rb_enc_symname2_p(name, strlen(name), enc);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
rb_enc_symname2_p(const char *name, long len, rb_encoding *enc)
|
rb_enc_symname_type(const char *name, long len, rb_encoding *enc)
|
||||||
{
|
{
|
||||||
const char *m = name;
|
const char *m = name;
|
||||||
const char *e = m + len;
|
const char *e = m + len;
|
||||||
int localid = FALSE;
|
int type = ID_JUNK;
|
||||||
|
|
||||||
if (!m || len <= 0) return FALSE;
|
if (!m || len <= 0) return -1;
|
||||||
switch (*m) {
|
switch (*m) {
|
||||||
case '\0':
|
case '\0':
|
||||||
return FALSE;
|
return -1;
|
||||||
|
|
||||||
case '$':
|
case '$':
|
||||||
if (is_special_global_name(++m, e, enc)) return TRUE;
|
type = ID_GLOBAL;
|
||||||
|
if (is_special_global_name(++m, e, enc)) return type;
|
||||||
goto id;
|
goto id;
|
||||||
|
|
||||||
case '@':
|
case '@':
|
||||||
if (*++m == '@') ++m;
|
type = ID_INSTANCE;
|
||||||
|
if (*++m == '@') {
|
||||||
|
++m;
|
||||||
|
type = ID_CLASS;
|
||||||
|
}
|
||||||
goto id;
|
goto id;
|
||||||
|
|
||||||
case '<':
|
case '<':
|
||||||
@ -9716,7 +9721,7 @@ rb_enc_symname2_p(const char *name, long len, rb_encoding *enc)
|
|||||||
switch (*++m) {
|
switch (*++m) {
|
||||||
case '~': ++m; break;
|
case '~': ++m; break;
|
||||||
case '=': if (*++m == '=') ++m; break;
|
case '=': if (*++m == '=') ++m; break;
|
||||||
default: return FALSE;
|
default: return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -9733,32 +9738,53 @@ rb_enc_symname2_p(const char *name, long len, rb_encoding *enc)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '[':
|
case '[':
|
||||||
if (*++m != ']') return FALSE;
|
if (*++m != ']') return -1;
|
||||||
if (*++m == '=') ++m;
|
if (*++m == '=') ++m;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '!':
|
case '!':
|
||||||
if (len == 1) return FALSE;
|
if (len == 1) return ID_JUNK;
|
||||||
switch (*++m) {
|
switch (*++m) {
|
||||||
case '=': case '~': ++m; break;
|
case '=': case '~': ++m; break;
|
||||||
default: return FALSE;
|
default: return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
localid = !rb_enc_isupper(*m, enc);
|
type = rb_enc_isupper(*m, enc) ? ID_CONST : ID_LOCAL;
|
||||||
id:
|
id:
|
||||||
if (m >= e || (*m != '_' && !rb_enc_isalpha(*m, enc) && ISASCII(*m)))
|
if (m >= e || (*m != '_' && !rb_enc_isalpha(*m, enc) && ISASCII(*m)))
|
||||||
return FALSE;
|
return -1;
|
||||||
while (m < e && is_identchar(m, e, enc)) m += rb_enc_mbclen(m, e, enc);
|
while (m < e && is_identchar(m, e, enc)) m += rb_enc_mbclen(m, e, enc);
|
||||||
if (localid) {
|
switch (*m) {
|
||||||
switch (*m) {
|
case '!': case '?':
|
||||||
case '!': case '?': case '=': ++m;
|
type = ID_JUNK;
|
||||||
}
|
++m;
|
||||||
|
break;
|
||||||
|
case '=':
|
||||||
|
type = ID_ATTRSET;
|
||||||
|
++m;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return m == e;
|
return m == e ? type : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_enc_symname2_p(const char *name, long len, rb_encoding *enc)
|
||||||
|
{
|
||||||
|
return rb_enc_symname_type(name, len, enc) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
rb_str_symname_type(VALUE name)
|
||||||
|
{
|
||||||
|
const char *ptr = StringValuePtr(name);
|
||||||
|
long len = RSTRING_LEN(name);
|
||||||
|
int type = rb_enc_symname_type(ptr, len, rb_enc_get(name));
|
||||||
|
RB_GC_GUARD(name);
|
||||||
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ID
|
static ID
|
||||||
@ -10076,6 +10102,81 @@ rb_is_junk_id(ID id)
|
|||||||
return is_junk_id(id);
|
return is_junk_id(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ID
|
||||||
|
rb_check_id(VALUE name)
|
||||||
|
{
|
||||||
|
st_data_t id;
|
||||||
|
VALUE tmp;
|
||||||
|
|
||||||
|
if (SYMBOL_P(name)) {
|
||||||
|
return SYM2ID(name);
|
||||||
|
}
|
||||||
|
else if (RB_TYPE_P(name, T_STRING)) {
|
||||||
|
tmp = rb_check_string_type(name);
|
||||||
|
if (NIL_P(tmp)) {
|
||||||
|
tmp = rb_inspect(name);
|
||||||
|
rb_raise(rb_eTypeError, "%s is not a symbol",
|
||||||
|
RSTRING_PTR(tmp));
|
||||||
|
}
|
||||||
|
name = tmp;
|
||||||
|
}
|
||||||
|
if (!st_lookup(global_symbols.sym_id, (st_data_t)name, &id))
|
||||||
|
return (ID)0;
|
||||||
|
return (ID)id;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_is_const_name(VALUE name)
|
||||||
|
{
|
||||||
|
return rb_str_symname_type(name) == ID_CONST;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_is_class_name(VALUE name)
|
||||||
|
{
|
||||||
|
return rb_str_symname_type(name) == ID_CLASS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_is_global_name(VALUE name)
|
||||||
|
{
|
||||||
|
return rb_str_symname_type(name) == ID_GLOBAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_is_instance_name(VALUE name)
|
||||||
|
{
|
||||||
|
return rb_str_symname_type(name) == ID_INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_is_attrset_name(VALUE name)
|
||||||
|
{
|
||||||
|
return rb_str_symname_type(name) == ID_ATTRSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_is_local_name(VALUE name)
|
||||||
|
{
|
||||||
|
return rb_str_symname_type(name) == ID_LOCAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_is_method_name(VALUE name)
|
||||||
|
{
|
||||||
|
switch (rb_str_symname_type(name)) {
|
||||||
|
case ID_LOCAL: case ID_ATTRSET: case ID_JUNK:
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_is_junk_name(VALUE name)
|
||||||
|
{
|
||||||
|
return rb_str_symname_type(name) == -1;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* !RIPPER */
|
#endif /* !RIPPER */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -495,6 +495,9 @@ class TestModule < Test::Unit::TestCase
|
|||||||
def test_const_get_invalid_name
|
def test_const_get_invalid_name
|
||||||
c1 = Class.new
|
c1 = Class.new
|
||||||
assert_raise(NameError) { c1.const_defined?(:foo) }
|
assert_raise(NameError) { c1.const_defined?(:foo) }
|
||||||
|
name = "gadzooks"
|
||||||
|
assert !Symbol.all_symbols.any? {|sym| sym.to_s == name}
|
||||||
|
assert_raise(NameError) { c1.const_defined?(name) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_const_get_no_inherited
|
def test_const_get_no_inherited
|
||||||
|
@ -144,4 +144,19 @@ class TestSymbol < Test::Unit::TestCase
|
|||||||
assert_equal(':"\\u3042\\u3044\\u3046"', "\u3042\u3044\u3046".encode(e).to_sym.inspect)
|
assert_equal(':"\\u3042\\u3044\\u3046"', "\u3042\u3044\u3046".encode(e).to_sym.inspect)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_no_inadvertent_symbol_creation
|
||||||
|
feature5072 = '[ruby-core:38367]'
|
||||||
|
c = Class.new
|
||||||
|
s = "gadzooks"
|
||||||
|
{:respond_to? => "#{s}1", :method_defined? => "#{s}2",
|
||||||
|
:public_method_defined? => "#{s}3", :private_method_defined? => "#{s}4",
|
||||||
|
:protected_method_defined? => "#{s}5", :const_defined? => "A#{s}",
|
||||||
|
:instance_variable_defined? => "@#{s}", :class_variable_defined? => "@@#{s}"
|
||||||
|
}.each do |meth, str|
|
||||||
|
msg = "#{meth}(#{str}) #{feature5072}"
|
||||||
|
assert !c.send(meth, str), msg
|
||||||
|
assert !Symbol.all_symbols.any? {|sym| sym.to_s == str}, msg
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
18
vm_method.c
18
vm_method.c
@ -713,7 +713,8 @@ rb_mod_undef_method(int argc, VALUE *argv, VALUE mod)
|
|||||||
static VALUE
|
static VALUE
|
||||||
rb_mod_method_defined(VALUE mod, VALUE mid)
|
rb_mod_method_defined(VALUE mod, VALUE mid)
|
||||||
{
|
{
|
||||||
if (!rb_method_boundp(mod, rb_to_id(mid), 1)) {
|
ID id = rb_check_id(mid);
|
||||||
|
if (!id || !rb_method_boundp(mod, id, 1)) {
|
||||||
return Qfalse;
|
return Qfalse;
|
||||||
}
|
}
|
||||||
return Qtrue;
|
return Qtrue;
|
||||||
@ -763,7 +764,9 @@ check_definition(VALUE mod, ID mid, rb_method_flag_t noex)
|
|||||||
static VALUE
|
static VALUE
|
||||||
rb_mod_public_method_defined(VALUE mod, VALUE mid)
|
rb_mod_public_method_defined(VALUE mod, VALUE mid)
|
||||||
{
|
{
|
||||||
return check_definition(mod, rb_to_id(mid), NOEX_PUBLIC);
|
ID id = rb_check_id(mid);
|
||||||
|
if (!id) return Qfalse;
|
||||||
|
return check_definition(mod, id, NOEX_PUBLIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -795,7 +798,9 @@ rb_mod_public_method_defined(VALUE mod, VALUE mid)
|
|||||||
static VALUE
|
static VALUE
|
||||||
rb_mod_private_method_defined(VALUE mod, VALUE mid)
|
rb_mod_private_method_defined(VALUE mod, VALUE mid)
|
||||||
{
|
{
|
||||||
return check_definition(mod, rb_to_id(mid), NOEX_PRIVATE);
|
ID id = rb_check_id(mid);
|
||||||
|
if (!id) return Qfalse;
|
||||||
|
return check_definition(mod, id, NOEX_PRIVATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -827,7 +832,9 @@ rb_mod_private_method_defined(VALUE mod, VALUE mid)
|
|||||||
static VALUE
|
static VALUE
|
||||||
rb_mod_protected_method_defined(VALUE mod, VALUE mid)
|
rb_mod_protected_method_defined(VALUE mod, VALUE mid)
|
||||||
{
|
{
|
||||||
return check_definition(mod, rb_to_id(mid), NOEX_PROTECTED);
|
ID id = rb_check_id(mid);
|
||||||
|
if (!id) return Qfalse;
|
||||||
|
return check_definition(mod, id, NOEX_PROTECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -1238,7 +1245,8 @@ obj_respond_to(int argc, VALUE *argv, VALUE obj)
|
|||||||
ID id;
|
ID id;
|
||||||
|
|
||||||
rb_scan_args(argc, argv, "11", &mid, &priv);
|
rb_scan_args(argc, argv, "11", &mid, &priv);
|
||||||
id = rb_to_id(mid);
|
if (!(id = rb_check_id(mid)))
|
||||||
|
return Qfalse;
|
||||||
if (basic_obj_respond_to(obj, id, !RTEST(priv)))
|
if (basic_obj_respond_to(obj, id, !RTEST(priv)))
|
||||||
return Qtrue;
|
return Qtrue;
|
||||||
return Qfalse;
|
return Qfalse;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user