Skip to content

Commit bf57198

Browse files
committed
merge revision(s) 50671: [Backport ruby#11192]
* compile.c (iseq_compile_each): out of range NTH_REF is always nil. * parse.y (parse_numvar): check overflow of NTH_REF and range. [ruby-core:69393] [Bug ruby#11192] * util.c (ruby_scan_digits): make public and add length parameter. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_1@51122 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
1 parent a57c925 commit bf57198

File tree

7 files changed

+58
-11
lines changed

7 files changed

+58
-11
lines changed

ChangeLog

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
Fri Jul 3 18:32:37 2015 Nobuyoshi Nakada <[email protected]>
2+
3+
* compile.c (iseq_compile_each): out of range NTH_REF is always
4+
nil.
5+
6+
* parse.y (parse_numvar): check overflow of NTH_REF and range.
7+
[ruby-core:69393] [Bug #11192]
8+
9+
* util.c (ruby_scan_digits): make public and add length parameter.
10+
111
Fri Jul 3 17:53:43 2015 Nobuyoshi Nakada <[email protected]>
212

313
* vm_eval.c (rb_method_call_status): resolve refined method entry

compile.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4795,6 +4795,10 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
47954795
}
47964796
case NODE_NTH_REF:{
47974797
if (!poped) {
4798+
if (!node->nd_nth) {
4799+
ADD_INSN(ret, line, putnil);
4800+
break;
4801+
}
47984802
ADD_INSN2(ret, line, getspecial, INT2FIX(1) /* '~' */,
47994803
INT2FIX(node->nd_nth << 1));
48004804
}

internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -867,6 +867,7 @@ VALUE rb_gcd_gmp(VALUE x, VALUE y);
867867

868868
/* util.c */
869869
extern const signed char ruby_digit36_to_number_table[];
870+
extern unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow);
870871

871872
/* variable.c */
872873
void rb_gc_mark_global_tbl(void);

parse.y

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6957,6 +6957,27 @@ parser_prepare(struct parser_params *parser)
69576957
space_seen && !ISSPACE(c) && \
69586958
(ambiguous_operator(op, syn), 0)))
69596959

6960+
static int
6961+
parse_numvar(struct parser_params *parser)
6962+
{
6963+
size_t len;
6964+
int overflow;
6965+
unsigned long n = ruby_scan_digits(tok()+1, toklen()-1, 10, &len, &overflow);
6966+
const unsigned long nth_ref_max =
6967+
(FIXNUM_MAX / 2 < INT_MAX) ? FIXNUM_MAX / 2 : INT_MAX;
6968+
/* NTH_REF is left-shifted to be ORed with back-ref flag and
6969+
* turned into a Fixnum, in compile.c */
6970+
6971+
if (overflow || n > nth_ref_max) {
6972+
/* compile_error()? */
6973+
rb_warnS("`%s' is too big for a number variable, always nil", tok());
6974+
return 0; /* $0 is $PROGRAM_NAME, not NTH_REF */
6975+
}
6976+
else {
6977+
return (int)n;
6978+
}
6979+
}
6980+
69606981
static int
69616982
parser_yylex(struct parser_params *parser)
69626983
{
@@ -8053,7 +8074,7 @@ parser_yylex(struct parser_params *parser)
80538074
pushback(c);
80548075
if (IS_lex_state_for(last_state, EXPR_FNAME)) goto gvar;
80558076
tokfix();
8056-
set_yylval_node(NEW_NTH_REF(atoi(tok()+1)));
8077+
set_yylval_node(NEW_NTH_REF(parse_numvar(parser)));
80578078
return tNTH_REF;
80588079

80598080
default:

test/ruby/test_syntax.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,13 @@ def test_null_range_cmdarg
421421
assert_syntax_error('0...%w.', /unterminated string/, bug10957)
422422
end
423423

424+
def test_too_big_nth_ref
425+
bug11192 = '[ruby-core:69393] [Bug #11192]'
426+
assert_warn(/too big/, bug11192) do
427+
eval('$99999999999999999')
428+
end
429+
end
430+
424431
private
425432

426433
def not_label(x) @result = x; @not_label ||= nil end

util.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -75,21 +75,25 @@ const signed char ruby_digit36_to_number_table[] = {
7575
/*f*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
7676
};
7777

78-
static unsigned long
79-
scan_digits(const char *str, int base, size_t *retlen, int *overflow)
78+
unsigned long
79+
ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow)
8080
{
8181

8282
const char *start = str;
8383
unsigned long ret = 0, x;
8484
unsigned long mul_overflow = (~(unsigned long)0) / base;
85-
int c;
85+
8686
*overflow = 0;
8787

88-
while ((c = (unsigned char)*str++) != '\0') {
89-
int d = ruby_digit36_to_number_table[c];
88+
if (!len) {
89+
*retlen = 0;
90+
return 0;
91+
}
92+
93+
do {
94+
int d = ruby_digit36_to_number_table[(unsigned char)*str++];
9095
if (d == -1 || base <= d) {
91-
*retlen = (str-1) - start;
92-
return ret;
96+
break;
9397
}
9498
if (mul_overflow < ret)
9599
*overflow = 1;
@@ -98,7 +102,7 @@ scan_digits(const char *str, int base, size_t *retlen, int *overflow)
98102
ret += d;
99103
if (ret < x)
100104
*overflow = 1;
101-
}
105+
} while (len < 0 || --len);
102106
*retlen = (str-1) - start;
103107
return ret;
104108
}
@@ -150,7 +154,7 @@ ruby_strtoul(const char *str, char **endptr, int base)
150154
b = base == 0 ? 10 : base;
151155
}
152156

153-
ret = scan_digits(str, b, &len, &overflow);
157+
ret = ruby_scan_digits(str, -1, b, &len, &overflow);
154158

155159
if (0 < len)
156160
subject_found = str+len;

version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#define RUBY_VERSION "2.1.7"
22
#define RUBY_RELEASE_DATE "2015-07-03"
3-
#define RUBY_PATCHLEVEL 372
3+
#define RUBY_PATCHLEVEL 373
44

55
#define RUBY_RELEASE_YEAR 2015
66
#define RUBY_RELEASE_MONTH 7

0 commit comments

Comments
 (0)