From 4d906fbc146c657280be940719504fdd56a55af3 Mon Sep 17 00:00:00 2001 From: akr Date: Tue, 25 Jun 2013 16:18:32 +0000 Subject: * bignum.c (bigsub_int): Fix a buffer over read. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@41631 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 4 ++++ bignum.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index dd084e56a3..cd1c371bca 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Wed Jun 26 01:17:29 2013 Tanaka Akira + + * bignum.c (bigsub_int): Fix a buffer over read. + Tue Jun 25 22:45:43 2013 Tanaka Akira * bignum.c (rb_absint_singlebit_p): Use POW2_P. diff --git a/bignum.c b/bignum.c index 4cf04ab98e..3c7ba28f8c 100644 --- a/bignum.c +++ b/bignum.c @@ -3091,7 +3091,7 @@ bigsub_int(VALUE x, long y0) { VALUE z; BDIGIT *xds, *zds; - long xn; + long xn, zn; BDIGIT_DBL_SIGNED num; long i, y; @@ -3099,10 +3099,19 @@ bigsub_int(VALUE x, long y0) xds = BDIGITS(x); xn = RBIGNUM_LEN(x); - z = bignew(xn, RBIGNUM_SIGN(x)); + if (xn == 0) + return LONG2NUM(-y0); + + zn = xn; +#if SIZEOF_BDIGITS < SIZEOF_LONG + if (zn < bdigit_roomof(SIZEOF_LONG)) + zn = bdigit_roomof(SIZEOF_LONG); +#endif + z = bignew(zn, RBIGNUM_SIGN(x)); zds = BDIGITS(z); #if SIZEOF_BDIGITS >= SIZEOF_LONG + assert(xn == zn); num = (BDIGIT_DBL_SIGNED)xds[0] - y; if (xn == 1 && num < 0) { RBIGNUM_SET_SIGN(z, !RBIGNUM_SIGN(x)); @@ -3113,26 +3122,62 @@ bigsub_int(VALUE x, long y0) zds[0] = BIGLO(num); num = BIGDN(num); i = 1; + if (i < xn) + goto y_is_zero_x; + goto finish; #else num = 0; - for (i=0; i