From owner-freebsd-bugs Sun Feb 2 06:11:17 1997 Return-Path: Received: (from root@localhost) by freefall.freebsd.org (8.8.5/8.8.5) id GAA19094 for bugs-outgoing; Sun, 2 Feb 1997 06:11:17 -0800 (PST) Received: from godzilla.zeta.org.au (godzilla.zeta.org.au [203.2.228.19]) by freefall.freebsd.org (8.8.5/8.8.5) with ESMTP id GAA19084 for ; Sun, 2 Feb 1997 06:11:04 -0800 (PST) Received: (from bde@localhost) by godzilla.zeta.org.au (8.8.3/8.6.9) id BAA22997 for bugs@freebsd.org; Mon, 3 Feb 1997 01:10:23 +1100 Date: Mon, 3 Feb 1997 01:10:23 +1100 From: Bruce Evans Message-Id: <199702021410.BAA22997@godzilla.zeta.org.au> To: bugs@freebsd.org Subject: fixes for scanf bugs related to PR2606 Sender: owner-bugs@freebsd.org X-Loop: FreeBSD.org Precedence: bulk Please review these fixes for scanf. You'll probably need to refer to the ANSI standard to remind yourself of the fine points of EOF handling by scanf. These points are too fine, so scanf should never be used, but /usr/ports/felt uses them to help find the longest line in a file using the following code: while (fscanf (fp, " %*[^\n]%n%*[\n]", &length) != EOF) ... This failed because scanf returned 0 at the end of the file. I think it also failed for non-newline-terminated last lines because scanf returned EOF instead of 0 after doing the non-counted assignment to `length'. Bruce Log: Fixed handling of input failure by the scanf family. - 0 was returned instead of EOF when an input failure occured while skipping white-space after 0 assignments. This might fix PR2606. The diagnosis in PR2606 seems to be wrong. - EOF was returned instead of 0 when an input failure occured after 0 assignments and nonzero suppressed assignments. - EOF was spelled -1. diff -c2 vfscanf.c~ vfscanf.c *** vfscanf.c~ Sat Jan 18 14:32:00 1997 --- vfscanf.c Mon Feb 3 00:38:55 1997 *************** *** 116,119 **** --- 116,120 ---- register 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 strtol/strtoul */ *************** *** 127,130 **** --- 128,132 ---- nassigned = 0; + nconversions = 0; nread = 0; base = 0; /* XXX just to keep gcc happy */ *************** *** 137,141 **** for (;;) { if (fp->_r <= 0 && __srefill(fp)) ! return (nassigned); if (!isspace(*fp->_p)) break; --- 139,143 ---- for (;;) { if (fp->_r <= 0 && __srefill(fp)) ! goto input_failure; if (!isspace(*fp->_p)) break; *************** *** 262,265 **** --- 264,268 ---- case 'n': + nconversions++; if (flags & SUPPRESS) /* ??? */ continue; *************** *** 350,353 **** --- 353,357 ---- nassigned++; } + nconversions++; break; *************** *** 391,394 **** --- 395,399 ---- } nread += n; + nconversions++; break; *************** *** 421,424 **** --- 426,430 ---- nassigned++; } + nconversions++; continue; *************** *** 557,560 **** --- 563,567 ---- } nread += p - buf; + nconversions++; break; *************** *** 648,651 **** --- 655,659 ---- } nread += p - buf; + nconversions++; break; #endif /* FLOATING_POINT */ *************** *** 653,657 **** } input_failure: ! return (nassigned ? nassigned : -1); match_failure: return (nassigned); --- 661,665 ---- } input_failure: ! return (nconversions != 0 ? nassigned : EOF); match_failure: return (nassigned);