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>