Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 14 Feb 2001 13:10:02 -0800 (PST)
From:      Tor.Egge@fast.no
To:        freebsd-bugs@FreeBSD.org
Subject:   Re: bin/15070: vfprintf/cvt/__dtoa race condition in threaded programs
Message-ID:  <200102142110.f1ELA2d66506@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR bin/15070; it has been noted by GNATS.

From: Tor.Egge@fast.no
To: Daniel Eischen <deischen@FreeBSD.org>, jdp@polstra.com
Cc: freebsd-gnats-submit@FreeBSD.org, Mike Smith <msmith@FreeBSD.org>
Subject: Re: bin/15070: vfprintf/cvt/__dtoa race condition in threaded programs
Date: Wed, 14 Feb 2001 22:02:36 +0100

 An updated patch that doesn't use spinlocks is enclosed.
 
 - Tor Egge
 
 
 Index: lib/libc/stdio/vfprintf.c
 ===================================================================
 RCS file: /home/ncvs/src/lib/libc/stdio/vfprintf.c,v
 retrieving revision 1.27
 diff -u -r1.27 vfprintf.c
 --- lib/libc/stdio/vfprintf.c	2001/02/10 06:25:33	1.27
 +++ lib/libc/stdio/vfprintf.c	2001/02/10 22:29:23
 @@ -268,7 +268,7 @@
  #define	BUF		(MAXEXP+MAXFRACT+1)	/* + decimal point */
  #define	DEFPREC		6
  
 -static char *cvt __P((double, int, int, char *, int *, int, int *));
 +static char *cvt __P((double, int, int, char *, int *, int, int *, char **));
  static int exponent __P((char *, int, int));
  
  #else /* no FLOATING_POINT */
 @@ -315,6 +315,7 @@
  	int expsize;		/* character count for expstr */
  	int ndig;		/* actual number of digits returned by cvt */
  	char expstr[7];		/* buffer for exponent string */
 +	char *dtoaresult;	/* buffer allocated by dtoa */
  #endif
  	u_long	ulval;		/* integer arguments %[diouxX] */
  	u_quad_t uqval;		/* %q integers */
 @@ -423,6 +424,9 @@
          }
          
  
 +#ifdef FLOATING_POINT
 +	dtoaresult = NULL;
 +#endif
  	/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
  	if (cantwrite(fp))
  		return (EOF);
 @@ -608,8 +612,12 @@
  				break;
  			}
  			flags |= FPT;
 +			if (dtoaresult != NULL) {
 +				free(dtoaresult);
 +				dtoaresult = NULL;
 +			}
  			cp = cvt(_double, prec, flags, &softsign,
 -				&expt, ch, &ndig);
 +				&expt, ch, &ndig, &dtoaresult);
  			if (ch == 'g' || ch == 'G') {
  				if (expt <= -4 || expt > prec)
  					ch = (ch == 'g') ? 'e' : 'E';
 @@ -864,6 +872,10 @@
  done:
  	FLUSH();
  error:
 +#ifdef FLOATING_POINT
 +	if (dtoaresult != NULL)
 +		free(dtoaresult);
 +#endif
  	if (__sferror(fp))
  		ret = EOF;
          if ((argtable != NULL) && (argtable != statargtable))
 @@ -1195,11 +1207,11 @@
  
  #ifdef FLOATING_POINT
  
 -extern char *__dtoa __P((double, int, int, int *, int *, char **));
 +extern char *__dtoa __P((double, int, int, int *, int *, char **, char **));
  
  static char *
  cvt(double value, int ndigits, int flags, char *sign, int *decpt,
 -    int ch, int *length)
 +    int ch, int *length, char **dtoaresultp)
  {
  	int mode, dsgn;
  	char *digits, *bp, *rve;
 @@ -1221,7 +1233,8 @@
  		*sign = '-';
  	} else
  		*sign = '\000';
 -	digits = __dtoa(value, mode, ndigits, decpt, &dsgn, &rve);
 +	digits = __dtoa(value, mode, ndigits, decpt, &dsgn, &rve,
 +			dtoaresultp);
  	if ((ch != 'g' && ch != 'G') || flags & ALT) {
  		/* print trailing zeros */
  		bp = digits + ndigits;
 Index: lib/libc/stdlib/netbsd_strtod.c
 ===================================================================
 RCS file: /home/ncvs/src/lib/libc/stdlib/netbsd_strtod.c,v
 retrieving revision 1.4
 diff -u -r1.4 netbsd_strtod.c
 --- lib/libc/stdlib/netbsd_strtod.c	2001/02/09 20:31:47	1.4
 +++ lib/libc/stdlib/netbsd_strtod.c	2001/02/14 20:53:26
 @@ -142,7 +142,7 @@
  #include "memory.h"
  #endif
  #endif
 -char *__dtoa __P((double, int, int, int *, int *, char **));
 +char *__dtoa __P((double, int, int, int *, int *, char **, char **));
  
  #ifdef MALLOC
  #ifdef KR_headers
 @@ -382,8 +382,6 @@
  
   typedef struct Bigint Bigint;
  
 - static Bigint *freelist[Kmax+1];
 -
   static Bigint *
  Balloc
  #ifdef KR_headers
 @@ -395,15 +393,10 @@
  	int x;
  	Bigint *rv;
  
 -	if ((rv = freelist[k]) != NULL) {
 -		freelist[k] = rv->next;
 -		}
 -	else {
 -		x = 1 << k;
 -		rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(Long));
 -		rv->k = k;
 -		rv->maxwds = x;
 -		}
 +	x = 1 << k;
 +	rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(Long));
 +	rv->k = k;
 +	rv->maxwds = x;
  	rv->sign = rv->wds = 0;
  	return rv;
  	}
 @@ -416,10 +409,7 @@
  	(Bigint *v)
  #endif
  {
 -	if (v) {
 -		v->next = freelist[v->k];
 -		freelist[v->k] = v;
 -		}
 +	free(v);
  	}
  
  #define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \
 @@ -1900,10 +1890,11 @@
   char *
  __dtoa
  #ifdef KR_headers
 -	(d, mode, ndigits, decpt, sign, rve)
 -	double d; int mode, ndigits, *decpt, *sign; char **rve;
 +	(d, mode, ndigits, decpt, sign, rve, resultp)
 +	double d; int mode, ndigits, *decpt, *sign; char **rve, **resultp;
  #else
 -	(double d, int mode, int ndigits, int *decpt, int *sign, char **rve)
 +	(double d, int mode, int ndigits, int *decpt, int *sign, char **rve,
 +	 char **resultp)
  #endif
  {
   /*	Arguments ndigits, decpt, sign are similar to those
 @@ -1953,15 +1944,6 @@
  	Bigint *mlo = NULL; /* pacify gcc */
  	double d2, ds, eps;
  	char *s, *s0;
 -	static Bigint *result;
 -	static int result_k;
 -
 -	if (result) {
 -		result->k = result_k;
 -		result->maxwds = 1 << result_k;
 -		Bfree(result);
 -		result = 0;
 -		}
  
  	if (word0(d) & Sign_bit) {
  		/* set sign for everything, including 0's and NaNs */
 @@ -2123,11 +2105,8 @@
  			if (i <= 0)
  				i = 1;
  		}
 -	j = sizeof(ULong);
 -	for(result_k = 0; sizeof(Bigint) - sizeof(ULong) + j <= i;
 -		j <<= 1) result_k++;
 -	result = Balloc(result_k);
 -	s = s0 = (char *)result;
 +	*resultp = (char *) malloc(i + 1);
 +	s = s0 = *resultp;
  
  	if (ilim >= 0 && ilim <= Quick_max && try_quick) {
  
 Index: lib/libc/stdlib/strtod.c
 ===================================================================
 RCS file: /home/ncvs/src/lib/libc/stdlib/strtod.c,v
 retrieving revision 1.6
 diff -u -r1.6 strtod.c
 --- lib/libc/stdlib/strtod.c	2001/02/10 05:05:09	1.6
 +++ lib/libc/stdlib/strtod.c	2001/02/14 20:53:26
 @@ -372,8 +372,6 @@
  
   typedef struct Bigint Bigint;
  
 - static Bigint *freelist[Kmax+1];
 -
   static Bigint *
  Balloc
  #ifdef KR_headers
 @@ -385,14 +383,10 @@
  	int x;
  	Bigint *rv;
  
 -	if ( (rv = freelist[k]) ) {
 -		freelist[k] = rv->next;
 -	} else {
 -		x = 1 << k;
 -		rv = (Bigint *)malloc(sizeof(Bigint) + (x-1)*sizeof(long));
 -		rv->k = k;
 -		rv->maxwds = x;
 -	}
 +	x = 1 << k;
 +	rv = (Bigint *)malloc(sizeof(Bigint) + (x-1)*sizeof(long));
 +	rv->k = k;
 +	rv->maxwds = x;
  	rv->sign = rv->wds = 0;
  	return rv;
  }
 @@ -405,10 +399,7 @@
  	(Bigint *v)
  #endif
  {
 -	if (v) {
 -		v->next = freelist[v->k];
 -		freelist[v->k] = v;
 -	}
 +	free(v);
  }
  
  #define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \
 @@ -1844,10 +1835,11 @@
  char *
  __dtoa
  #ifdef KR_headers
 -	(d, mode, ndigits, decpt, sign, rve)
 -	double d; int mode, ndigits, *decpt, *sign; char **rve;
 +	(d, mode, ndigits, decpt, sign, rve, resultp)
 +	double d; int mode, ndigits, *decpt, *sign; char **rve, **resultp;
  #else
 -	(double d, int mode, int ndigits, int *decpt, int *sign, char **rve)
 +	(double d, int mode, int ndigits, int *decpt, int *sign, char **rve,
 +	 char **resultp)
  #endif
  {
   /*	Arguments ndigits, decpt, sign are similar to those
 @@ -1895,15 +1887,6 @@
  	Bigint *b, *b1, *delta, *mlo, *mhi, *S;
  	double d2, ds, eps;
  	char *s, *s0;
 -	static Bigint *result;
 -	static int result_k;
 -
 -	if (result) {
 -		result->k = result_k;
 -		result->maxwds = 1 << result_k;
 -		Bfree(result);
 -		result = 0;
 -	}
  
  	if (word0(d) & Sign_bit) {
  		/* set sign for everything, including 0's and NaNs */
 @@ -2062,11 +2045,8 @@
  			if (i <= 0)
  				i = 1;
  	}
 -	j = sizeof(unsigned long);
 -	for (result_k = 0; sizeof(Bigint) - sizeof(unsigned long) + j < i;
 -		j <<= 1) result_k++;
 -	result = Balloc(result_k);
 -	s = s0 = (char *)result;
 +	*resultp = (char *) malloc(i + 1);
 +	s = s0 = *resultp;
  
  	if (ilim >= 0 && ilim <= Quick_max && try_quick) {
  
 


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200102142110.f1ELA2d66506>