diff options
author | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-06-25 21:53:58 +0000 |
---|---|---|
committer | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-06-25 21:53:58 +0000 |
commit | 5026d0ae752018bfda74ee04c11f755b7b6adddb (patch) | |
tree | b74b190aecdd85d801bc9ef98de4eb26942836cf /bignum.c | |
parent | 46979cdb96dd3a226e9a995ce1c69ee36daeef78 (diff) | |
download | ruby-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.c | 62 |
1 files changed, 46 insertions, 16 deletions
@@ -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); } |