summaryrefslogtreecommitdiffstats
path: root/bignum.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-07-30 02:16:42 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-07-30 02:16:42 +0000
commit712540b9427390c8d7f06535ec109e4301227619 (patch)
treee7dedaf7e6f870b1be663dde18505fadc6ff17c4 /bignum.c
parentd7c6f7953b2fd60fa580dcbaf01399337286e2be (diff)
downloadruby-712540b9427390c8d7f06535ec109e4301227619.tar.gz
ruby-712540b9427390c8d7f06535ec109e4301227619.tar.xz
ruby-712540b9427390c8d7f06535ec109e4301227619.zip
* bignum.c (rb_big_aref): check for Bignum index range.
[ruby-dev:31271] git-svn-id: http://svn.ruby-lang.org/repos/ruby/trunk@12855 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'bignum.c')
-rw-r--r--bignum.c34
1 files changed, 22 insertions, 12 deletions
diff --git a/bignum.c b/bignum.c
index a0402d7d2..f4c2015c9 100644
--- a/bignum.c
+++ b/bignum.c
@@ -2061,29 +2061,39 @@ static VALUE
rb_big_aref(VALUE x, VALUE y)
{
BDIGIT *xds;
- int shift;
- long s1, s2;
+ BDIGIT_DBL num;
+ VALUE shift;
+ long i, s1, s2;
if (TYPE(y) == T_BIGNUM) {
- if (!RBIGNUM(y)->sign || RBIGNUM(x)->sign)
+ if (!RBIGNUM(y)->sign)
return INT2FIX(0);
- return INT2FIX(1);
+ if (RBIGNUM(bigtrunc(y))->len > SIZEOF_VALUE/SIZEOF_BDIGITS) {
+ out_of_range:
+ return RBIGNUM(x)->sign ? INT2FIX(0) : INT2FIX(1);
+ }
+ shift = big2ulong(y, "long", Qfalse);
+ }
+ else {
+ i = NUM2LONG(y);
+ if (i < 0) return INT2FIX(0);
+ shift = (VALUE)i;
}
- shift = NUM2INT(y);
- if (shift < 0) return INT2FIX(0);
s1 = shift/BITSPERDIG;
s2 = shift%BITSPERDIG;
+ if (s1 >= RBIGNUM(x)->len) goto out_of_range;
if (!RBIGNUM(x)->sign) {
- if (s1 >= RBIGNUM(x)->len) return INT2FIX(1);
- x = rb_big_clone(x);
- get2comp(x);
+ xds = BDIGITS(x);
+ i = 0; num = 1;
+ while (num += ~xds[i], ++i <= s1) {
+ num = BIGDN(num);
+ }
}
else {
- if (s1 >= RBIGNUM(x)->len) return INT2FIX(0);
+ num = BDIGITS(x)[s1];
}
- xds = BDIGITS(x);
- if (xds[s1] & (1<<s2))
+ if (num & ((BDIGIT_DBL)1<<s2))
return INT2FIX(1);
return INT2FIX(0);
}