aboutsummaryrefslogtreecommitdiffstats
path: root/lib/vsprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/vsprintf.c')
-rw-r--r--lib/vsprintf.c80
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
1457char *pointer(const char *fmt, char *buf, char *end, void *ptr, 1459char *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
1977out:
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
2240out:
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
2413out:
2426 if (size > 0) { 2414 if (size > 0) {
2427 if (str < end) 2415 if (str < end)
2428 *str = '\0'; 2416 *str = '\0';