mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
parse.y: invalid name as mere string
* parse.y (parser_peek_variable_name): treat invalid global, class, and instance variable names as mere strings rather than errors. [ruby-core:54885] [Bug #8375] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40635 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
0542f05b32
commit
ecddb96785
3 changed files with 98 additions and 32 deletions
|
@ -1,3 +1,9 @@
|
||||||
|
Fri May 10 23:56:34 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* parse.y (parser_peek_variable_name): treat invalid global, class,
|
||||||
|
and instance variable names as mere strings rather than errors.
|
||||||
|
[ruby-core:54885] [Bug #8375]
|
||||||
|
|
||||||
Fri May 10 20:22:40 2013 Tanaka Akira <akr@fsij.org>
|
Fri May 10 20:22:40 2013 Tanaka Akira <akr@fsij.org>
|
||||||
|
|
||||||
* configure.in: Move library checks into "Checks for libraries." part.
|
* configure.in: Move library checks into "Checks for libraries." part.
|
||||||
|
|
103
parse.y
103
parse.y
|
@ -6157,6 +6157,70 @@ ripper_flush_string_content(struct parser_params *parser, rb_encoding *enc)
|
||||||
#define flush_string_content(enc) ((void)(enc))
|
#define flush_string_content(enc) ((void)(enc))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
RUBY_FUNC_EXPORTED const unsigned int ruby_global_name_punct_bits[(0x7e - 0x20 + 31) / 32];
|
||||||
|
/* this can be shared with ripper, since it's independent from struct
|
||||||
|
* parser_params. */
|
||||||
|
#ifndef RIPPER
|
||||||
|
#define BIT(c, idx) (((c) / 32 - 1 == idx) ? (1U << ((c) % 32)) : 0)
|
||||||
|
#define SPECIAL_PUNCT(idx) ( \
|
||||||
|
BIT('~', idx) | BIT('*', idx) | BIT('$', idx) | BIT('?', idx) | \
|
||||||
|
BIT('!', idx) | BIT('@', idx) | BIT('/', idx) | BIT('\\', idx) | \
|
||||||
|
BIT(';', idx) | BIT(',', idx) | BIT('.', idx) | BIT('=', idx) | \
|
||||||
|
BIT(':', idx) | BIT('<', idx) | BIT('>', idx) | BIT('\"', idx) | \
|
||||||
|
BIT('&', idx) | BIT('`', idx) | BIT('\'', idx) | BIT('+', idx) | \
|
||||||
|
BIT('0', idx))
|
||||||
|
const unsigned int ruby_global_name_punct_bits[] = {
|
||||||
|
SPECIAL_PUNCT(0),
|
||||||
|
SPECIAL_PUNCT(1),
|
||||||
|
SPECIAL_PUNCT(2),
|
||||||
|
};
|
||||||
|
#undef BIT
|
||||||
|
#undef SPECIAL_PUNCT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
is_global_name_punct(const char c)
|
||||||
|
{
|
||||||
|
if (c <= 0x20 || 0x7e < c) return 0;
|
||||||
|
return (ruby_global_name_punct_bits[(c - 0x20) / 32] >> (c % 32)) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
parser_peek_variable_name(struct parser_params *parser)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
const char *p = lex_p;
|
||||||
|
|
||||||
|
if (p + 1 >= lex_pend) return 0;
|
||||||
|
c = *p++;
|
||||||
|
switch (c) {
|
||||||
|
case '$':
|
||||||
|
if ((c = *p) == '-') {
|
||||||
|
if (++p >= lex_pend) return 0;
|
||||||
|
c = *p;
|
||||||
|
}
|
||||||
|
else if (is_global_name_punct(c) || ISDIGIT(c)) {
|
||||||
|
return tSTRING_DVAR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '@':
|
||||||
|
if ((c = *p) == '@') {
|
||||||
|
if (++p >= lex_pend) return 0;
|
||||||
|
c = *p;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '{':
|
||||||
|
lex_p = p;
|
||||||
|
command_start = TRUE;
|
||||||
|
return tSTRING_DBEG;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!ISASCII(c) || c == '_' || ISALPHA(c))
|
||||||
|
return tSTRING_DVAR;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
parser_parse_string(struct parser_params *parser, NODE *quote)
|
parser_parse_string(struct parser_params *parser, NODE *quote)
|
||||||
{
|
{
|
||||||
|
@ -6187,16 +6251,10 @@ parser_parse_string(struct parser_params *parser, NODE *quote)
|
||||||
}
|
}
|
||||||
newtok();
|
newtok();
|
||||||
if ((func & STR_FUNC_EXPAND) && c == '#') {
|
if ((func & STR_FUNC_EXPAND) && c == '#') {
|
||||||
switch (c = nextc()) {
|
int t = parser_peek_variable_name(parser);
|
||||||
case '$':
|
if (t) return t;
|
||||||
case '@':
|
|
||||||
pushback(c);
|
|
||||||
return tSTRING_DVAR;
|
|
||||||
case '{':
|
|
||||||
command_start = TRUE;
|
|
||||||
return tSTRING_DBEG;
|
|
||||||
}
|
|
||||||
tokadd('#');
|
tokadd('#');
|
||||||
|
c = nextc();
|
||||||
}
|
}
|
||||||
pushback(c);
|
pushback(c);
|
||||||
if (tokadd_string(func, term, paren, "e->nd_nest,
|
if (tokadd_string(func, term, paren, "e->nd_nest,
|
||||||
|
@ -6403,16 +6461,10 @@ parser_here_document(struct parser_params *parser, NODE *here)
|
||||||
/* int mb = ENC_CODERANGE_7BIT, *mbp = &mb;*/
|
/* int mb = ENC_CODERANGE_7BIT, *mbp = &mb;*/
|
||||||
newtok();
|
newtok();
|
||||||
if (c == '#') {
|
if (c == '#') {
|
||||||
switch (c = nextc()) {
|
int t = parser_peek_variable_name(parser);
|
||||||
case '$':
|
if (t) return t;
|
||||||
case '@':
|
|
||||||
pushback(c);
|
|
||||||
return tSTRING_DVAR;
|
|
||||||
case '{':
|
|
||||||
command_start = TRUE;
|
|
||||||
return tSTRING_DBEG;
|
|
||||||
}
|
|
||||||
tokadd('#');
|
tokadd('#');
|
||||||
|
c = nextc();
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
pushback(c);
|
pushback(c);
|
||||||
|
@ -9998,22 +10050,17 @@ is_special_global_name(const char *m, const char *e, rb_encoding *enc)
|
||||||
int mb = 0;
|
int mb = 0;
|
||||||
|
|
||||||
if (m >= e) return 0;
|
if (m >= e) return 0;
|
||||||
switch (*m) {
|
if (is_global_name_punct(*m)) {
|
||||||
case '~': case '*': case '$': case '?': case '!': case '@':
|
|
||||||
case '/': case '\\': case ';': case ',': case '.': case '=':
|
|
||||||
case ':': case '<': case '>': case '\"':
|
|
||||||
case '&': case '`': case '\'': case '+':
|
|
||||||
case '0':
|
|
||||||
++m;
|
++m;
|
||||||
break;
|
}
|
||||||
case '-':
|
else if (*m == '-') {
|
||||||
if (++m >= e) return 0;
|
if (++m >= e) return 0;
|
||||||
if (is_identchar(m, e, enc)) {
|
if (is_identchar(m, e, enc)) {
|
||||||
if (!ISASCII(*m)) mb = 1;
|
if (!ISASCII(*m)) mb = 1;
|
||||||
m += rb_enc_mbclen(m, e, enc);
|
m += rb_enc_mbclen(m, e, enc);
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
default:
|
else {
|
||||||
if (!rb_enc_isdigit(*m, enc)) return 0;
|
if (!rb_enc_isdigit(*m, enc)) return 0;
|
||||||
do {
|
do {
|
||||||
if (!ISASCII(*m)) mb = 1;
|
if (!ISASCII(*m)) mb = 1;
|
||||||
|
|
|
@ -361,6 +361,17 @@ class TestParse < Test::Unit::TestCase
|
||||||
assert_equal("foo 1 bar", "foo #$1 bar")
|
assert_equal("foo 1 bar", "foo #$1 bar")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_dstr_disallowd_variable
|
||||||
|
bug8375 = '[ruby-core:54885] [Bug #8375]'
|
||||||
|
%w[@ @1 @@. @@ @@1 @@. $ $%].each do |src|
|
||||||
|
src = '#'+src+' '
|
||||||
|
str = assert_nothing_raised(SyntaxError, "#{bug8375} #{src.dump}") do
|
||||||
|
break eval('"'+src+'"')
|
||||||
|
end
|
||||||
|
assert_equal(src, str, bug8375)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_dsym
|
def test_dsym
|
||||||
assert_nothing_raised { eval(':""') }
|
assert_nothing_raised { eval(':""') }
|
||||||
end
|
end
|
||||||
|
@ -527,13 +538,14 @@ class TestParse < Test::Unit::TestCase
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_raise(SyntaxError) do
|
assert_nothing_raised(SyntaxError) do
|
||||||
eval %q(
|
x = eval %q(
|
||||||
<<FOO
|
<<FOO
|
||||||
#$
|
#$
|
||||||
FOO
|
FOO
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
assert_equal "\#$\n", x
|
||||||
|
|
||||||
assert_raise(SyntaxError) do
|
assert_raise(SyntaxError) do
|
||||||
eval %Q(
|
eval %Q(
|
||||||
|
@ -553,14 +565,15 @@ FOO
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_raise(SyntaxError) do
|
assert_nothing_raised(SyntaxError) do
|
||||||
eval %q(
|
x = eval %q(
|
||||||
<<FOO
|
<<FOO
|
||||||
#$
|
#$
|
||||||
foo
|
foo
|
||||||
FOO
|
FOO
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
assert_equal "\#$\nfoo\n", x
|
||||||
|
|
||||||
assert_nothing_raised do
|
assert_nothing_raised do
|
||||||
eval "x = <<""FOO\r\n1\r\nFOO"
|
eval "x = <<""FOO\r\n1\r\nFOO"
|
||||||
|
|
Loading…
Reference in a new issue