From nialls@euristix.ie  Fri Sep 18 01:54:24 1998
Received: from relay.esat.net (relay.esat.net [192.111.39.11])
          by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id BAA01688
          for <freebsd-gnats-submit@freebsd.org>; Fri, 18 Sep 1998 01:54:22 -0700 (PDT)
          (envelope-from nialls@euristix.ie)
Received: from (euristix.ie) [193.120.210.2] 
	by relay.esat.net with esmtp 
	 id 0zJwIf-0003UZ-00; Fri, 18 Sep 1998 09:53:57 +0100
Received: by gateway.euristix.ie id <19713>; Fri, 18 Sep 1998 09:52:24 +0100
Message-Id: <98Sep18.095224bst.19713@gateway.euristix.ie>
Date: Fri, 18 Sep 1998 09:32:12 +0100
From: Niall Smart <nialls@euristix.ie>
Sender: nsmart@euristix.ie
To: freebsd-gnats-submit@freebsd.org
Subject: Bug in *scanf: %n is sometimes ignored.

>Number:         7970
>Category:       bin
>Synopsis:       Bug in *scanf: %n is sometimes ignored.
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Sep 18 02:00:01 PDT 1998
>Closed-Date:    Fri Sep 25 05:21:10 PDT 1998
>Last-Modified:  Fri Sep 25 05:21:45 PDT 1998
>Originator:     Niall Smart
>Release:        FreeBSD 3.0-CURRENT i386
>Organization:
None
>Environment:

>Description:

There is a bug in the implementation of __svfscanf which sometimes
causes the %n `conversion' to be ignored.  (%n is used to assign the
number of characters read from the input stream to its corresponding
argument)

The following code demonstrates the bug:

#include <stdio.h>

int
main()
{
        int     i;
        int     n = 12345678;

        sscanf("24\n", "%li %n", &i, &n);       
        
        printf("%d %d\n", i, n);
        
        return 0;
}

The output should be "4 2", but it is "4 12345678"; n is not
modified.  The bug arises when a whitespace is present in the
format string and __svfscanf hits EOF while skipping 
corresponding whitespace in the input stream, in this case
it jumps to input_failure and exits before seeing the %n 
subsequent in the format string.  Jumping to input_failure
would _usually_ be the correct move since most conversions
would require input (which is not available) so quitting then
would be an optimisation.  The solution is simply to have it
continue in its iteration over the format string, this is the
approach taken by OpenBSD and I have used their patch.

Credit for patch: Chris Torek <torek@bsdi.com>
                  Tod Miller  <millert@openbsd.org>

>How-To-Repeat:

See attached code.

>Fix:
        
*** src/lib/libc/stdio/vfscanf.c~       Tue Sep 15 17:52:48 1998
--- src/lib/libc/stdio/vfscanf.c        Tue Sep 15 17:57:04 1998
***************
*** 137,149 ****
                if (c == 0)
                        return (nassigned);
                if (isspace(c)) {
!                       for (;;) {
!                               if (fp->_r <= 0 && __srefill(fp))
!                                       goto input_failure;
!                               if (!isspace(*fp->_p))
!                                       break;
                                nread++, fp->_r--, fp->_p++;
-                       }
                        continue;
                }
                if (c != '%')
--- 137,144 ----
                if (c == 0)
                        return (nassigned);
                if (isspace(c)) {
!                       while ((fp->_r > 0 || __srefill(fp) == 0) && isspace(*fp->_p))
                                nread++, fp->_r--, fp->_p++;
                        continue;
                }
                if (c != '%')
>Release-Note:
>Audit-Trail:

From: Jin Guojun (ITG staff) <jin@george.lbl.gov>
To: freebsd-gnats-submit@FreeBSD.ORG, nialls@euristix.ie
Cc:  Subject: Re: bin/7970: Bug in *scanf: %n is sometimes ignored.
Date: Fri, 18 Sep 1998 07:07:22 -0700 (PDT)

 > The following code demonstrates the bug:
 > 
 > #include <stdio.h>
 > 
 > int
 > main()
 > {
 >         int     i;
 >         int     n = 12345678;
 > 
 >         sscanf("24\n", "%li %n", &i, &n);       
 >         
 >         printf("%d %d\n", i, n);
 >         
 >         return 0;
 > }
 > 
 > The output should be "4 2", but it is "4 12345678"; n is not
 > ...
 
 The output should be "24 3", you have 3 bytes in the stream and the first
 "%li" is 24. If you got "4 2", then it is completely wrong somewhere.
 
 	-Jin
 

From: Niall Smart <nialls@euristix.ie>
To: "Jin Guojun (ITG staff)" <jin@george.lbl.gov>
Cc: freebsd-gnats-submit@freebsd.org
Subject: Re: bin/7970: Bug in *scanf: %n is sometimes ignored.
Date: Fri, 18 Sep 1998 14:23:37 +0100

 > > The following code demonstrates the bug:
 > >
 > >         sscanf("24\n", "%li %n", &i, &n);
 > >
 > >         printf("%d %d\n", i, n);
 > >
 > >         return 0;
 > > }
 > >
 > > The output should be "4 2", but it is "4 12345678"; n is not
 > > ...
 
 > The output should be "24 3", you have 3 bytes in the stream and the first
 > "%li" is 24. If you got "4 2", then it is completely wrong somewhere.
 
 Whoops, a miscreant "2" slipped in there somehow, the format string should
 be "4\n".
 
 Niall
State-Changed-From-To: open->closed 
State-Changed-By: obrien 
State-Changed-When: Fri Sep 25 05:21:10 PDT 1998 
State-Changed-Why:  
applied patch 
>Unformatted:
