aboutsummaryrefslogtreecommitdiffstats
path: root/bignum.c
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-06-26 03:49:45 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-06-26 03:49:45 +0000
commit1457ee2ce4582456a7226fe81b817abb9548813e (patch)
treee6b4321377bf89be71b98f7d7b6fa24ef1d9b16e /bignum.c
parent9be51267b54f923e9e95824984416eca9b95dd6c (diff)
downloadruby-1457ee2ce4582456a7226fe81b817abb9548813e.tar.gz
* bignum.c (bigxor_int): Fix a buffer over read.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@41640 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'bignum.c')
-rw-r--r--bignum.c27
1 files changed, 17 insertions, 10 deletions
diff --git a/bignum.c b/bignum.c
index ce0706631a..4b926160f5 100644
--- a/bignum.c
+++ b/bignum.c
@@ -4873,6 +4873,10 @@ bigxor_int(VALUE x, long y)
sign = (y >= 0) ? 1 : 0;
xds = BDIGITS(x);
zn = xn = RBIGNUM_LEN(x);
+#if SIZEOF_BDIGITS < SIZEOF_LONG
+ if (zn < bdigit_roomof(SIZEOF_LONG))
+ zn = bdigit_roomof(SIZEOF_LONG);
+#endif
z = bignew(zn, !(RBIGNUM_SIGN(x) ^ sign));
zds = BDIGITS(z);
@@ -4880,19 +4884,22 @@ bigxor_int(VALUE x, long y)
i = 1;
zds[0] = xds[0] ^ y;
#else
- {
- long num = y;
-
- for (i=0; i<bdigit_roomof(SIZEOF_LONG); i++) {
- zds[i] = xds[i] ^ BIGLO(num);
- num = BIGDN(num);
- }
+ for (i = 0; i < xn; i++) {
+ zds[i] = xds[i] ^ BIGLO(y);
+ y = BIGDN(y);
+ }
+ for (; i < zn; i++) {
+ zds[i] = (RBIGNUM_SIGN(x) ? 0 : BDIGMAX) ^ BIGLO(y);
+ y = BIGDN(y);
}
#endif
- while (i < xn) {
- zds[i] = sign?xds[i]:BIGLO(~xds[i]);
- i++;
+ for (; i < xn; i++) {
+ zds[i] = sign ? xds[i] : BIGLO(~xds[i]);
+ }
+ for (; i < zn; i++) {
+ zds[i] = sign ^ RBIGNUM_SIGN(x) ? BDIGMAX : 0;
}
+
if (!RBIGNUM_SIGN(z)) get2comp(z);
return bignorm(z);
}