Date: Fri, 18 Sep 1998 09:32:12 +0100 From: Niall Smart <nialls@euristix.ie> To: freebsd-gnats-submit@FreeBSD.ORG Subject: bin/7970: Bug in *scanf: %n is sometimes ignored. Message-ID: <98Sep18.095224bst.19713@gateway.euristix.ie>
next in thread | raw e-mail | index | archive | help
>Number: 7970 >Category: bin >Synopsis: Bug in *scanf: %n is sometimes ignored. >Confidential: no >Severity: critical >Priority: high >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Fri Sep 18 02:00:01 PDT 1998 >Last-Modified: >Originator: Niall Smart >Organization: None >Release: FreeBSD 3.0-CURRENT i386 >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 != '%') >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?98Sep18.095224bst.19713>