aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/string_helpers.c49
-rw-r--r--lib/test-string_helpers.c40
-rw-r--r--lib/vsprintf.c8
3 files changed, 33 insertions, 64 deletions
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 */
459int string_escape_mem(const char *src, size_t isz, char **dst, size_t osz, 432int 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}
514EXPORT_SYMBOL(string_escape_mem); 479EXPORT_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
263static __init void
264test_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
263static __init void test_string_escape(const char *name, 275static __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
308out: 323out:
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
314static __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
327static int __init test_string_helpers_init(void) 329static 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}
349module_init(test_string_helpers_init); 349module_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}