[cp-patches] Patch: FYI: fix classpath/23863

Tom Tromey tromey at redhat.com
Fri Jun 9 16:10:07 UTC 2006


I'm checking this in to Classpath and also to GCC svn trunk.

This fixes PR 23863, a bug in mprec.  The bug is that when parsing
certain doubles, we can overwrite the stack.  This showed up when
using a gcj-compiled ecj to compile GNU Classpath.

The fix is to import a new version of mprec.c from newlib, and then to
apply a small patch to let it dynamically grow its freelist.  This way
any size bigint can be allocated and the stack will never be trashed.

This patch also adds an assert in the place where we were previously
returning a bad result, to help insure against regressions.

Tested on x86 FC4 by re-running ecj1 on the failing compilation.

Tom

Index: ChangeLog
from  Tom Tromey  <tromey at redhat.com>

	PR classpath/23863:
	* native/fdlibm/dtoa.c (_dtoa): Free contents of _Jv_reent when
	finished.
	* native/fdlibm/mprec.c: New version from newlib.  Commented out
	some includes.  Added <assert.h>.
	(_reent, _Bigint): New defines.
	(_REENT_CHECK_MP, _REENT_MP_FREELIST, _REENT_MP_P5S): Likewise.
	(__ULong, __Long): New types.
	(_calloc_r): New function.
	(Balloc): Dynamically add new _freelist entries as needed.
	* native/fdlibm/mprec.h (struct _Jv_Bigint): Don't use
	MAX_BIGNUMS to size _x[].
	(struct _Jv_reent): _freelist now a _Jv_Bigint**.  Removed
	_allocation_map, num.  Added _max_k.

Index: native/fdlibm/dtoa.c
===================================================================
RCS file: /cvsroot/classpath/classpath/native/fdlibm/dtoa.c,v
retrieving revision 1.4
diff -u -r1.4 dtoa.c
--- native/fdlibm/dtoa.c 5 Mar 2005 14:46:53 -0000 1.4
+++ native/fdlibm/dtoa.c 9 Jun 2006 16:10:26 -0000
@@ -2,7 +2,7 @@
  *
  * The author of this software is David M. Gay.
  *
- * Copyright (c) 1991 by AT&T.
+ * Copyright (c) 1991, 2006 by AT&T.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose without fee is hereby granted, provided that this entire notice
@@ -897,10 +897,23 @@
 {
   struct _Jv_reent reent;
   char *p;
+  int i;
+
   memset (&reent, 0, sizeof reent);
 
   p = _dtoa_r (&reent, _d, mode, ndigits, decpt, sign, rve, float_type);
   strcpy (buf, p);
 
-  return;
+  for (i = 0; i < reent._result_k; ++i)
+    {
+      struct _Jv_Bigint *l = reent._freelist[i];
+      while (l)
+	{
+	  struct _Jv_Bigint *next = l->_next;
+	  free (l);
+	  l = next;
+	}
+    }
+  if (reent._freelist)
+    free (reent._freelist);
 }
Index: native/fdlibm/mprec.c
===================================================================
RCS file: /cvsroot/classpath/classpath/native/fdlibm/mprec.c,v
retrieving revision 1.7
diff -u -r1.7 mprec.c
--- native/fdlibm/mprec.c 12 Jan 2006 09:26:49 -0000 1.7
+++ native/fdlibm/mprec.c 9 Jun 2006 16:10:26 -0000
@@ -80,72 +80,112 @@
  *	down depends on the machine and the number being converted.
  */
 
+/*#include <_ansi.h>*/
 #include <assert.h>
 #include <stdlib.h>
 #include <string.h>
+/* #include <reent.h> */
 #include "mprec.h"
 
 /* reent.c knows this value */
-#define _Kmax 15
-#include <stdio.h>
+/* #define _Kmax 15 */
 
