diff options
-rw-r--r-- | fs/proc/array.c | 4 | ||||
-rw-r--r-- | include/linux/string_helpers.h | 8 | ||||
-rw-r--r-- | lib/string_helpers.c | 49 | ||||
-rw-r--r-- | lib/test-string_helpers.c | 40 | ||||
-rw-r--r-- | lib/vsprintf.c | 8 | ||||
-rw-r--r-- | net/sunrpc/cache.c | 8 |
6 files changed, 44 insertions, 73 deletions
diff --git a/fs/proc/array.c b/fs/proc/array.c index a4490c0a4644..13f047ad08e4 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
@@ -99,8 +99,8 @@ static inline void task_name(struct seq_file *m, struct task_struct *p) | |||
99 | buf = m->buf + m->count; | 99 | buf = m->buf + m->count; |
100 | 100 | ||
101 | /* Ignore error for now */ | 101 | /* Ignore error for now */ |
102 | string_escape_str(tcomm, &buf, m->size - m->count, | 102 | buf += string_escape_str(tcomm, buf, m->size - m->count, |
103 | ESCAPE_SPACE | ESCAPE_SPECIAL, "\n\\"); | 103 | ESCAPE_SPACE | ESCAPE_SPECIAL, "\n\\"); |
104 | 104 | ||
105 | m->count = buf - m->buf; | 105 | m->count = buf - m->buf; |
106 | seq_putc(m, '\n'); | 106 | seq_putc(m, '\n'); |
diff --git a/include/linux/string_helpers.h b/include/linux/string_helpers.h index 657571817260..0991913f4953 100644 --- a/include/linux/string_helpers.h +++ b/include/linux/string_helpers.h | |||
@@ -47,22 +47,22 @@ static inline int string_unescape_any_inplace(char *buf) | |||
47 | #define ESCAPE_ANY_NP (ESCAPE_ANY | ESCAPE_NP) | 47 | #define ESCAPE_ANY_NP (ESCAPE_ANY | ESCAPE_NP) |
48 | #define ESCAPE_HEX 0x20 | 48 | #define ESCAPE_HEX 0x20 |
49 | 49 | ||
50 | int string_escape_mem(const char *src, size_t isz, char **dst, size_t osz, | 50 | int string_escape_mem(const char *src, size_t isz, char *dst, size_t osz, |
51 | unsigned int flags, const char *esc); | 51 | unsigned int flags, const char *esc); |
52 | 52 | ||
53 | static inline int string_escape_mem_any_np(const char *src, size_t isz, | 53 | static inline int string_escape_mem_any_np(const char *src, size_t isz, |
54 | char **dst, size_t osz, const char *esc) | 54 | char *dst, size_t osz, const char *esc) |
55 | { | 55 | { |
56 | return string_escape_mem(src, isz, dst, osz, ESCAPE_ANY_NP, esc); | 56 | return string_escape_mem(src, isz, dst, osz, ESCAPE_ANY_NP, esc); |
57 | } | 57 | } |
58 | 58 | ||
59 | static inline int string_escape_str(const char *src, char **dst, size_t sz, | 59 | static inline int string_escape_str(const char *src, char *dst, size_t sz, |
60 | unsigned int flags, const char *esc) | 60 | unsigned int flags, const char *esc) |
61 | { | 61 | { |
62 | return string_escape_mem(src, strlen(src), dst, sz, flags, esc); | 62 | return string_escape_mem(src, strlen(src), dst, sz, flags, esc); |
63 | } | 63 | } |
64 | 64 | ||
65 | static inline int string_escape_str_any_np(const char *src, char **dst, | 65 | static inline int string_escape_str_any_np(const char *src, char *dst, |
66 | size_t sz, const char *esc) | 66 | size_t sz, const char *esc) |
67 | { | 67 | { |
68 | return string_escape_str(src, dst, sz, ESCAPE_ANY_NP, esc); | 68 | return string_escape_str(src, dst, sz, ESCAPE_ANY_NP, esc); |
diff --git a/lib/string_helpers.c b/lib/string_helpers.c index 9c48ddad0f0d..1826c7407258 100644 --- a/lib/string_helpers.c +++ b/lib/string_helpers.c | |||
@@ -274,11 +274,6 @@ static bool escape_space(unsigned char c, char **dst, char *end) | |||
274 | return false; | 274 | return false; |
275 | } | 275 | } |
276 | 276 | ||
277 | if (out + 2 > end) { | ||
278 | *dst = out + 2; | ||
279 | return true; | ||
280 | } | ||
281 | |||
282 | if (out < end) | 277 | if (out < end) |
283 | *out = '\\'; | 278 | *out = '\\'; |
284 | ++out; | 279 | ++out; |
@@ -309,11 +304,6 @@ static bool escape_special(unsigned char c, char **dst, char *end) | |||
309 | return false; | 304 | return false; |
310 | } | 305 | } |
311 | 306 | ||
312 | if (out + 2 > end) { | ||
313 | *dst = out + 2; | ||
314 | return true; | ||
315 | } | ||
316 | |||
317 | if (out < end) | 307 | if (out < end) |
318 | *out = '\\'; | 308 | *out = '\\'; |
319 | ++out; | 309 | ++out; |
@@ -332,11 +322,6 @@ static bool escape_null(unsigned char c, char **dst, char *end) | |||
332 | if (c) | 322 | if (c) |
333 | return false; | 323 | return false; |
334 | 324 | ||
335 | if (out + 2 > end) { | ||
336 | *dst = out + 2; | ||
337 | return true; | ||
338 | } | ||
339 | |||
340 | if (out < end) | 325 | if (out < end) |
341 | *out = '\\'; | 326 | *out = '\\'; |
342 | ++out; | 327 | ++out; |
@@ -352,11 +337,6 @@ static bool escape_octal(unsigned char c, char **dst, char *end) | |||
352 | { | 337 | { |
353 | char *out = *dst; | 338 | char *out = *dst; |
354 | 339 | ||
355 | if (out + 4 > end) { | ||
356 | *dst = out + 4; | ||
357 | return true; | ||
358 | } | ||
359 | |||
360 | if (out < end) | 340 | if (out < end) |
361 | *out = '\\'; | 341 | *out = '\\'; |
362 | ++out; | 342 | ++out; |
@@ -378,11 +358,6 @@ static bool escape_hex(unsigned char c, char **dst, char *end) | |||
378 | { | 358 | { |
379 | char *out = *dst; | 359 | char *out = *dst; |
380 | 360 | ||
381 | if (out + 4 > end) { | ||
382 | *dst = out + 4; | ||
383 | return true; | ||
384 | } | ||
385 | |||
386 | if (out < end) | 361 | if (out < end) |
387 | *out = '\\'; | 362 | *out = '\\'; |
388 | ++out; | 363 | ++out; |
@@ -449,20 +424,17 @@ static bool escape_hex(unsigned char c, char **dst, char *end) | |||
449 | * it if needs. | 424 | * it if needs. |
450 | * | 425 | * |
451 | * Return: | 426 | * Return: |
452 | * The amount of the characters processed to the destination buffer, or | 427 | * The total size of the escaped output that would be generated for |
453 | * %-ENOMEM if the size of buffer is not enough to put an escaped character is | 428 | * the given input and flags. To check whether the output was |
454 | * returned. | 429 | * truncated, compare the return value to osz. There is room left in |
455 | * | 430 | * dst for a '\0' terminator if and only if ret < osz. |
456 | * Even in the case of error @dst pointer will be updated to point to the byte | ||
457 | * after the last processed character. | ||
458 | */ | 431 | */ |
459 | int string_escape_mem(const char *src, size_t isz, char **dst, size_t osz, | 432 | int string_escape_mem(const char *src, size_t isz, char *dst, size_t osz, |
460 | unsigned int flags, const char *esc) | 433 | unsigned int flags, const char *esc) |
461 | { | 434 | { |
462 | char *p = *dst; | 435 | char *p = dst; |
463 | char *end = p + osz; | 436 | char *end = p + osz; |
464 | bool is_dict = esc && *esc; | 437 | bool is_dict = esc && *esc; |
465 | int ret; | ||
466 | 438 | ||
467 | while (isz--) { | 439 | while (isz--) { |
468 | unsigned char c = *src++; | 440 | unsigned char c = *src++; |
@@ -502,13 +474,6 @@ int string_escape_mem(const char *src, size_t isz, char **dst, size_t osz, | |||
502 | escape_passthrough(c, &p, end); | 474 | escape_passthrough(c, &p, end); |
503 | } | 475 | } |
504 | 476 | ||
505 | if (p > end) { | 477 | return p - dst; |
506 | *dst = end; | ||
507 | return -ENOMEM; | ||
508 | } | ||
509 | |||
510 | ret = p - *dst; | ||
511 | *dst = p; | ||
512 | return ret; | ||
513 | } | 478 | } |
514 | EXPORT_SYMBOL(string_escape_mem); | 479 | EXPORT_SYMBOL(string_escape_mem); |
diff --git a/lib/test-string_helpers.c b/lib/test-string_helpers.c index ab0d30e1e18f..8e376efd88a4 100644 --- a/lib/test-string_helpers.c +++ b/lib/test-string_helpers.c | |||
@@ -260,16 +260,28 @@ static __init const char *test_string_find_match(const struct test_string_2 *s2, | |||
260 | return NULL; | 260 | return NULL; |
261 | } | 261 | } |
262 | 262 | ||
263 | static __init void | ||
264 | test_string_escape_overflow(const char *in, int p, unsigned int flags, const char *esc, | ||
265 | int q_test, const char *name) | ||
266 | { | ||
267 | int q_real; | ||
268 | |||
269 | q_real = string_escape_mem(in, p, NULL, 0, flags, esc); | ||
270 | if (q_real != q_test) | ||
271 | pr_warn("Test '%s' failed: flags = %u, osz = 0, expected %d, got %d\n", | ||
272 | name, flags, q_test, q_real); | ||
273 | } | ||
274 | |||
263 | static __init void test_string_escape(const char *name, | 275 | static __init void test_string_escape(const char *name, |
264 | const struct test_string_2 *s2, | 276 | const struct test_string_2 *s2, |
265 | unsigned int flags, const char *esc) | 277 | unsigned int flags, const char *esc) |
266 | { | 278 | { |
267 | int q_real = 512; | 279 | size_t out_size = 512; |
268 | char *out_test = kmalloc(q_real, GFP_KERNEL); | 280 | char *out_test = kmalloc(out_size, GFP_KERNEL); |
269 | char *out_real = kmalloc(q_real, GFP_KERNEL); | 281 | char *out_real = kmalloc(out_size, GFP_KERNEL); |
270 | char *in = kmalloc(256, GFP_KERNEL); | 282 | char *in = kmalloc(256, GFP_KERNEL); |
271 | char *buf = out_real; | ||
272 | int p = 0, q_test = 0; | 283 | int p = 0, q_test = 0; |
284 | int q_real; | ||
273 | 285 | ||
274 | if (!out_test || !out_real || !in) | 286 | if (!out_test || !out_real || !in) |
275 | goto out; | 287 | goto out; |
@@ -301,29 +313,19 @@ static __init void test_string_escape(const char *name, | |||
301 | q_test += len; | 313 | q_test += len; |
302 | } | 314 | } |
303 | 315 | ||
304 | q_real = string_escape_mem(in, p, &buf, q_real, flags, esc); | 316 | q_real = string_escape_mem(in, p, out_real, out_size, flags, esc); |
305 | 317 | ||
306 | test_string_check_buf(name, flags, in, p, out_real, q_real, out_test, | 318 | test_string_check_buf(name, flags, in, p, out_real, q_real, out_test, |
307 | q_test); | 319 | q_test); |
320 | |||
321 | test_string_escape_overflow(in, p, flags, esc, q_test, name); | ||
322 | |||
308 | out: | 323 | out: |
309 | kfree(in); | 324 | kfree(in); |
310 | kfree(out_real); | 325 | kfree(out_real); |
311 | kfree(out_test); | 326 | kfree(out_test); |
312 | } | 327 | } |
313 | 328 | ||
314 | static __init void test_string_escape_nomem(void) | ||
315 | { | ||
316 | char *in = "\eb \\C\007\"\x90\r]"; | ||
317 | char out[64], *buf = out; | ||
318 | int rc = -ENOMEM, ret; | ||
319 | |||
320 | ret = string_escape_str_any_np(in, &buf, strlen(in), NULL); | ||
321 | if (ret == rc) | ||
322 | return; | ||
323 | |||
324 | pr_err("Test 'escape nomem' failed: got %d instead of %d\n", ret, rc); | ||
325 | } | ||
326 | |||
327 | static int __init test_string_helpers_init(void) | 329 | static int __init test_string_helpers_init(void) |
328 | { | 330 | { |
329 | unsigned int i; | 331 | unsigned int i; |
@@ -342,8 +344,6 @@ static int __init test_string_helpers_init(void) | |||
342 | for (i = 0; i < (ESCAPE_ANY_NP | ESCAPE_HEX) + 1; i++) | 344 | for (i = 0; i < (ESCAPE_ANY_NP | ESCAPE_HEX) + 1; i++) |
343 | test_string_escape("escape 1", escape1, i, TEST_STRING_2_DICT_1); | 345 | test_string_escape("escape 1", escape1, i, TEST_STRING_2_DICT_1); |
344 | 346 | ||
345 | test_string_escape_nomem(); | ||
346 | |||
347 | return -EINVAL; | 347 | return -EINVAL; |
348 | } | 348 | } |
349 | module_init(test_string_helpers_init); | 349 | module_init(test_string_helpers_init); |
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 4da1e7aaf9d5..3a1e0843f9a2 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
@@ -1235,8 +1235,12 @@ char *escaped_string(char *buf, char *end, u8 *addr, struct printf_spec spec, | |||
1235 | 1235 | ||
1236 | len = spec.field_width < 0 ? 1 : spec.field_width; | 1236 | len = spec.field_width < 0 ? 1 : spec.field_width; |
1237 | 1237 | ||
1238 | /* Ignore the error. We print as many characters as we can */ | 1238 | /* |
1239 | string_escape_mem(addr, len, &buf, end - buf, flags, NULL); | 1239 | * string_escape_mem() writes as many characters as it can to |
1240 | * the given buffer, and returns the total size of the output | ||
1241 | * had the buffer been big enough. | ||
1242 | */ | ||
1243 | buf += string_escape_mem(addr, len, buf, buf < end ? end - buf : 0, flags, NULL); | ||
1240 | 1244 | ||
1241 | return buf; | 1245 | return buf; |
1242 | } | 1246 | } |
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 5199bb1a017e..2928afffbb81 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c | |||
@@ -1072,10 +1072,12 @@ void qword_add(char **bpp, int *lp, char *str) | |||
1072 | 1072 | ||
1073 | if (len < 0) return; | 1073 | if (len < 0) return; |
1074 | 1074 | ||
1075 | ret = string_escape_str(str, &bp, len, ESCAPE_OCTAL, "\\ \n\t"); | 1075 | ret = string_escape_str(str, bp, len, ESCAPE_OCTAL, "\\ \n\t"); |
1076 | if (ret < 0 || ret == len) | 1076 | if (ret >= len) { |
1077 | bp += len; | ||
1077 | len = -1; | 1078 | len = -1; |
1078 | else { | 1079 | } else { |
1080 | bp += ret; | ||
1079 | len -= ret; | 1081 | len -= ret; |
1080 | *bp++ = ' '; | 1082 | *bp++ = ' '; |
1081 | len--; | 1083 | len--; |