From pm@zin.lublin.pl  Wed Dec 29 22:58:11 2004
Return-Path: <pm@zin.lublin.pl>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id CCCFC16A4CE
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 29 Dec 2004 22:58:11 +0000 (GMT)
Received: from shellma.zin.lublin.pl (shellma.zin.lublin.pl [212.182.126.68])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 50DF443D45
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 29 Dec 2004 22:58:11 +0000 (GMT)
	(envelope-from pm@zin.lublin.pl)
Received: by shellma.zin.lublin.pl (Postfix, from userid 1018)
	id 5AB3A347116; Wed, 29 Dec 2004 23:59:32 +0100 (CET)
Message-Id: <20041229225932.5AB3A347116@shellma.zin.lublin.pl>
Date: Wed, 29 Dec 2004 23:59:32 +0100 (CET)
From: Pawel Malachowski <pawmal-posting@freebsd.lublin.pl>
Reply-To: Pawe Maachowski <pawmal-posting@freebsd.lublin.pl>
To: FreeBSD-gnats-submit@freebsd.org
Cc: venglin@freebsd.lublin.pl
Subject: sscanf %lld broken on 4.x
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         75638
>Category:       bin
>Synopsis:       sscanf %lld broken on 4.x
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Dec 29 23:00:46 GMT 2004
>Closed-Date:    Sat Jan 22 00:28:13 GMT 2005
>Last-Modified:  Sat Jan 22 00:28:13 GMT 2005
>Originator:     Pawe Maachowski
>Release:        FreeBSD 4.11-STABLE i386
>Organization:
ZiN
>Environment:
System: FreeBSD 4.11-STABLE #20: Sat Dec 18 19:32:41 CET 2004

	
>Description:
sscanf(s, "%lld", &l) will not set l to valid value if l was previously
not zero.

For example, ports/net-mgmt/iftop `max-bandwidth' option is broken on 4.x because of this.

>How-To-Repeat:

#include <stdio.h>
void main(void) {
  char *s = "10";
  long long l;
  int rc = 0;
  rc = sscanf(s, "%lld", &l);
  fprintf(stderr, "rc %d, s %s, l %lld\n", rc, s, l);
}

output on 4.x:
rc 1, s 10, l -4629710020483743734

output on 5.3:
rc 1, s 10, l 10

>Fix:

Workaround: set lld value to zero before using it with sscanf (noticed by venglin).

#include <stdio.h>
void main(void) {
  char *s = "10";
  long long l = 0;
  int rc = 0;
  rc = sscanf(s, "%lld", &l);
  fprintf(stderr, "rc %d, s %s, l %lld\n", rc, s, l);
}

output on 4.x:
rc 1, s 10, l 10
 
>Release-Note:
>Audit-Trail:

From: Przemyslaw Frasunek <venglin@freebsd.lublin.pl>
To: freebsd-gnats-submit@FreeBSD.org
Cc:  
Subject: Re: bin/75638: sscanf %lld broken on 4.x
Date: Thu, 30 Dec 2004 00:16:34 +0100

  > sscanf(s, "%lld", &l) will not set l to valid value if l was previously
  > not zero.
 
 well, not exactly non-zero. the problem occurs when l if initialized with value 
 greater than 0xffffffff:
 
 lagoon:venglin:~> cat test.c
 #include <stdio.h>
 
 int main(void) {
          //long long value = 0x100000000L;
          long long value = 0xffffffff;
          char *s = "10";
 
          fprintf(stderr, "%lld %s\n", value, s);
          sscanf(s, "%lld", &value);
          fprintf(stderr, "%lld %s\n", value, s);
 }
 lagoon:venglin:~> cc -o test test.c
 lagoon:venglin:~> ./test
 4294967295 10
 10 10
 
 
 lagoon:venglin:~> cat test.c
 #include <stdio.h>
 
 int main(void) {
          long long value = 0x100000000L;
          //long long value = 0xffffffff;
          char *s = "10";
 
          fprintf(stderr, "%lld %s\n", value, s);
          sscanf(s, "%lld", &value);
          fprintf(stderr, "%lld %s\n", value, s);
 }
 lagoon:venglin:~> cc -o test test.c
 lagoon:venglin:~> ./test
 4294967296 10
 4294967306 10
 
 it looks like classical unsigned integer overflow, which could have some yet 
 unknown security implications.
 
 -- 
 * Fido: 2:480/124 ** WWW: http://www.frasunek.com/ ** NICHDL: PMF9-RIPE *
 * JID: venglin@jabber.atman.pl ** PGP ID: 2578FCAD ** HAM-RADIO: SQ8JIV *

From: Bruce Evans <bde@zeta.org.au>
To: Przemyslaw Frasunek <venglin@freebsd.lublin.pl>
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: Re: bin/75638: sscanf %lld broken on 4.x
Date: Fri, 31 Dec 2004 00:32:40 +1100 (EST)

 On Wed, 29 Dec 2004, Przemyslaw Frasunek wrote:
 
 >   > sscanf(s, "%lld", &l) will not set l to valid value if l was previously
 >   > not zero.
 >
 >  well, not exactly non-zero. the problem occurs when l if initialized with value
 >  greater than 0xffffffff:
 
 The bug is actually that %lld is not supported in RELENG_4 (or C90).  Ports
 and other code that use it are broken (unportable).  %q must be used in
 RELENG_4.  From `man scanf':
 
 %      q       Indicates either that the conversion will be one of dioux or n
 %              and the next pointer is a pointer to a long long int (rather than
 %              int),
 
 This is the only support claimed for long long in scanf in RELENG_4.
 Note that "q" format is unsuitable for printing quad_t's, unlike what
 its name suggests, since quad_t may be different from long long, and
 is different on all supported 64-bit arches.  Thus the requirements
 for printing quads and long longs in RELENG_4 are weird: quads can be
 printed with %q formats but must be passed as long longs, while long
 longs can't be printed with %lld format but can be passed as long longs.
 
 Unfortunately, gcc's format checker also doesn't understand the difference
 between "q" and "ll" conversions, and doesn't know that old versions of
 scanf (and older versions of printf) don't support "ll", so gcc -Wformat
 cannot help avoid using undefined %ll conversion specifiers.  It can
 sometimes detect the relatively benign type mismatch between quads and
 %q.
 
 Bruce
State-Changed-From-To: open->closed 
State-Changed-By: das 
State-Changed-When: Sat Jan 22 00:27:15 GMT 2005 
State-Changed-Why:  
As has been explained, 4.X doesn't support scanf's %lld specifier. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=75638 
>Unformatted:
