tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

rfc: *scanf() parse certain string incorrectly


For first, a small test case:

#include <stdio.h>

int main()
        /* set of "white space" symbols from isspace(3) */
        char *str = "\f\n\r\t\v%z";
        char c = 0;
        sscanf(str, "%%%c", &c);
        printf("char %c\n", c);
        printf("code %d\n", (unsigned int) c);
        return 0;

And of course results (linux/netbsd):

andy@FITFIESPPC176:~/tmp/base-ts$ ./scanf
char z
code 122

-bash-3.2$ ./scanf
code 0

Here is a cite from SUSv3 (a little bit unclear, as I think, but anyway):
"A directive that is a conversion specification defines a set of
matching input sequences, as described below for each conversion
character. A conversion specification shall be executed in the
following steps.
Input white-space characters (as specified by isspace()) shall be
skipped, unless the conversion specification includes a [, c, C, or n
conversion specifier."

And a small hack (This hack NOT covers all cases!):

diff --git a/lib/libc/stdio/vfscanf.c b/lib/libc/stdio/vfscanf.c
index cdd17dc..4c1aeba 100644
--- a/lib/libc/stdio/vfscanf.c
+++ b/lib/libc/stdio/vfscanf.c
@@ -140,6 +140,12 @@ __svfscanf(FILE *fp, char const *fmt0, va_list ap)
        return (ret);

+#define SCANF_SKIP_SPACE() \
+do { \
+    while ((fp->_r > 0 || __srefill(fp) == 0) && isspace(*fp->_p)) \
+       nread++, fp->_r--, fp->_p++; \
+} while (/*CONSTCOND*/ 0)
  * __svfscanf_unlocked - non-MT-safe version of __svfscanf
@@ -198,6 +202,7 @@ __svfscanf_unlocked(FILE *fp, const char *fmt0, va_list ap)
 again:         c = *fmt++;
                switch (c) {
                case '%':
+                       SCANF_SKIP_SPACE();
                        if (fp->_r <= 0 && __srefill(fp))
                                goto input_failure;

Results after applying the hack.

-bash-3.2$ LD_LIBRARY_PATH=~/current/obj/lib/libc ./scanf
char z
code 122

With Best Regards,
Andy Shevchenko

Home | Main Index | Thread Index | Old Index