-_Jv_Bigint *
-_DEFUN (Balloc, (ptr, k), struct _Jv_reent *ptr _AND int k)
-{
-  _Jv_Bigint *rv = NULL;
+#define _reent _Jv_reent
+#define _Bigint _Jv_Bigint
 
-  int i = 0;
-  int j = 1;
+#define _REENT_CHECK_MP(x)
+#define _REENT_MP_FREELIST(x) ((x)->_freelist)
+#define _REENT_MP_P5S(x) ((x)->_p5s)
 
-  /* FIXME - assert disabled because of PR classpath/23863
-   * assert ((1 << k) < MAX_BIGNUM_WDS);
-   */
+typedef unsigned long __ULong;
+typedef long __Long;
 
-  while ((ptr->_allocation_map & j) && i < MAX_BIGNUMS)
-    i++, j <<= 1;
+static void *
+_calloc_r (void *ignore, size_t x1, size_t x2)
+{
+  char *result = (char *) malloc (x1 * x2);
+  memset (result, 0, x1 * x2);
+  return result;
+}
 
-  assert (i < MAX_BIGNUMS);
+_Bigint *
+_DEFUN (Balloc, (ptr, k), struct _reent *ptr _AND int k)
+{
+  int x;
+  _Bigint *rv ;
+  int new_k = k + 1;
 
-  if (i >= MAX_BIGNUMS) 
-    return NULL;
+  _REENT_CHECK_MP(ptr);
+  if (_REENT_MP_FREELIST(ptr) == NULL)
+    {
+      /* Allocate a list of pointers to the mprec objects */
+      _REENT_MP_FREELIST(ptr) = (struct _Bigint **) _calloc_r (ptr, 
+						      sizeof (struct _Bigint *),
+							       new_k);
+      if (_REENT_MP_FREELIST(ptr) == NULL)
+	{
+	  return NULL;
+	}
+      ptr->_max_k = new_k;
+    }
+  else if (new_k > ptr->_max_k)
+    {
+      struct _Bigint **new_list
+	= (struct _Bigint **) realloc (ptr->_freelist,
+				       new_k * sizeof (struct _Bigint *));
+      memset (&new_list[ptr->_max_k], 0,
+	      (new_k - ptr->_max_k) * sizeof (struct _Bigint *));
+      ptr->_freelist = new_list;
+      ptr->_max_k = new_k;
+
+    }
 
-  ptr->_allocation_map |= j;
-  rv = &ptr->_freelist[i];
-      
-  rv->_k = k;
-  rv->_maxwds = 32;
+  assert (k <= ptr->_max_k);
 
+  if ((rv = _REENT_MP_FREELIST(ptr)[k]) != 0)
+    {
+      _REENT_MP_FREELIST(ptr)[k] = rv->_next;
+    }
+  else
+    {
+      x = 1 << k;
+      /* Allocate an mprec Bigint and stick in in the freelist */
+      rv = (_Bigint *) _calloc_r (ptr,
+				  1,
+				  sizeof (_Bigint) +
+				  (x-1) * sizeof(rv->_x));
+      if (rv == NULL) return NULL;
+      rv->_k = k;
+      rv->_maxwds = x;
+    }
+  rv->_sign = rv->_wds = 0;
   return rv;
 }
 
-
 void
-_DEFUN (Bfree, (ptr, v), struct _Jv_reent *ptr _AND _Jv_Bigint * v)
+_DEFUN (Bfree, (ptr, v), struct _reent *ptr _AND _Bigint * v)
 {
-  long i;
-
-  i = v - ptr->_freelist;
-
-  assert (i >= 0 && i < MAX_BIGNUMS);
-
-  if (i >= 0 && i < MAX_BIGNUMS)
-    ptr->_allocation_map &= ~ (1 << i);
+  _REENT_CHECK_MP(ptr);
+  if (v)
+    {
+      v->_next = _REENT_MP_FREELIST(ptr)[v->_k];
+      _REENT_MP_FREELIST(ptr)[v->_k] = v;
+    }
 }
 
-
-_Jv_Bigint *
+_Bigint *
 _DEFUN (multadd, (ptr, b, m, a),
-	struct _Jv_reent *ptr _AND
-	_Jv_Bigint * b _AND
+	struct _reent *ptr _AND
+	_Bigint * b _AND
 	int m _AND
 	int a)
 {
   int i, wds;
-  unsigned long *x, y;
+  __ULong *x, y;
 #ifdef Pack_32
-  unsigned long xi, z;
+  __ULong xi, z;
 #endif
-  _Jv_Bigint *b1;
+  _Bigint *b1;
 
   wds = b->_wds;
   x = b->_x;
@@ -180,17 +220,17 @@
   return b;
 }
 
-_Jv_Bigint *
+_Bigint *
 _DEFUN (s2b, (ptr, s, nd0, nd, y9),
-	struct _Jv_reent * ptr _AND
+	struct _reent * ptr _AND
 	_CONST char *s _AND
 	int nd0 _AND
 	int nd _AND
-	unsigned long y9)
+	__ULong y9)
 {
-  _Jv_Bigint *b;
+  _Bigint *b;
   int i, k;
-  long x, y;
+  __Long x, y;
 
   x = (nd + 8) / 9;
   for (k = 0, y = 1; x > y; y <<= 1, k++);
@@ -222,7 +262,7 @@
 
 int
 _DEFUN (hi0bits,
-	(x), register unsigned long x)
+	(x), register __ULong x)
 {
   register int k = 0;
 
@@ -256,10 +296,10 @@
 }
 
 int
