aboutsummaryrefslogtreecommitdiffstats
path: root/bignum.c
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-06-25 21:53:58 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-06-25 21:53:58 +0000
commit5026d0ae752018bfda74ee04c11f755b7b6adddb (patch)
treeb74b190aecdd85d801bc9ef98de4eb26942836cf /bignum.c
parent46979cdb96dd3a226e9a995ce1c69ee36daeef78 (diff)
downloadruby-5026d0ae752018bfda74ee04c11f755b7b6adddb.tar.gz
* bignum.c (bigadd_int): Fix a buffer over read.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@41636 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'bignum.c')
-rw-r--r--bignum.c62
1 files changed, 46 insertions, 16 deletions
diff --git a/bignum.c b/bignum.c
index 3c7ba28f8c..750fd84b43 100644
--- a/bignum.c
+++ b/bignum.c
@@ -3195,12 +3195,16 @@ bigadd_int(VALUE x, long y)
xds = BDIGITS(x);
xn = RBIGNUM_LEN(x);
- if (xn < 2) {
- zn = 3;
- }
- else {
- zn = xn + 1;
- }
+ if (xn == 0)
+ return LONG2NUM(y);
+
+ zn = xn;
+#if SIZEOF_BDIGITS < SIZEOF_LONG
+ if (zn < bdigit_roomof(SIZEOF_LONG))
+ zn = bdigit_roomof(SIZEOF_LONG);
+#endif
+ zn++;
+
z = bignew(zn, RBIGNUM_SIGN(x));
zds = BDIGITS(z);
@@ -3209,29 +3213,55 @@ bigadd_int(VALUE x, long y)
zds[0] = BIGLO(num);
num = BIGDN(num);
i = 1;
+ if (i < xn)
+ goto y_is_zero_x;
+ goto y_is_zero_z;
#else
num = 0;
- for (i=0; i<bdigit_roomof(SIZEOF_LONG); i++) {
+ for (i=0; i < xn; i++) {
+ if (y == 0) goto y_is_zero_x;
num += (BDIGIT_DBL)xds[i] + BIGLO(y);
zds[i] = BIGLO(num);
num = BIGDN(num);
y = BIGDN(y);
}
+ for (; i < zn; i++) {
+ if (y == 0) goto y_is_zero_z;
+ num += BIGLO(y);
+ zds[i] = BIGLO(num);
+ num = BIGDN(num);
+ y = BIGDN(y);
+ }
+ goto finish;
+
#endif
- while (num && i < xn) {
- num += xds[i];
- zds[i++] = BIGLO(num);
+
+ for (;i < xn; i++) {
+ y_is_zero_x:
+ if (num == 0) goto num_is_zero_x;
+ num += (BDIGIT_DBL)xds[i];
+ zds[i] = BIGLO(num);
num = BIGDN(num);
}
- if (num) zds[i++] = (BDIGIT)num;
- else while (i < xn) {
+ for (; i < zn; i++) {
+ y_is_zero_z:
+ if (num == 0) goto num_is_zero_z;
+ zds[i] = BIGLO(num);
+ num = BIGDN(num);
+ }
+ goto finish;
+
+ for (;i < xn; i++) {
+ num_is_zero_x:
zds[i] = xds[i];
- i++;
}
- assert(i <= zn);
- while (i < zn) {
- zds[i++] = 0;
+ for (; i < zn; i++) {
+ num_is_zero_z:
+ zds[i] = 0;
}
+ goto finish;
+
+ finish:
RB_GC_GUARD(x);
return bignorm(z);
}