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>
