Feature #5072 » 0002-Avoid-inadvertent-symbol-creation-in-reflection-meth.patch
include/ruby/ruby.h | ||
---|---|---|
ID rb_intern2(const char*, long);
|
||
ID rb_intern_str(VALUE str);
|
||
const char *rb_id2name(ID);
|
||
int rb_check_id(VALUE, ID*);
|
||
ID rb_to_id(VALUE);
|
||
VALUE rb_id2str(ID);
|
||
object.c | ||
---|---|---|
else {
|
||
rb_scan_args(argc, argv, "11", &name, &recur);
|
||
}
|
||
id = rb_to_id(name);
|
||
if(!rb_check_id(name, &id))
|
||
return Qfalse;
|
||
if (!rb_is_const_id(id)) {
|
||
rb_name_error(id, "wrong constant name %s", rb_id2name(id));
|
||
}
|
||
... | ... | |
static VALUE
|
||
rb_obj_ivar_defined(VALUE obj, VALUE iv)
|
||
{
|
||
ID id = rb_to_id(iv);
|
||
ID id;
|
||
if(!rb_check_id(iv, &id))
|
||
return Qfalse;
|
||
if (!rb_is_instance_id(id)) {
|
||
rb_name_error(id, "`%s' is not allowed as an instance variable name", rb_id2name(id));
|
||
... | ... | |
static VALUE
|
||
rb_mod_cvar_defined(VALUE obj, VALUE iv)
|
||
{
|
||
ID id = rb_to_id(iv);
|
||
ID id;
|
||
if(!rb_check_id(iv, &id))
|
||
return Qfalse;
|
||
if (!rb_is_class_id(id)) {
|
||
rb_name_error(id, "`%s' is not allowed as a class variable name", rb_id2name(id));
|
parse.y | ||
---|---|---|
return is_junk_id(id);
|
||
}
|
||
int
|
||
rb_check_id(VALUE name, ID *id)
|
||
{
|
||
VALUE tmp;
|
||
switch (TYPE(name)) {
|
||
default:
|
||
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;
|
||
/* fall through */
|
||
case T_STRING:
|
||
return st_lookup(global_symbols.sym_id, (st_data_t)name, id);
|
||
case T_SYMBOL:
|
||
*id = SYM2ID(name);
|
||
return 1;
|
||
}
|
||
return 0; /* not reached */
|
||
}
|
||
#endif /* !RIPPER */
|
||
static void
|
test/ruby/test_parse.rb | ||
---|---|---|
assert_equal(':"foo=="', "foo==".intern.inspect)
|
||
end
|
||
def test_no_inadvertent_symbol_creation
|
||
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|
|
||
Object.send(meth, str)
|
||
assert !Symbol.all_symbols.any?{|sym| sym.to_s == str}
|
||
end
|
||
end
|
||
def test_all_symbols
|
||
x = Symbol.all_symbols
|
||
assert_kind_of(Array, x)
|
vm_method.c | ||
---|---|---|
static VALUE
|
||
rb_mod_method_defined(VALUE mod, VALUE mid)
|
||
{
|
||
if (!rb_method_boundp(mod, rb_to_id(mid), 1)) {
|
||
ID id;
|
||
if(!rb_check_id(mid, &id))
|
||
return Qfalse;
|
||
if (!rb_method_boundp(mod, id, 1)) {
|
||
return Qfalse;
|
||
}
|
||
return Qtrue;
|
||
... | ... | |
static VALUE
|
||
rb_mod_public_method_defined(VALUE mod, VALUE mid)
|
||
{
|
||
return check_definition(mod, rb_to_id(mid), NOEX_PUBLIC);
|
||
ID id;
|
||
if(!rb_check_id(mid, &id))
|
||
return Qfalse;
|
||
return check_definition(mod, id, NOEX_PUBLIC);
|
||
}
|
||
/*
|
||
... | ... | |
static VALUE
|
||
rb_mod_private_method_defined(VALUE mod, VALUE mid)
|
||
{
|
||
return check_definition(mod, rb_to_id(mid), NOEX_PRIVATE);
|
||
ID id;
|
||
if(!rb_check_id(mid, &id))
|
||
return Qfalse;
|
||
return check_definition(mod, mid, NOEX_PRIVATE);
|
||
}
|
||
/*
|
||
... | ... | |
static VALUE
|
||
rb_mod_protected_method_defined(VALUE mod, VALUE mid)
|
||
{
|
||
return check_definition(mod, rb_to_id(mid), NOEX_PROTECTED);
|
||
ID id;
|
||
if(!rb_check_id(mid, &id))
|
||
return Qfalse;
|
||
return check_definition(mod, id, NOEX_PROTECTED);
|
||
}
|
||
int
|
||
... | ... | |
ID id;
|
||
rb_scan_args(argc, argv, "11", &mid, &priv);
|
||
id = rb_to_id(mid);
|
||
if(!rb_check_id(mid, &id))
|
||
return Qfalse;
|
||
if (basic_obj_respond_to(obj, id, !RTEST(priv)))
|
||
return Qtrue;
|
||
return Qfalse;
|