-_DEFUN (lo0bits, (y), unsigned long *y)
+_DEFUN (lo0bits, (y), __ULong *y)
 {
   register int k;
-  register unsigned long x = *y;
+  register __ULong x = *y;
 
   if (x & 7)
     {
@@ -298,17 +338,17 @@
     {
       k++;
       x >>= 1;
-      if (!(x & 1))
+      if (!x & 1)
 	return 32;
     }
   *y = x;
   return k;
 }
 
-_Jv_Bigint *
-_DEFUN (i2b, (ptr, i), struct _Jv_reent * ptr _AND int i)
+_Bigint *
+_DEFUN (i2b, (ptr, i), struct _reent * ptr _AND int i)
 {
-  _Jv_Bigint *b;
+  _Bigint *b;
 
   b = Balloc (ptr, 1);
   b->_x[0] = i;
@@ -316,15 +356,15 @@
   return b;
 }
 
-_Jv_Bigint *
-_DEFUN (mult, (ptr, a, b), struct _Jv_reent * ptr _AND _Jv_Bigint * a _AND _Jv_Bigint * b)
+_Bigint *
+_DEFUN (mult, (ptr, a, b), struct _reent * ptr _AND _Bigint * a _AND _Bigint * b)
 {
-  _Jv_Bigint *c;
+  _Bigint *c;
   int k, wa, wb, wc;
-  unsigned long carry, y, z;
-  unsigned long *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
+  __ULong carry, y, z;
+  __ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
 #ifdef Pack_32
-  unsigned long z2;
+  __ULong z2;
 #endif
 
   if (a->_wds < b->_wds)
@@ -350,7 +390,7 @@
 #ifdef Pack_32
   for (; xb < xbe; xb++, xc0++)
     {
-      if ((y = *xb & 0xffff))
+      if ((y = *xb & 0xffff) != 0)
 	{
 	  x = xa;
 	  xc = xc0;
@@ -366,7 +406,7 @@
 	  while (x < xae);
 	  *xc = carry;
 	}
-      if ((y = *xb >> 16))
+      if ((y = *xb >> 16) != 0)
 	{
 	  x = xa;
 	  xc = xc0;
@@ -387,7 +427,7 @@
 #else
   for (; xb < xbe; xc0++)
     {
-      if ((y = *xb++))
+      if (y = *xb++)
 	{
 	  x = xa;
 	  xc = xc0;
@@ -408,23 +448,24 @@
   return c;
 }
 
-_Jv_Bigint *
+_Bigint *
 _DEFUN (pow5mult,
-	(ptr, b, k), struct _Jv_reent * ptr _AND _Jv_Bigint * b _AND int k)
+	(ptr, b, k), struct _reent * ptr _AND _Bigint * b _AND int k)
 {
-  _Jv_Bigint *b1, *p5, *p51;
+  _Bigint *b1, *p5, *p51;
   int i;
   static _CONST int p05[3] = {5, 25, 125};
 
-  if ((i = k & 3))
+  if ((i = k & 3) != 0)
     b = multadd (ptr, b, p05[i - 1], 0);
 
   if (!(k >>= 2))
     return b;
-  if (!(p5 = ptr->_p5s))
+  _REENT_CHECK_MP(ptr);
+  if (!(p5 = _REENT_MP_P5S(ptr)))
     {
       /* first time */
-      p5 = ptr->_p5s = i2b (ptr, 625);
+      p5 = _REENT_MP_P5S(ptr) = i2b (ptr, 625);
       p5->_next = 0;
     }
   for (;;)
@@ -447,12 +488,12 @@
   return b;
 }
 
-_Jv_Bigint *
-_DEFUN (lshift, (ptr, b, k), struct _Jv_reent * ptr _AND _Jv_Bigint * b _AND int k)
+_Bigint *
+_DEFUN (lshift, (ptr, b, k), struct _reent * ptr _AND _Bigint * b _AND int k)
 {
   int i, k1, n, n1;
-  _Jv_Bigint *b1;
-  unsigned long *x, *x1, *xe, z;
+  _Bigint *b1;
+  __ULong *x, *x1, *xe, z;
 
 #ifdef Pack_32
   n = k >> 5;
@@ -480,7 +521,7 @@
 	  z = *x++ >> k1;
 	}
       while (x < xe);
-      if ((*x1 = z))
+      if ((*x1 = z) != 0)
 	++n1;
     }
 #else
@@ -490,11 +531,11 @@
       z = 0;
       do
 	{
-	  *x1++ = (*x << k & 0xffff) | z;
+	  *x1++ = *x << k & 0xffff | z;
 	  z = *x++ >> k1;
 	}
       while (x < xe);
-      if ((*x1 = z))
+      if (*x1 = z)
 	++n1;
     }
 #endif
@@ -508,9 +549,9 @@
 }
 
 int
-_DEFUN (cmp, (a, b), _Jv_Bigint * a _AND _Jv_Bigint * b)
+_DEFUN (cmp, (a, b), _Bigint * a _AND _Bigint * b)
 {
-  unsigned long *xa, *xa0, *xb, *xb0;
+  __ULong *xa, *xa0, *xb, *xb0;
   int i, j;
 
   i = a->_wds;
@@ -537,16 +578,16 @@
   return 0;
 }
 
-_Jv_Bigint *
-_DEFUN (diff, (ptr, a, b), struct _Jv_reent * ptr _AND
-	_Jv_Bigint * a _AND _Jv_Bigint * b)
+_Bigint *
+_DEFUN (diff, (ptr, a, b), struct _reent * ptr _AND
+	_Bigint * a _AND _Bigint * b)
 {
-  _Jv_Bigint *c;
+  _Bigint *c;
   int i, wa, wb;
-  long borrow, y;		/* We need signed shifts here. */
-  unsigned long *xa, *xae, *xb, *xbe, *xc;
+  __Long borrow, y;		/* We need signed shifts here. */
+  __ULong *xa, *xae, *xb, *xbe, *xc;
 #ifdef Pack_32
-  long z;
+  __Long z;
 #endif
 
   i = cmp (a, b);
@@ -625,7 +666,7 @@
 _DEFUN (ulp, (_x), double _x)
 {
   union double_union x, a;
-  register long L;
+  register __Long L;
 
   x.d = _x;
 
@@ -659,7 +700,7 @@
 	  word0 (a) = 0;
 	  L -= Exp_shift;
 #ifndef _DOUBLE_IS_32BITS
-	  word1 (a) = L >= 31 ? 1 : 1 << (31 - L);
+         word1 (a) = L >= 31 ? 1 : 1 << (31 - L);
 #endif
 	}
     }
@@ -669,13 +710,13 @@
 
 double
 _DEFUN (b2d, (a, e),
-	_Jv_Bigint * a _AND int *e)
+	_Bigint * a _AND int *e)
 {
-  unsigned long *xa, *xa0, w, y, z;
+  __ULong *xa, *xa0, w, y, z;
   int k;
   union double_union d;
 #ifdef VAX
-  unsigned long d0, d1;
+  __ULong d0, d1;
 #else
 #define d0 word0(d)
 #define d1 word1(d)
@@ -696,7 +737,7 @@
       d0 = Exp_1 | y >> (Ebits - k);
       w = xa > xa0 ? *--xa : 0;
 #ifndef _DOUBLE_IS_32BITS
-      d1 = y << (32 - Ebits + k) | w >> (Ebits - k);
+      d1 = y << ((32 - Ebits) + k) | w >> (Ebits - k);
 #endif
       goto ret_d;
     }
