tech-userlevel archive

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

rfc: *scanf() parse certain string incorrectly



Hello.
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
char
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();
 literal:
 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

AltStyle によって変換されたページ (->オリジナル) /