aboutsummaryrefslogtreecommitdiffstats
path: root/lib/vsprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/vsprintf.c')
-rw-r--r--lib/vsprintf.c109
1 files changed, 65 insertions, 44 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 39c99fea7c03..fab33a9c5318 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -23,12 +23,12 @@
23#include <linux/ctype.h> 23#include <linux/ctype.h>
24#include <linux/kernel.h> 24#include <linux/kernel.h>
25#include <linux/kallsyms.h> 25#include <linux/kallsyms.h>
26#include <linux/math64.h>
26#include <linux/uaccess.h> 27#include <linux/uaccess.h>
27#include <linux/ioport.h> 28#include <linux/ioport.h>
28#include <net/addrconf.h> 29#include <net/addrconf.h>
29 30
30#include <asm/page.h> /* for PAGE_SIZE */ 31#include <asm/page.h> /* for PAGE_SIZE */
31#include <asm/div64.h>
32#include <asm/sections.h> /* for dereference_function_descriptor() */ 32#include <asm/sections.h> /* for dereference_function_descriptor() */
33 33
34#include "kstrtox.h" 34#include "kstrtox.h"
@@ -38,6 +38,8 @@
38 * @cp: The start of the string 38 * @cp: The start of the string
39 * @endp: A pointer to the end of the parsed string will be placed here 39 * @endp: A pointer to the end of the parsed string will be placed here
40 * @base: The number base to use 40 * @base: The number base to use
41 *
42 * This function is obsolete. Please use kstrtoull instead.
41 */ 43 */
42unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base) 44unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base)
43{ 45{
@@ -61,6 +63,8 @@ EXPORT_SYMBOL(simple_strtoull);
61 * @cp: The start of the string 63 * @cp: The start of the string
62 * @endp: A pointer to the end of the parsed string will be placed here 64 * @endp: A pointer to the end of the parsed string will be placed here
63 * @base: The number base to use 65 * @base: The number base to use
66 *
67 * This function is obsolete. Please use kstrtoul instead.
64 */ 68 */
65unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base) 69unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base)
66{ 70{
@@ -73,6 +77,8 @@ EXPORT_SYMBOL(simple_strtoul);
73 * @cp: The start of the string 77 * @cp: The start of the string
74 * @endp: A pointer to the end of the parsed string will be placed here 78 * @endp: A pointer to the end of the parsed string will be placed here
75 * @base: The number base to use 79 * @base: The number base to use
80 *
81 * This function is obsolete. Please use kstrtol instead.
76 */ 82 */
77long simple_strtol(const char *cp, char **endp, unsigned int base) 83long simple_strtol(const char *cp, char **endp, unsigned int base)
78{ 84{
@@ -88,6 +94,8 @@ EXPORT_SYMBOL(simple_strtol);
88 * @cp: The start of the string 94 * @cp: The start of the string
89 * @endp: A pointer to the end of the parsed string will be placed here 95 * @endp: A pointer to the end of the parsed string will be placed here
90 * @base: The number base to use 96 * @base: The number base to use
97 *
98 * This function is obsolete. Please use kstrtoll instead.
91 */ 99 */
92long long simple_strtoll(const char *cp, char **endp, unsigned int base) 100long long simple_strtoll(const char *cp, char **endp, unsigned int base)
93{ 101{
@@ -1485,7 +1493,10 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
1485 num = va_arg(args, long); 1493 num = va_arg(args, long);
1486 break; 1494 break;
1487 case FORMAT_TYPE_SIZE_T: 1495 case FORMAT_TYPE_SIZE_T:
1488 num = va_arg(args, size_t); 1496 if (spec.flags & SIGN)
1497 num = va_arg(args, ssize_t);
1498 else
1499 num = va_arg(args, size_t);
1489 break; 1500 break;
1490 case FORMAT_TYPE_PTRDIFF: 1501 case FORMAT_TYPE_PTRDIFF:
1491 num = va_arg(args, ptrdiff_t); 1502 num = va_arg(args, ptrdiff_t);
@@ -2013,7 +2024,11 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
2013 char digit; 2024 char digit;
2014 int num = 0; 2025 int num = 0;
2015 u8 qualifier; 2026 u8 qualifier;
2016 u8 base; 2027 unsigned int base;
2028 union {
2029 long long s;
2030 unsigned long long u;
2031 } val;
2017 s16 field_width; 2032 s16 field_width;
2018 bool is_sign; 2033 bool is_sign;
2019 2034
@@ -2053,8 +2068,11 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
2053 2068
2054 /* get field width */ 2069 /* get field width */
2055 field_width = -1; 2070 field_width = -1;
2056 if (isdigit(*fmt)) 2071 if (isdigit(*fmt)) {
2057 field_width = skip_atoi(&fmt); 2072 field_width = skip_atoi(&fmt);
2073 if (field_width <= 0)
2074 break;
2075 }
2058 2076
2059 /* get conversion qualifier */ 2077 /* get conversion qualifier */
2060 qualifier = -1; 2078 qualifier = -1;
@@ -2154,58 +2172,61 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
2154 || (base == 0 && !isdigit(digit))) 2172 || (base == 0 && !isdigit(digit)))
2155 break; 2173 break;
2156 2174
2175 if (is_sign)
2176 val.s = qualifier != 'L' ?
2177 simple_strtol(str, &next, base) :
2178 simple_strtoll(str, &next, base);
2179 else
2180 val.u = qualifier != 'L' ?
2181 simple_strtoul(str, &next, base) :
2182 simple_strtoull(str, &next, base);
2183
2184 if (field_width > 0 && next - str > field_width) {
2185 if (base == 0)
2186 _parse_integer_fixup_radix(str, &base);
2187 while (next - str > field_width) {
2188 if (is_sign)
2189 val.s = div_s64(val.s, base);
2190 else
2191 val.u = div_u64(val.u, base);
2192 --next;
2193 }
2194 }
2195
2157 switch (qualifier) { 2196 switch (qualifier) {
2158 case 'H': /* that's 'hh' in format */ 2197 case 'H': /* that's 'hh' in format */
2159 if (is_sign) { 2198 if (is_sign)
2160 signed char *s = (signed char *)va_arg(args, signed char *); 2199 *va_arg(args, signed char *) = val.s;
2161 *s = (signed char)simple_strtol(str, &next, base); 2200 else
2162 } else { 2201 *va_arg(args, unsigned char *) = val.u;
2163 unsigned char *s = (unsigned char *)va_arg(args, unsigned char *);
2164 *s = (unsigned char)simple_strtoul(str, &next, base);
2165 }
2166 break; 2202 break;
2167 case 'h': 2203 case 'h':
2168 if (is_sign) { 2204 if (is_sign)
2169 short *s = (short *)va_arg(args, short *); 2205 *va_arg(args, short *) = val.s;
2170 *s = (short)simple_strtol(str, &next, base); 2206 else
2171 } else { 2207 *va_arg(args, unsigned short *) = val.u;
2172 unsigned short *s = (unsigned short *)va_arg(args, unsigned short *);
2173 *s = (unsigned short)simple_strtoul(str, &next, base);
2174 }
2175 break; 2208 break;
2176 case 'l': 2209 case 'l':
2177 if (is_sign) { 2210 if (is_sign)
2178 long *l = (long *)va_arg(args, long *); 2211 *va_arg(args, long *) = val.s;
2179 *l = simple_strtol(str, &next, base); 2212 else
2180 } else { 2213 *va_arg(args, unsigned long *) = val.u;
2181 unsigned long *l = (unsigned long *)va_arg(args, unsigned long *);
2182 *l = simple_strtoul(str, &next, base);
2183 }
2184 break; 2214 break;
2185 case 'L': 2215 case 'L':
2186 if (is_sign) { 2216 if (is_sign)
2187 long long *l = (long long *)va_arg(args, long long *); 2217 *va_arg(args, long long *) = val.s;
2188 *l = simple_strtoll(str, &next, base); 2218 else
2189 } else { 2219 *va_arg(args, unsigned long long *) = val.u;
2190 unsigned long long *l = (unsigned long long *)va_arg(args, unsigned long long *);
2191 *l = simple_strtoull(str, &next, base);
2192 }
2193 break; 2220 break;
2194 case 'Z': 2221 case 'Z':
2195 case 'z': 2222 case 'z':
2196 { 2223 *va_arg(args, size_t *) = val.u;
2197 size_t *s = (size_t *)va_arg(args, size_t *); 2224 break;
2198 *s = (size_t)simple_strtoul(str, &next, base);
2199 }
2200 break;
2201 default: 2225 default:
2202 if (is_sign) { 2226 if (is_sign)
2203 int *i = (int *)va_arg(args, int *); 2227 *va_arg(args, int *) = val.s;
2204 *i = (int)simple_strtol(str, &next, base); 2228 else
2205 } else { 2229 *va_arg(args, unsigned int *) = val.u;
2206 unsigned int *i = (unsigned int *)va_arg(args, unsigned int*);
2207 *i = (unsigned int)simple_strtoul(str, &next, base);
2208 }
2209 break; 2230 break;
2210 } 2231 }
2211 num++; 2232 num++;