summaryrefslogtreecommitdiff
path: root/parse.y
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-07-09 06:14:41 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-07-09 06:14:41 +0000
commit76a929a7fca3c84630574e4daa9dab7a96b04fc8 (patch)
treea9cd02b421dd1e70fd8e478589f93ae94af9af23 /parse.y
parent37f018fdf52d0f75d66d467055f992dee1c0a420 (diff)
* parse.y: change Symbol <-> ID relationship to avoid
exposing IDs from collectable symbols. [Bug #10014] Now, rb_check_id() returns 0 if corresponding symbol is pinned dynamic symbol. There is remaining intern_cstr_without_pindown(), it can return IDs from collectable symbols. We must be careful to use it (only used in parse.y). I think it should be removed if it does not have impact for performance. * parse.y: add: * STATIC_SYM2ID() * STATIC_ID2SYM() rename: * rb_pin_dynamic_symbol() -> dsymbol_pindown() * internal.h: remove: * rb_check_id_without_pindown() * rb_sym2id_without_pindown() add: * rb_check_symbol() * rb_check_symbol_cstr() * load.c: use rb_check_id() or rb_check_id_cstr(). * object.c: ditto. * struct.c: ditto. * thread.c: ditto. * vm_method.c: ditto. * string.c (sym_find): use only rb_check_symbol(). * sprintf.c (rb_str_format): use rb_check_symbol_cstr(). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@46764 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'parse.y')
-rw-r--r--parse.y251
1 files changed, 155 insertions, 96 deletions
diff --git a/parse.y b/parse.y
index 7b47522583..26c5c314da 100644
--- a/parse.y
+++ b/parse.y
@@ -51,7 +51,10 @@ 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)
+#define STATIC_SYM2ID(sym) RSHIFT((unsigned long)(sym), RUBY_SPECIAL_SHIFT)
+#define STATIC_ID2SYM(id) (((VALUE)(id)<<RUBY_SPECIAL_SHIFT)|SYMBOL_FLAG)
static inline int id_type(ID);
#define is_notop_id(id) ((id)>tLAST_OP_ID)
@@ -8831,7 +8834,6 @@ block_dup_check_gen(struct parser_params *parser, NODE *node1, NODE *node2)
}
}
-static ID rb_pin_dynamic_symbol(VALUE);
static ID attrsetname_to_attr(VALUE name);
static int lookup_id_str(ID id, st_data_t *data);
@@ -10481,7 +10483,7 @@ dsymbol_check(const VALUE sym)
}
static ID
-rb_pin_dynamic_symbol(VALUE sym)
+dsymbol_pindown(VALUE sym)
{
must_be_dynamic_symbol(sym);
@@ -10496,19 +10498,55 @@ rb_pin_dynamic_symbol(VALUE sym)
return (ID)sym;
}
-static int
-lookup_str_id(st_data_t str, st_data_t *data)
+static ID
+lookup_str_id(st_data_t str, st_data_t *id_datap)
{
- ID id;
+ if (st_lookup(global_symbols.str_id, str, id_datap)) {
+ const ID id = (ID)*id_datap;
- if (!st_lookup(global_symbols.str_id, str, data)) {
+ if (ID_DYNAMIC_SYM_P(id) && !SYMBOL_PINNED_P(id)) {
+ *id_datap = 0;
+ return FALSE;
+ }
+ else {
+ return TRUE;
+ }
+ }
+ else {
return FALSE;
}
- id = (ID)*data;
+}
+
+static VALUE
+lookup_str_sym(const st_data_t str, st_data_t *sym_datap)
+{
+ if (st_lookup(global_symbols.str_id, str, sym_datap)) {
+ const ID id = *sym_datap;
+
+ if (ID_DYNAMIC_SYM_P(id)) {
+ *sym_datap = dsymbol_check(id);
+ }
+ else {
+ *sym_datap = STATIC_ID2SYM(id);
+ }
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
+static int
+lookup_id_str(ID id, st_data_t *data)
+{
if (ID_DYNAMIC_SYM_P(id)) {
- *data = (st_data_t)rb_pin_dynamic_symbol((VALUE)id);
+ *data = RSYMBOL(id)->fstr;
+ return TRUE;
}
- return TRUE;
+ if (st_lookup(global_symbols.id_str, id, data)) {
+ return TRUE;
+ }
+ return FALSE;
}
static ID
@@ -10535,7 +10573,7 @@ rb_intern3(const char *name, long len, rb_encoding *enc)
id = intern_cstr_without_pindown(name, len, enc);
if (ID_DYNAMIC_SYM_P(id)) {
- id = rb_pin_dynamic_symbol((VALUE)id);
+ id = dsymbol_pindown((VALUE)id);
}
return id;
@@ -10684,10 +10722,12 @@ rb_intern(const char *name)
ID
rb_intern_str(VALUE str)
{
- st_data_t id;
+ st_data_t sym;
+
+ if (lookup_str_sym(str, &sym)) {
+ return SYM2ID(sym);
+ }
- if (lookup_str_id(str, &id))
- return (ID)id;
return intern_str(rb_str_dup(str));
}
@@ -10733,15 +10773,9 @@ rb_str_dynamic_intern(VALUE str)
{
#if USE_SYMBOL_GC
rb_encoding *enc, *ascii;
- ID id;
+ VALUE sym;
- if (st_lookup(global_symbols.str_id, str, &id)) {
- VALUE sym = ID2SYM(id);
- if (ID_DYNAMIC_SYM_P(id)) {
- /* because of lazy sweep, dynamic symbol may be unmarked already and swept
- * at next time */
- sym = dsymbol_check(sym);
- }
+ if (lookup_str_sym(str, &sym)) {
return sym;
}
@@ -10762,40 +10796,17 @@ rb_str_dynamic_intern(VALUE str)
#endif
}
-static int
-lookup_id_str(ID id, st_data_t *data)
-{
- if (ID_DYNAMIC_SYM_P(id)) {
- id = (ID)dsymbol_check((VALUE)id);
- *data = RSYMBOL(id)->fstr;
- return TRUE;
- }
- if (st_lookup(global_symbols.id_str, id, data)) {
- return TRUE;
- }
- return FALSE;
-}
-
ID
-rb_sym2id(VALUE x)
+rb_sym2id(VALUE sym)
{
- if (STATIC_SYM_P(x)) {
- return RSHIFT((unsigned long)(x),RUBY_SPECIAL_SHIFT);
+ if (STATIC_SYM_P(sym)) {
+ return STATIC_SYM2ID(sym);
}
else {
- return rb_pin_dynamic_symbol(x);
- }
-}
-
-ID
-rb_sym2id_without_pindown(VALUE x)
-{
- if (STATIC_SYM_P(x)) {
- return RSHIFT((unsigned long)(x),RUBY_SPECIAL_SHIFT);
- }
- else {
- must_be_dynamic_symbol(x);
- return (ID)x;
+ if (!SYMBOL_PINNED_P(sym)) {
+ dsymbol_pindown(sym);
+ }
+ return (ID)sym;
}
}
@@ -10803,7 +10814,7 @@ VALUE
rb_id2sym(ID x)
{
if (!ID_DYNAMIC_SYM_P(x)) {
- return ((VALUE)(x)<<RUBY_SPECIAL_SHIFT)|SYMBOL_FLAG;
+ return STATIC_ID2SYM(x);
}
else {
return (VALUE)x;
@@ -10814,10 +10825,14 @@ rb_id2sym(ID x)
VALUE
rb_sym2str(VALUE sym)
{
- return rb_id2str(rb_sym2id_without_pindown(sym));
+ if (DYNAMIC_SYM_P(sym)) {
+ return RSYMBOL(sym)->fstr;
+ }
+ else {
+ return rb_id2str(STATIC_SYM2ID(sym));
+ }
}
-
VALUE
rb_id2str(ID id)
{
@@ -10862,7 +10877,7 @@ rb_id2str(ID id)
str = rb_str_dup(str);
rb_str_cat(str, "=", 1);
register_static_symid_str(id, str);
- if (st_lookup(global_symbols.id_str, id, &data)) {
+ if (lookup_id_str(id, &data)) {
VALUE str = (VALUE)data;
if (RBASIC(str)->klass == 0)
RBASIC_SET_CLASS_RAW(str, rb_cString);
@@ -10985,38 +11000,56 @@ rb_is_junk_id(ID id)
ID
rb_check_id(volatile VALUE *namep)
{
- ID id;
+ st_data_t id;
+ VALUE tmp;
+ VALUE name = *namep;
- id = rb_check_id_without_pindown((VALUE *)namep);
- if (ID_DYNAMIC_SYM_P(id)) {
- id = rb_pin_dynamic_symbol((VALUE)id);
+ if (STATIC_SYM_P(name)) {
+ return STATIC_SYM2ID(name);
+ }
+ else if (DYNAMIC_SYM_P(name)) {
+ if (SYMBOL_PINNED_P(name)) {
+ return (ID)name;
+ }
+ else {
+ *namep = RSYMBOL(name)->fstr;
+ return 0;
+ }
+ }
+ 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 nor a string",
+ RSTRING_PTR(tmp));
+ }
+ name = tmp;
+ *namep = name;
}
- return id;
-}
+ sym_check_asciionly(name);
-ID
-rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc)
-{
- ID id;
+ if (lookup_str_id(name, &id)) {
+ return id;
+ }
- id = rb_check_id_cstr_without_pindown(ptr, len, enc);
- if (ID_DYNAMIC_SYM_P(id)) {
- id = rb_pin_dynamic_symbol((VALUE)id);
+ {
+ ID gid = attrsetname_to_attr(name);
+ if (gid) return rb_id_attrset(gid);
}
- return id;
+ return (ID)0;
}
-ID
-rb_check_id_without_pindown(VALUE *namep)
+VALUE
+rb_check_symbol(volatile VALUE *namep)
{
- st_data_t id;
+ st_data_t sym;
VALUE tmp;
VALUE name = *namep;
if (SYMBOL_P(name)) {
- return rb_sym2id_without_pindown(name);
+ return name;
}
else if (!RB_TYPE_P(name, T_STRING)) {
tmp = rb_check_string_type(name);
@@ -11031,55 +11064,81 @@ rb_check_id_without_pindown(VALUE *namep)
sym_check_asciionly(name);
- if (st_lookup(global_symbols.str_id, (st_data_t)name, &id))
- return (ID)id;
+ if (lookup_str_sym(name, &sym)) {
+ return sym;
+ }
{
ID gid = attrsetname_to_attr(name);
- if (gid) return rb_id_attrset(gid);
+ if (gid) return ID2SYM(rb_id_attrset(gid));
}
- return (ID)0;
+ return Qnil;
}
-static ID
-attrsetname_to_attr(VALUE name)
+ID
+rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc)
{
- if (rb_is_attrset_name(name)) {
- st_data_t id;
- struct RString fake_str;
- /* make local name by chopping '=' */
- const VALUE localname = setup_fake_str(&fake_str, RSTRING_PTR(name), RSTRING_LEN(name) - 1);
- rb_enc_copy(localname, name);
- OBJ_FREEZE(localname);
+ st_data_t id;
+ struct RString fake_str;
+ const VALUE name = setup_fake_str(&fake_str, ptr, len);
+ rb_enc_associate(name, enc);
- if (st_lookup(global_symbols.str_id, (st_data_t)localname, &id)) {
- return (ID)id;
+ sym_check_asciionly(name);
+
+ if (lookup_str_id(name, &id)) {
+ return id;
+ }
+
+ if (rb_is_attrset_name(name)) {
+ fake_str.as.heap.len = len - 1;
+ if (lookup_str_id((st_data_t)name, &id)) {
+ return rb_id_attrset((ID)id);
}
- RB_GC_GUARD(name);
}
return (ID)0;
}
-ID
-rb_check_id_cstr_without_pindown(const char *ptr, long len, rb_encoding *enc)
+VALUE
+rb_check_symbol_cstr(const char *ptr, long len, rb_encoding *enc)
{
- st_data_t id;
+ st_data_t sym;
struct RString fake_str;
const VALUE name = setup_fake_str(&fake_str, ptr, len);
rb_enc_associate(name, enc);
sym_check_asciionly(name);
- if (st_lookup(global_symbols.str_id, (st_data_t)name, &id))
- return (ID)id;
+ if (lookup_str_sym(name, &sym)) {
+ return sym;
+ }
if (rb_is_attrset_name(name)) {
fake_str.as.heap.len = len - 1;
- if (st_lookup(global_symbols.str_id, (st_data_t)name, &id)) {
- return rb_id_attrset((ID)id);
+ if (lookup_str_sym((st_data_t)name, &sym)) {
+ return ID2SYM(rb_id_attrset(SYM2ID(sym)));
+ }
+ }
+
+ return Qnil;
+}
+
+static ID
+attrsetname_to_attr(VALUE name)
+{
+ if (rb_is_attrset_name(name)) {
+ st_data_t id;
+ struct RString fake_str;
+ /* make local name by chopping '=' */
+ const VALUE localname = setup_fake_str(&fake_str, RSTRING_PTR(name), RSTRING_LEN(name) - 1);
+ rb_enc_copy(localname, name);
+ OBJ_FREEZE(localname);
+
+ if (lookup_str_id((st_data_t)localname, &id)) {
+ return (ID)id;
}
+ RB_GC_GUARD(name);
}
return (ID)0;