[uClibc]bug#1137: scanf() has problems with max-widths and leading zeros

Peter Kjellerstedt peter.kjellerstedt at axis.com
Thu Mar 22 17:55:53 UTC 2001


Package: uClibc
Version: CVS
Severity: normal

The latest scanf() in CVS (uClibc/stdio/scanf.c 1.11) does not handle
max-widths very well in case the scanned string starts with a zero.
The problem is that sc->width is always decreased in scan_getc(), but
it is not increased in scan_ungetc(). This can, however, only be done
if scan_ungetc() is called after a call to scan_getc(), but not after
a call to scan_getc_nw(). Therefore a flag is needed to keep track of
whether sc->width should be increased or not.

The following program shows the problem:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
  char val[] = "0901203403";
  int i;
  int h;

  printf("Original: %s\n", val);
  printf("Result:   ");
  for (i = 0; i < sizeof(val)/2; i++)
  {  
    sscanf(val + i*2, "%02x", &h);
    printf("%02X", h);
  }
  printf("\n");

  exit(0);
}

When run with the latest scanf() in CVS it gives:

Original: 0901203403
Result:   0000203400

Where both strings of course were supposed to be equal.

The patch below solves the problem.

//Peter

-----------------------------------------------------------------------
--- scanf.org.c	Thu Mar 22 18:25:34 2001
+++ scanf.c	Thu Mar 22 18:26:35 2001
@@ -139,6 +139,7 @@
 	FILE *fp;
 	int nread;
 	int width;
+	int width_flag;
 	int ungot_char;
 	int ungot_flag;
 };
@@ -166,6 +167,7 @@
 {
 	sc->fp = fp;
 	sc->nread = 0;
+	sc->width_flag = 0;
 	sc->ungot_flag = 0;
 	if ((sc->ungot_char = getc(fp)) > 0) { /* not EOF or EOS */
 		sc->ungot_flag = 1;
@@ -182,6 +184,7 @@
 	if (sc->ungot_char > 0) {
 		++sc->nread;
 	}
+	sc->width_flag = 0;
 	return sc->ungot_char;
 }
 
@@ -190,6 +193,7 @@
 	if (sc->ungot_flag == 0) {
 		sc->ungot_char = getc(sc->fp);
 	}
+	sc->width_flag = 1;
 	if (--sc->width < 0) {
 		sc->ungot_flag = 1;
 		return 0;
@@ -206,6 +210,9 @@
 	if (sc->ungot_flag != 0) {
 		assert(sc->width < 0);
 		return;
+	}
+	if (sc->width_flag) {
+		++sc->width;
 	}
 	sc->ungot_flag = 1;
 	if (sc->ungot_char > 0) {	/* not EOF or EOS */
-----------------------------------------------------------------------


------------------------------------------------------------
Peter Kjellerstedt       E-Mail: Peter.Kjellerstedt at axis.com
Axis Communications AB   Phone:  +46 46 272 18 69
Scheelevagen 34          Fax:    +46 46 13 61 30
SE-223 63 LUND           URL:    http://www.axis.com/








More information about the uClibc mailing list