From 2f30b1f9e1b612cdd1a17daeecf514229e8d6a5f Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Mon, 21 Sep 2009 17:04:29 -0700 Subject: vsprintf: use WARN_ON_ONCE Signed-off-by: Marcin Slusarz Reviewed-by: Frederic Weisbecker Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/vsprintf.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'lib/vsprintf.c') diff --git a/lib/vsprintf.c b/lib/vsprintf.c index d320c1816a7..73a14b8c6d1 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1092,13 +1092,8 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) /* Reject out-of-range values early. Large positive sizes are used for unknown buffer sizes. */ - if (unlikely((int) size < 0)) { - /* There can be only one.. */ - static char warn = 1; - WARN_ON(warn); - warn = 0; + if (WARN_ON_ONCE((int) size < 0)) return 0; - } str = buf; end = buf + size; @@ -1544,13 +1539,8 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf) struct printf_spec spec = {0}; - if (unlikely((int) size < 0)) { - /* There can be only one.. */ - static char warn = 1; - WARN_ON(warn); - warn = 0; + if (WARN_ON_ONCE((int) size < 0)) return 0; - } str = buf; end = buf + size; -- cgit v1.2.3-70-g09d2 From eb78cd26b9b519d94e20ce9c0697e5056046669d Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 18 Sep 2009 13:04:06 +0000 Subject: lib/vsprintf.c: Avoid possible unaligned accesses in %pI6c Jens Rosenboom noticed that a possibly unaligned const char* is cast to a const struct in6_addr *. Avoid this at the cost of a struct in6_addr copy on the stack. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- lib/vsprintf.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'lib/vsprintf.c') diff --git a/lib/vsprintf.c b/lib/vsprintf.c index cb8a112030b..a1941f8d205 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -671,7 +671,7 @@ static char *ip4_string(char *p, const u8 *addr, bool leading_zeros) return p; } -static char *ip6_compressed_string(char *p, const struct in6_addr *addr) +static char *ip6_compressed_string(char *p, const char *addr) { int i; int j; @@ -683,7 +683,12 @@ static char *ip6_compressed_string(char *p, const struct in6_addr *addr) u8 hi; u8 lo; bool needcolon = false; - bool useIPv4 = ipv6_addr_v4mapped(addr) || ipv6_addr_is_isatap(addr); + bool useIPv4; + struct in6_addr in6; + + memcpy(&in6, addr, sizeof(struct in6_addr)); + + useIPv4 = ipv6_addr_v4mapped(&in6) || ipv6_addr_is_isatap(&in6); memset(zerolength, 0, sizeof(zerolength)); @@ -695,7 +700,7 @@ static char *ip6_compressed_string(char *p, const struct in6_addr *addr) /* find position of longest 0 run */ for (i = 0; i < range; i++) { for (j = i; j < range; j++) { - if (addr->s6_addr16[j] != 0) + if (in6.s6_addr16[j] != 0) break; zerolength[i]++; } @@ -722,7 +727,7 @@ static char *ip6_compressed_string(char *p, const struct in6_addr *addr) needcolon = false; } /* hex u16 without leading 0s */ - word = ntohs(addr->s6_addr16[i]); + word = ntohs(in6.s6_addr16[i]); hi = word >> 8; lo = word & 0xff; if (hi) { @@ -741,19 +746,19 @@ static char *ip6_compressed_string(char *p, const struct in6_addr *addr) if (useIPv4) { if (needcolon) *p++ = ':'; - p = ip4_string(p, &addr->s6_addr[12], false); + p = ip4_string(p, &in6.s6_addr[12], false); } *p = '\0'; return p; } -static char *ip6_string(char *p, const struct in6_addr *addr, const char *fmt) +static char *ip6_string(char *p, const char *addr, const char *fmt) { int i; for (i = 0; i < 8; i++) { - p = pack_hex_byte(p, addr->s6_addr[2 * i]); - p = pack_hex_byte(p, addr->s6_addr[2 * i + 1]); + p = pack_hex_byte(p, *addr++); + p = pack_hex_byte(p, *addr++); if (fmt[0] == 'I' && i != 7) *p++ = ':'; } @@ -768,9 +773,9 @@ static char *ip6_addr_string(char *buf, char *end, const u8 *addr, char ip6_addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")]; if (fmt[0] == 'I' && fmt[2] == 'c') - ip6_compressed_string(ip6_addr, (const struct in6_addr *)addr); + ip6_compressed_string(ip6_addr, addr); else - ip6_string(ip6_addr, (const struct in6_addr *)addr, fmt); + ip6_string(ip6_addr, addr, fmt); return string(buf, end, ip6_addr, spec); } -- cgit v1.2.3-70-g09d2 From 8fccae2c95506270f74ee8429c273b0924e89c83 Mon Sep 17 00:00:00 2001 From: Andy Spencer Date: Thu, 1 Oct 2009 15:44:27 -0700 Subject: sscanf(): fix %*s%n When using %*s, sscanf should honor conversion specifiers immediately following the %*s. For example, the following code should find the position of the end of the string "hello". int end; char buf[] = "hello world"; sscanf(buf, "%*s%n", &end); printf("%d\n", end); Ideally, sscanf would advance the fmt and str pointers the same as it would without the *, but the code for that is rather complicated and is not included in the patch. Signed-off-by: Andy Spencer Acked-by: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/vsprintf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/vsprintf.c') diff --git a/lib/vsprintf.c b/lib/vsprintf.c index b91839e9e89..33bed5e67a2 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1771,7 +1771,7 @@ int vsscanf(const char * buf, const char * fmt, va_list args) * advance both strings to next white space */ if (*fmt == '*') { - while (!isspace(*fmt) && *fmt) + while (!isspace(*fmt) && *fmt != '%' && *fmt) fmt++; while (!isspace(*str) && *str) str++; -- cgit v1.2.3-70-g09d2