@@ -720,18 +761,18 @@
   if (k < Ebits + 16)
     {
       z = xa > xa0 ? *--xa : 0;
-      d0 = Exp_1 | y << (k - Ebits) | z >> (Ebits + 16 - k);
+      d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
       w = xa > xa0 ? *--xa : 0;
       y = xa > xa0 ? *--xa : 0;
-      d1 = z << (k + 16 - Ebits) | w << (k - Ebits) | y >> (16 + Ebits - k);
+      d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
       goto ret_d;
     }
   z = xa > xa0 ? *--xa : 0;
   w = xa > xa0 ? *--xa : 0;
   k -= Ebits + 16;
-  d0 = Exp_1 | y << (k + 16) | z << k | w >> (16 - k);
+  d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
   y = xa > xa0 ? *--xa : 0;
-  d1 = w << (k + 16) | y << k;
+  d1 = w << k + 16 | y << k;
 #endif
 ret_d:
 #ifdef VAX
@@ -744,22 +785,24 @@
   return d.d;
 }
 
-_Jv_Bigint *
+_Bigint *
 _DEFUN (d2b,
 	(ptr, _d, e, bits),
-	struct _Jv_reent * ptr _AND
+	struct _reent * ptr _AND
 	double _d _AND
 	int *e _AND
 	int *bits)
 
 {
   union double_union d;
-  _Jv_Bigint *b;
+  _Bigint *b;
   int de, i, k;
-  unsigned long *x, y, z;
+  __ULong *x, y, z;
 #ifdef VAX
-  unsigned long d0, d1;
+  __ULong d0, d1;
+#endif
   d.d = _d;
+#ifdef VAX
   d0 = word0 (d) >> 16 | word0 (d) << 16;
   d1 = word1 (d) >> 16 | word1 (d) << 16;
 #else
@@ -783,16 +826,18 @@
   z |= Exp_msk11;
 #endif
 #else
-  if ((de = (int) (d0 >> Exp_shift)))
+  if ((de = (int) (d0 >> Exp_shift)) != 0)
     z |= Exp_msk1;
 #endif
 #ifdef Pack_32
 #ifndef _DOUBLE_IS_32BITS
-  if ((y = d1))
+  if (d1)
     {
-      if ((k = lo0bits (&y)))
+      y = d1;
+      k = lo0bits (&y);
+      if (k)
 	{
-	  x[0] = y | z << (32 - k);
+         x[0] = y | z << (32 - k);
 	  z >>= k;
 	}
       else
@@ -814,22 +859,24 @@
 #endif
     }
 #else
-  if ((y = d1))
+  if (d1)
     {
-      if ((k = lo0bits (&y)))
+      y = d1;
+      k = lo0bits (&y);
+      if (k)
 	if (k >= 16)
 	  {
-	    x[0] = y | (z << (32 - k) & 0xffff);
-	    x[1] = z >> (k - 16) & 0xffff;
+	    x[0] = y | z << 32 - k & 0xffff;
+	    x[1] = z >> k - 16 & 0xffff;
 	    x[2] = z >> k;
 	    i = 2;
 	  }
 	else
 	  {
 	    x[0] = y & 0xffff;
-	    x[1] = (y >> 16 | z << (16 - k)) & 0xffff;
+	    x[1] = y >> 16 | z << 16 - k & 0xffff;
 	    x[2] = z >> k & 0xffff;
-	    x[3] = z >> (k + 16);
+	    x[3] = z >> k + 16;
 	    i = 3;
 	  }
       else
@@ -894,7 +941,7 @@
 #undef d1
 
 double
-_DEFUN (ratio, (a, b), _Jv_Bigint * a _AND _Jv_Bigint * b)
+_DEFUN (ratio, (a, b), _Bigint * a _AND _Bigint * b)
 
 {
   union double_union da, db;
@@ -958,3 +1005,17 @@
 #endif
 
 
+double
+_DEFUN (_mprec_log10, (dig),
+	int dig)
+{
+  double v = 1.0;
+  if (dig < 24)
+    return tens[dig];
+  while (dig > 0)
+    {
+      v *= 10;
+      dig--;
+    }
+  return v;
+}
Index: native/fdlibm/mprec.h
===================================================================
RCS file: /cvsroot/classpath/classpath/native/fdlibm/mprec.h,v
retrieving revision 1.8
diff -u -r1.8 mprec.h
--- native/fdlibm/mprec.h 4 Jan 2006 16:37:55 -0000 1.8
+++ native/fdlibm/mprec.h 9 Jun 2006 16:10:27 -0000
@@ -282,7 +282,7 @@
 {
   struct _Jv_Bigint *_next;
   int _k, _maxwds, _sign, _wds;
-  unsigned long _x[MAX_BIGNUM_WDS];
+  unsigned long _x[1];
 };
 
 
@@ -310,10 +310,8 @@
   int _result_k;
   struct _Jv_Bigint *_p5s;
 
-  struct _Jv_Bigint _freelist[MAX_BIGNUMS];
-  int _allocation_map;
-
-  int num;
+  struct _Jv_Bigint **_freelist;
+  int _max_k;
 };
 
 



More information about the Classpath-patches mailing list