[<prev] [next>] [day] [month] [year] [list]
Message-Id: <505877CE020000780009C02B@nat28.tlf.novell.com>
Date: Tue, 18 Sep 2012 12:31:58 +0100
From: "Jan Beulich" <JBeulich@...e.com>
To: <akpm@...ux-foundation.org>
Cc: "Konrad Rzeszutek Wilk" <konrad.wilk@...cle.com>,
<linux-kernel@...r.kernel.org>
Subject: [PATCH] improve standard conformance of sscanf()
Xen's pciback points out a couple of deficiencies with vsscanf()'s
standard conformance:
- Trailing character matching cannot be checked by the caller: With a
format string of "(%x:%x.%x) %n" absence of the closing parenthesis
cannot be checked, as input of "(00:00.0)" doesn't cause the %n to be
evaluated (because of the code not skipping white space before the
trailing %n).
- The parameter corresponding to a trailing %n could get filled even if
there was a matching error: With a format string of "(%x:%x.%x)%n",
input of "(00:00.0]" would still fill the respective variable pointed
to (and hence again make the mismatch non-detectable by the caller).
This patch aims at fixing those, but leaves other non-conforming
aspects of it untouched, among them these possibly relevant ones:
- improper handling of the assignment suppression character '*'
(blindly discarding all succeeding non-white space from the format
and input strings),
- not honoring conversion specifiers for %n,
- not recognizing the C99 conversion specifier 't' (recognized by
vsprintf()).
Signed-off-by: Jan Beulich <jbeulich@...e.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@...cle.com>
---
lib/vsprintf.c | 33 ++++++++++++++-------------------
1 file changed, 14 insertions(+), 19 deletions(-)
--- 3.6-rc6/lib/vsprintf.c
+++ 3.6-rc6-sscanf-conformance/lib/vsprintf.c
@@ -2017,7 +2017,7 @@ int vsscanf(const char *buf, const char
s16 field_width;
bool is_sign;
- while (*fmt && *str) {
+ while (*fmt) {
/* skip any white space in format */
/* white space in format matchs any amount of
* white space, including none, in the input.
@@ -2042,6 +2042,8 @@ int vsscanf(const char *buf, const char
* advance both strings to next white space
*/
if (*fmt == '*') {
+ if (!*str)
+ break;
while (!isspace(*fmt) && *fmt != '%' && *fmt)
fmt++;
while (!isspace(*str) && *str)
@@ -2070,7 +2072,17 @@ int vsscanf(const char *buf, const char
}
}
- if (!*fmt || !*str)
+ if (!*fmt)
+ break;
+
+ if (*fmt == 'n') {
+ /* return number of characters read so far */
+ *va_arg(args, int *) = str - buf;
+ ++fmt;
+ continue;
+ }
+
+ if (!*str)
break;
base = 10;
@@ -2103,13 +2115,6 @@ int vsscanf(const char *buf, const char
num++;
}
continue;
- case 'n':
- /* return number of characters read so far */
- {
- int *i = (int *)va_arg(args, int*);
- *i = str - buf;
- }
- continue;
case 'o':
base = 8;
break;
@@ -2210,16 +2215,6 @@ int vsscanf(const char *buf, const char
str = next;
}
- /*
- * Now we've come all the way through so either the input string or the
- * format ended. In the former case, there can be a %n at the current
- * position in the format that needs to be filled.
- */
- if (*fmt == '%' && *(fmt + 1) == 'n') {
- int *p = (int *)va_arg(args, int *);
- *p = str - buf;
- }
-
return num;
}
EXPORT_SYMBOL(vsscanf);
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists