Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 3 Feb 1997 01:10:23 +1100
From:      Bruce Evans <bde@zeta.org.au>
To:        bugs@freebsd.org
Subject:   fixes for scanf bugs related to PR2606
Message-ID:  <199702021410.BAA22997@godzilla.zeta.org.au>

next in thread | raw e-mail | index | archive | help
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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199702021410.BAA22997>