Date: Mon, 15 Jan 2001 13:50:06 -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: <200101152150.f0FLo6P19676@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: wollman@khavrinen.lcs.mit.edu Cc: freebsd-gnats-submit@FreeBSD.ORG Subject: Re: bin/15070: vfprintf/cvt/__dtoa race condition in threaded programs Date: Mon, 15 Jan 2001 22:48:55 +0100 > Since the interface is purely internal, it would be better to simply > *fix* it.... Like this ? Index: lib/libc/stdlib/strtod.c =================================================================== RCS file: /home/ncvs/src/lib/libc/stdlib/strtod.c,v retrieving revision 1.3 diff -u -r1.3 strtod.c --- lib/libc/stdlib/strtod.c 1996/07/12 18:55:22 1.3 +++ lib/libc/stdlib/strtod.c 2001/01/15 21:06:01 @@ -371,6 +371,16 @@ static Bigint *freelist[Kmax+1]; + /* + * Make Balloc/Bfree thread-safe in libc for use with + * kernel threads. + */ +#include "libc_private.h" +#include "spinlock.h" +static spinlock_t thread_lock = _SPINLOCK_INITIALIZER; +#define THREAD_LOCK() if (__isthreaded) _SPINLOCK(&thread_lock); +#define THREAD_UNLOCK() if (__isthreaded) _SPINUNLOCK(&thread_lock); + static Bigint * Balloc #ifdef KR_headers @@ -382,9 +392,12 @@ int x; Bigint *rv; + THREAD_LOCK(); if ( (rv = freelist[k]) ) { freelist[k] = rv->next; + THREAD_UNLOCK(); } else { + THREAD_UNLOCK(); x = 1 << k; rv = (Bigint *)malloc(sizeof(Bigint) + (x-1)*sizeof(long)); rv->k = k; @@ -403,8 +416,10 @@ #endif { if (v) { + THREAD_LOCK(); v->next = freelist[v->k]; freelist[v->k] = v; + THREAD_UNLOCK(); } } @@ -1839,10 +1854,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 @@ -1890,15 +1906,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 */ @@ -2057,11 +2064,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); + s = s0 = *resultp; if (ilim >= 0 && ilim <= Quick_max && try_quick) { Index: lib/libc/stdio/vfprintf.c =================================================================== RCS file: /home/ncvs/src/lib/libc/stdio/vfprintf.c,v retrieving revision 1.23 diff -u -r1.23 vfprintf.c --- lib/libc/stdio/vfprintf.c 2001/01/06 20:48:00 1.23 +++ lib/libc/stdio/vfprintf.c 2001/01/15 21:43:09 @@ -264,7 +264,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 */ @@ -310,6 +310,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 */ @@ -418,6 +419,9 @@ } +#ifdef FLOATING_POINT + dtoaresult = NULL; +#endif FLOCKFILE(fp); /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */ if (cantwrite(fp)) { @@ -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'; @@ -865,6 +873,10 @@ done: FLUSH(); error: +#ifdef FLOATING_POINT + if (dtoaresult != NULL) + free(dtoaresult); +#endif if (__sferror(fp)) ret = EOF; FUNLOCKFILE(fp); @@ -1203,13 +1215,14 @@ #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(value, ndigits, flags, sign, decpt, ch, length) +cvt(value, ndigits, flags, sign, decpt, ch, length, dtoaresultp) double value; int ndigits, flags, *decpt, ch, *length; char *sign; + char **dtoaresultp; { int mode, dsgn; char *digits, *bp, *rve; @@ -1231,7 +1244,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; - Tor Egge 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?200101152150.f0FLo6P19676>