diff options
Diffstat (limited to 'lib/vsprintf.c')
| -rw-r--r-- | lib/vsprintf.c | 80 |
1 files changed, 34 insertions, 46 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 95cd63b43b99..f9cee8e1233c 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
| @@ -1449,6 +1449,8 @@ int kptr_restrict __read_mostly; | |||
| 1449 | * (legacy clock framework) of the clock | 1449 | * (legacy clock framework) of the clock |
| 1450 | * - 'Cr' For a clock, it prints the current rate of the clock | 1450 | * - 'Cr' For a clock, it prints the current rate of the clock |
| 1451 | * | 1451 | * |
| 1452 | * ** Please update also Documentation/printk-formats.txt when making changes ** | ||
| 1453 | * | ||
| 1452 | * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 | 1454 | * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 |
| 1453 | * function pointers are really function descriptors, which contain a | 1455 | * function pointers are really function descriptors, which contain a |
| 1454 | * pointer to the real address. | 1456 | * pointer to the real address. |
| @@ -1457,7 +1459,7 @@ static noinline_for_stack | |||
| 1457 | char *pointer(const char *fmt, char *buf, char *end, void *ptr, | 1459 | char *pointer(const char *fmt, char *buf, char *end, void *ptr, |
| 1458 | struct printf_spec spec) | 1460 | struct printf_spec spec) |
| 1459 | { | 1461 | { |
| 1460 | int default_width = 2 * sizeof(void *) + (spec.flags & SPECIAL ? 2 : 0); | 1462 | const int default_width = 2 * sizeof(void *); |
| 1461 | 1463 | ||
| 1462 | if (!ptr && *fmt != 'K') { | 1464 | if (!ptr && *fmt != 'K') { |
| 1463 | /* | 1465 | /* |
| @@ -1769,14 +1771,14 @@ qualifier: | |||
| 1769 | 1771 | ||
| 1770 | case 'n': | 1772 | case 'n': |
| 1771 | /* | 1773 | /* |
| 1772 | * Since %n poses a greater security risk than utility, treat | 1774 | * Since %n poses a greater security risk than |
| 1773 | * it as an invalid format specifier. Warn about its use so | 1775 | * utility, treat it as any other invalid or |
| 1774 | * that new instances don't get added. | 1776 | * unsupported format specifier. |
| 1775 | */ | 1777 | */ |
| 1776 | WARN_ONCE(1, "Please remove ignored %%n in '%s'\n", fmt); | ||
| 1777 | /* Fall-through */ | 1778 | /* Fall-through */ |
| 1778 | 1779 | ||
| 1779 | default: | 1780 | default: |
| 1781 | WARN_ONCE(1, "Please remove unsupported %%%c in format string\n", *fmt); | ||
| 1780 | spec->type = FORMAT_TYPE_INVALID; | 1782 | spec->type = FORMAT_TYPE_INVALID; |
| 1781 | return fmt - start; | 1783 | return fmt - start; |
| 1782 | } | 1784 | } |
| @@ -1811,41 +1813,16 @@ qualifier: | |||
| 1811 | * @fmt: The format string to use | 1813 | * @fmt: The format string to use |
| 1812 | * @args: Arguments for the format string | 1814 | * @args: Arguments for the format string |
| 1813 | * | 1815 | * |
| 1814 | * This function follows C99 vsnprintf, but has some extensions: | 1816 | * This function generally follows C99 vsnprintf, but has some |
| 1815 | * %pS output the name of a text symbol with offset | 1817 | * extensions and a few limitations: |
| 1816 | * %ps output the name of a text symbol without offset | 1818 | * |
| 1817 | * %pF output the name of a function pointer with its offset | 1819 | * %n is unsupported |
| 1818 | * %pf output the name of a function pointer without its offset | 1820 | * %p* is handled by pointer() |
| 1819 | * %pB output the name of a backtrace symbol with its offset | ||
| 1820 | * %pR output the address range in a struct resource with decoded flags | ||
| 1821 | * %pr output the address range in a struct resource with raw flags | ||
| 1822 | * %pb output the bitmap with field width as the number of bits | ||
| 1823 | * %pbl output the bitmap as range list with field width as the number of bits | ||
| 1824 | * %pM output a 6-byte MAC address with colons | ||
| 1825 | * %pMR output a 6-byte MAC address with colons in reversed order | ||
| 1826 | * %pMF output a 6-byte MAC address with dashes | ||
| 1827 | * %pm output a 6-byte MAC address without colons | ||
| 1828 | * %pmR output a 6-byte MAC address without colons in reversed order | ||
| 1829 | * %pI4 print an IPv4 address without leading zeros | ||
| 1830 | * %pi4 print an IPv4 address with leading zeros | ||
| 1831 | * %pI6 print an IPv6 address with colons | ||
| 1832 | * %pi6 print an IPv6 address without colons | ||
| 1833 | * %pI6c print an IPv6 address as specified by RFC 5952 | ||
| 1834 | * %pIS depending on sa_family of 'struct sockaddr *' print IPv4/IPv6 address | ||
| 1835 | * %piS depending on sa_family of 'struct sockaddr *' print IPv4/IPv6 address | ||
| 1836 | * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper | ||
| 1837 | * case. | ||
| 1838 | * %*pE[achnops] print an escaped buffer | ||
| 1839 | * %*ph[CDN] a variable-length hex string with a separator (supports up to 64 | ||
| 1840 | * bytes of the input) | ||
| 1841 | * %pC output the name (Common Clock Framework) or address (legacy clock | ||
| 1842 | * framework) of a clock | ||
| 1843 | * %pCn output the name (Common Clock Framework) or address (legacy clock | ||
| 1844 | * framework) of a clock | ||
| 1845 | * %pCr output the current rate of a clock | ||
| 1846 | * %n is ignored | ||
| 1847 | * | 1821 | * |
| 1848 | * ** Please update Documentation/printk-formats.txt when making changes ** | 1822 | * See pointer() or Documentation/printk-formats.txt for more |
| 1823 | * extensive description. | ||
| 1824 | * | ||
| 1825 | * ** Please update the documentation in both places when making changes ** | ||
| 1849 | * | 1826 | * |
| 1850 | * The return value is the number of characters which would | 1827 | * The return value is the number of characters which would |
| 1851 | * be generated for the given input, excluding the trailing | 1828 | * be generated for the given input, excluding the trailing |
| @@ -1944,10 +1921,15 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) | |||
| 1944 | break; | 1921 | break; |
| 1945 | 1922 | ||
| 1946 | case FORMAT_TYPE_INVALID: | 1923 | case FORMAT_TYPE_INVALID: |
| 1947 | if (str < end) | 1924 | /* |
| 1948 | *str = '%'; | 1925 | * Presumably the arguments passed gcc's type |
| 1949 | ++str; | 1926 | * checking, but there is no safe or sane way |
| 1950 | break; | 1927 | * for us to continue parsing the format and |
| 1928 | * fetching from the va_list; the remaining | ||
| 1929 | * specifiers and arguments would be out of | ||
| 1930 | * sync. | ||
| 1931 | */ | ||
| 1932 | goto out; | ||
| 1951 | 1933 | ||
| 1952 | default: | 1934 | default: |
| 1953 | switch (spec.type) { | 1935 | switch (spec.type) { |
| @@ -1992,6 +1974,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) | |||
| 1992 | } | 1974 | } |
| 1993 | } | 1975 | } |
| 1994 | 1976 | ||
| 1977 | out: | ||
| 1995 | if (size > 0) { | 1978 | if (size > 0) { |
| 1996 | if (str < end) | 1979 | if (str < end) |
| 1997 | *str = '\0'; | 1980 | *str = '\0'; |
| @@ -2189,9 +2172,10 @@ do { \ | |||
| 2189 | 2172 | ||
| 2190 | switch (spec.type) { | 2173 | switch (spec.type) { |
| 2191 | case FORMAT_TYPE_NONE: | 2174 | case FORMAT_TYPE_NONE: |
| 2192 | case FORMAT_TYPE_INVALID: | ||
| 2193 | case FORMAT_TYPE_PERCENT_CHAR: | 2175 | case FORMAT_TYPE_PERCENT_CHAR: |
| 2194 | break; | 2176 | break; |
| 2177 | case FORMAT_TYPE_INVALID: | ||
| 2178 | goto out; | ||
| 2195 | 2179 | ||
| 2196 | case FORMAT_TYPE_WIDTH: | 2180 | case FORMAT_TYPE_WIDTH: |
| 2197 | case FORMAT_TYPE_PRECISION: | 2181 | case FORMAT_TYPE_PRECISION: |
| @@ -2253,6 +2237,7 @@ do { \ | |||
| 2253 | } | 2237 | } |
| 2254 | } | 2238 | } |
| 2255 | 2239 | ||
| 2240 | out: | ||
| 2256 | return (u32 *)(PTR_ALIGN(str, sizeof(u32))) - bin_buf; | 2241 | return (u32 *)(PTR_ALIGN(str, sizeof(u32))) - bin_buf; |
| 2257 | #undef save_arg | 2242 | #undef save_arg |
| 2258 | } | 2243 | } |
| @@ -2286,7 +2271,7 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf) | |||
| 2286 | char *str, *end; | 2271 | char *str, *end; |
| 2287 | const char *args = (const char *)bin_buf; | 2272 | const char *args = (const char *)bin_buf; |
| 2288 | 2273 | ||
| 2289 | if (WARN_ON_ONCE((int) size < 0)) | 2274 | if (WARN_ON_ONCE(size > INT_MAX)) |
| 2290 | return 0; | 2275 | return 0; |
| 2291 | 2276 | ||
| 2292 | str = buf; | 2277 | str = buf; |
| @@ -2375,12 +2360,14 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf) | |||
| 2375 | break; | 2360 | break; |
| 2376 | 2361 | ||
| 2377 | case FORMAT_TYPE_PERCENT_CHAR: | 2362 | case FORMAT_TYPE_PERCENT_CHAR: |
| 2378 | case FORMAT_TYPE_INVALID: | ||
| 2379 | if (str < end) | 2363 | if (str < end) |
| 2380 | *str = '%'; | 2364 | *str = '%'; |
| 2381 | ++str; | 2365 | ++str; |
| 2382 | break; | 2366 | break; |
| 2383 | 2367 | ||
| 2368 | case FORMAT_TYPE_INVALID: | ||
| 2369 | goto out; | ||
| 2370 | |||
| 2384 | default: { | 2371 | default: { |
| 2385 | unsigned long long num; | 2372 | unsigned long long num; |
| 2386 | 2373 | ||
| @@ -2423,6 +2410,7 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf) | |||
| 2423 | } /* switch(spec.type) */ | 2410 | } /* switch(spec.type) */ |
| 2424 | } /* while(*fmt) */ | 2411 | } /* while(*fmt) */ |
| 2425 | 2412 | ||
| 2413 | out: | ||
| 2426 | if (size > 0) { | 2414 | if (size > 0) { |
| 2427 | if (str < end) | 2415 | if (str < end) |
| 2428 | *str = '\0'; | 2416 | *str = '\0'; |
