diff options
Diffstat (limited to 'lib/vsprintf.c')
-rw-r--r-- | lib/vsprintf.c | 109 |
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 | */ |
42 | unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base) | 44 | unsigned 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 | */ |
65 | unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base) | 69 | unsigned 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 | */ |
77 | long simple_strtol(const char *cp, char **endp, unsigned int base) | 83 | long 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 | */ |
92 | long long simple_strtoll(const char *cp, char **endp, unsigned int base) | 100 | long 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++; |