diff options
Diffstat (limited to 'lib/vsprintf.c')
-rw-r--r-- | lib/vsprintf.c | 73 |
1 files changed, 72 insertions, 1 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 6fe2c84eb055..ec337f64f52d 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <asm/page.h> /* for PAGE_SIZE */ | 33 | #include <asm/page.h> /* for PAGE_SIZE */ |
34 | #include <asm/sections.h> /* for dereference_function_descriptor() */ | 34 | #include <asm/sections.h> /* for dereference_function_descriptor() */ |
35 | 35 | ||
36 | #include <linux/string_helpers.h> | ||
36 | #include "kstrtox.h" | 37 | #include "kstrtox.h" |
37 | 38 | ||
38 | /** | 39 | /** |
@@ -1101,6 +1102,62 @@ char *ip4_addr_string_sa(char *buf, char *end, const struct sockaddr_in *sa, | |||
1101 | } | 1102 | } |
1102 | 1103 | ||
1103 | static noinline_for_stack | 1104 | static noinline_for_stack |
1105 | char *escaped_string(char *buf, char *end, u8 *addr, struct printf_spec spec, | ||
1106 | const char *fmt) | ||
1107 | { | ||
1108 | bool found = true; | ||
1109 | int count = 1; | ||
1110 | unsigned int flags = 0; | ||
1111 | int len; | ||
1112 | |||
1113 | if (spec.field_width == 0) | ||
1114 | return buf; /* nothing to print */ | ||
1115 | |||
1116 | if (ZERO_OR_NULL_PTR(addr)) | ||
1117 | return string(buf, end, NULL, spec); /* NULL pointer */ | ||
1118 | |||
1119 | |||
1120 | do { | ||
1121 | switch (fmt[count++]) { | ||
1122 | case 'a': | ||
1123 | flags |= ESCAPE_ANY; | ||
1124 | break; | ||
1125 | case 'c': | ||
1126 | flags |= ESCAPE_SPECIAL; | ||
1127 | break; | ||
1128 | case 'h': | ||
1129 | flags |= ESCAPE_HEX; | ||
1130 | break; | ||
1131 | case 'n': | ||
1132 | flags |= ESCAPE_NULL; | ||
1133 | break; | ||
1134 | case 'o': | ||
1135 | flags |= ESCAPE_OCTAL; | ||
1136 | break; | ||
1137 | case 'p': | ||
1138 | flags |= ESCAPE_NP; | ||
1139 | break; | ||
1140 | case 's': | ||
1141 | flags |= ESCAPE_SPACE; | ||
1142 | break; | ||
1143 | default: | ||
1144 | found = false; | ||
1145 | break; | ||
1146 | } | ||
1147 | } while (found); | ||
1148 | |||
1149 | if (!flags) | ||
1150 | flags = ESCAPE_ANY_NP; | ||
1151 | |||
1152 | len = spec.field_width < 0 ? 1 : spec.field_width; | ||
1153 | |||
1154 | /* Ignore the error. We print as many characters as we can */ | ||
1155 | string_escape_mem(addr, len, &buf, end - buf, flags, NULL); | ||
1156 | |||
1157 | return buf; | ||
1158 | } | ||
1159 | |||
1160 | static noinline_for_stack | ||
1104 | char *uuid_string(char *buf, char *end, const u8 *addr, | 1161 | char *uuid_string(char *buf, char *end, const u8 *addr, |
1105 | struct printf_spec spec, const char *fmt) | 1162 | struct printf_spec spec, const char *fmt) |
1106 | { | 1163 | { |
@@ -1221,6 +1278,17 @@ int kptr_restrict __read_mostly; | |||
1221 | * - '[Ii][4S][hnbl]' IPv4 addresses in host, network, big or little endian order | 1278 | * - '[Ii][4S][hnbl]' IPv4 addresses in host, network, big or little endian order |
1222 | * - 'I[6S]c' for IPv6 addresses printed as specified by | 1279 | * - 'I[6S]c' for IPv6 addresses printed as specified by |
1223 | * http://tools.ietf.org/html/rfc5952 | 1280 | * http://tools.ietf.org/html/rfc5952 |
1281 | * - 'E[achnops]' For an escaped buffer, where rules are defined by combination | ||
1282 | * of the following flags (see string_escape_mem() for the | ||
1283 | * details): | ||
1284 | * a - ESCAPE_ANY | ||
1285 | * c - ESCAPE_SPECIAL | ||
1286 | * h - ESCAPE_HEX | ||
1287 | * n - ESCAPE_NULL | ||
1288 | * o - ESCAPE_OCTAL | ||
1289 | * p - ESCAPE_NP | ||
1290 | * s - ESCAPE_SPACE | ||
1291 | * By default ESCAPE_ANY_NP is used. | ||
1224 | * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form | 1292 | * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form |
1225 | * "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" | 1293 | * "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" |
1226 | * Options for %pU are: | 1294 | * Options for %pU are: |
@@ -1321,6 +1389,8 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
1321 | }} | 1389 | }} |
1322 | } | 1390 | } |
1323 | break; | 1391 | break; |
1392 | case 'E': | ||
1393 | return escaped_string(buf, end, ptr, spec, fmt); | ||
1324 | case 'U': | 1394 | case 'U': |
1325 | return uuid_string(buf, end, ptr, spec, fmt); | 1395 | return uuid_string(buf, end, ptr, spec, fmt); |
1326 | case 'V': | 1396 | case 'V': |
@@ -1633,6 +1703,7 @@ qualifier: | |||
1633 | * %piS depending on sa_family of 'struct sockaddr *' print IPv4/IPv6 address | 1703 | * %piS depending on sa_family of 'struct sockaddr *' print IPv4/IPv6 address |
1634 | * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper | 1704 | * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper |
1635 | * case. | 1705 | * case. |
1706 | * %*pE[achnops] print an escaped buffer | ||
1636 | * %*ph[CDN] a variable-length hex string with a separator (supports up to 64 | 1707 | * %*ph[CDN] a variable-length hex string with a separator (supports up to 64 |
1637 | * bytes of the input) | 1708 | * bytes of the input) |
1638 | * %n is ignored | 1709 | * %n is ignored |
@@ -1937,7 +2008,7 @@ EXPORT_SYMBOL(sprintf); | |||
1937 | * @args: Arguments for the format string | 2008 | * @args: Arguments for the format string |
1938 | * | 2009 | * |
1939 | * The format follows C99 vsnprintf, except %n is ignored, and its argument | 2010 | * The format follows C99 vsnprintf, except %n is ignored, and its argument |
1940 | * is skiped. | 2011 | * is skipped. |
1941 | * | 2012 | * |
1942 | * The return value is the number of words(32bits) which would be generated for | 2013 | * The return value is the number of words(32bits) which would be generated for |
1943 | * the given input. | 2014 | * the given input. |