Re: [PATCH] Fix sscanf (more fixes)

From: Paul (set@pobox.com)
Date: Mon Sep 24 2001 - 13:05:19 EST


        This patch includes my previous modifications and also
corrects behaviour to match sscanf(3) as far as matching white
space and avoiding a false match in some cases.

Paul
set@pobox.com

--- 2.4.9-ac13-user/lib/vsprintf.c.old Fri Sep 21 19:42:25 2001
+++ 2.4.9-ac13-user/lib/vsprintf.c Mon Sep 24 13:52:05 2001
@@ -18,6 +18,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
+#include <linux/kernel.h>
 
 #include <asm/div64.h>
 
@@ -515,36 +516,44 @@
         int num = 0;
         int qualifier;
         int base;
- unsigned int field_width;
+ int field_width = -1;
         int is_sign = 0;
 
- for (; *fmt; fmt++) {
+ while(*fmt && *str) {
                 /* skip any white space in format */
+ /* white space in format matchs any amount of
+ * white space, including none, in the input.
+ */
                 if (isspace(*fmt)) {
- continue;
+ while (isspace(*fmt))
+ ++fmt;
+ while (isspace(*str))
+ ++str;
                 }
 
                 /* anything that is not a conversion must match exactly */
- if (*fmt != '%') {
+ if (*fmt != '%' && *fmt) {
                         if (*fmt++ != *str++)
- return num;
+ break;
                         continue;
                 }
+
+ if (!*fmt)
+ break;
                 ++fmt;
                 
                 /* skip this conversion.
                  * advance both strings to next white space
                  */
                 if (*fmt == '*') {
- while (!isspace(*fmt))
+ while (!isspace(*fmt) && *fmt)
                                 fmt++;
- while(!isspace(*str))
+ while (!isspace(*str) && *str)
                                 str++;
                         continue;
                 }
 
                 /* get field width */
- field_width = 0xffffffffUL;
                 if (isdigit(*fmt))
                         field_width = skip_atoi(&fmt);
 
@@ -557,25 +566,32 @@
                 base = 10;
                 is_sign = 0;
 
- switch(*fmt) {
+ if (!*fmt || !*str)
+ break;
+
+ switch(*fmt++) {
                 case 'c':
                 {
                         char *s = (char *) va_arg(args,char*);
+ if (field_width == -1)
+ field_width = 1;
                         do {
                                 *s++ = *str++;
- } while(field_width-- > 0);
+ } while(field_width-- > 0 && *str);
                         num++;
                 }
                 continue;
                 case 's':
                 {
                         char *s = (char *) va_arg(args, char *);
+ if(field_width == -1)
+ field_width = INT_MAX;
                         /* first, skip leading white space in buffer */
                         while (isspace(*str))
                                 str++;
 
                         /* now copy until next white space */
- while (!isspace(*str) && field_width--) {
+ while (*str && !isspace(*str) && field_width--) {
                                 *s++ = *str++;
                         }
                         *s = '\0';
@@ -617,6 +633,9 @@
                 while (isspace(*str))
                         str++;
 
+ if (!*str || !isdigit(*str))
+ break;
+
                 switch(qualifier) {
                 case 'h':
                         if (is_sign) {
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sun Sep 30 2001 - 21:00:24 EST