--- vfscanf.c.orig Tue Nov 18 16:48:06 2003 +++ vfscanf.c Tue Nov 18 17:35:55 2003 @@ -99,7 +99,9 @@ #define CT_FLOAT 4 /* %[efgEFG] conversion */ static const u_char *__sccl(char *, const u_char *); -static int parsefloat(FILE *, char *, char *); +#ifdef FLOATING_POINT +static int parsefloat(FILE *, char **, size_t); +#endif /* FLOATING_POINT */ int __scanfdebug = 0; @@ -133,7 +135,6 @@ int flags; /* flags as defined above */ char *p0; /* saves original value of p when necessary */ int nassigned; /* number of fields assigned */ - int nconversions; /* number of conversions */ int nread; /* number of characters consumed from fp */ int base; /* base argument to conversion function */ char ccltab[256]; /* character class table for %[...] */ @@ -150,7 +151,6 @@ ORIENT(fp, -1); nassigned = 0; - nconversions = 0; nread = 0; for (;;) { c = *fmt++; @@ -288,7 +288,6 @@ break; case 'n': - nconversions++; if (flags & SUPPRESS) /* ??? */ continue; if (flags & SHORTSHORT) @@ -421,7 +420,6 @@ nread += r; nassigned++; } - nconversions++; break; case CT_CCL: @@ -525,7 +523,6 @@ nassigned++; } nread += n; - nconversions++; break; case CT_STRING: @@ -607,7 +604,6 @@ nread += p - p0; nassigned++; } - nconversions++; continue; case CT_INT: @@ -758,39 +754,42 @@ nassigned++; } nread += p - buf; - nconversions++; break; #ifdef FLOATING_POINT case CT_FLOAT: + { + char *pbuf; /* scan a floating point number as if by strtod */ - if (width == 0 || width > sizeof(buf) - 1) - width = sizeof(buf) - 1; - if ((width = parsefloat(fp, buf, buf + width)) == 0) + if ((width = parsefloat(fp, &pbuf, width)) == 0) { + if (pbuf) + free(pbuf); goto match_failure; + } if ((flags & SUPPRESS) == 0) { if (flags & LONGDBL) { - long double res = strtold(buf, &p); + long double res = strtold(pbuf, &p); *va_arg(ap, long double *) = res; } else if (flags & LONG) { - double res = strtod(buf, &p); + double res = strtod(pbuf, &p); *va_arg(ap, double *) = res; } else { - float res = strtof(buf, &p); + float res = strtof(pbuf, &p); *va_arg(ap, float *) = res; } - if (__scanfdebug && p - buf != width) + if (__scanfdebug && p - pbuf != width) abort(); nassigned++; } nread += width; - nconversions++; + free(pbuf); break; + } #endif /* FLOATING_POINT */ } } input_failure: - return (nconversions != 0 ? nassigned : EOF); + return (nassigned ? nassigned : EOF); match_failure: return (nassigned); } @@ -910,7 +909,7 @@ #ifdef FLOATING_POINT static int -parsefloat(FILE *fp, char *buf, char *end) +parsefloat(FILE *fp, char **buf, size_t width) { char *commit, *p; int infnanpos = 0; @@ -921,7 +920,16 @@ unsigned char c; char decpt = *localeconv()->decimal_point; _Bool gotmantdig = 0, ishex = 0; + char *b, *e; + size_t s; + s = (width == 0 ? BUF : width + 1); + b = (char *)malloc(s); + if (b == NULL) { + *buf = NULL; + return 0; + } + e = b + (s - 1); /* * We set commit = p whenever the string we have read so far * constitutes a valid representation of a floating point @@ -931,8 +939,8 @@ * always necessary to read at least one character that doesn't * match; thus, we can't short-circuit "infinity" or "nan(...)". */ - commit = buf - 1; - for (p = buf; p < end; ) { + commit = b - 1; + for (p = b; width == 0 || p < e; ) { c = *fp->_p; reswitch: switch (state) { @@ -1046,6 +1054,17 @@ default: abort(); } + if (p >= e) { + size_t diff = (p - b); + s += BUF; + b = (char *)reallocf(b, s); + if (b == NULL) { + *buf = NULL; + return 0; + } + e = b + (s - 1); + p = b + diff; + } *p++ = c; if (--fp->_r > 0) fp->_p++; @@ -1057,6 +1076,7 @@ while (commit < --p) __ungetc(*(u_char *)p, fp); *++commit = '\0'; - return (commit - buf); + *buf = b; + return (commit - b); } #endif