aboutsummaryrefslogtreecommitdiffstats
path: root/lib/string_helpers.c
diff options
context:
space:
mode:
authorRasmus Villemoes <linux@rasmusvillemoes.dk>2015-04-15 19:17:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-04-15 19:35:23 -0400
commit3aeddc7d665e41b1ba193f5c427ca52086d085ae (patch)
tree7f00129aa094227adc55ee92cc585f039a747fe5 /lib/string_helpers.c
parent9c98f2359600386efd1c6adfabc5a04118a79798 (diff)
lib/string_helpers.c: refactor string_escape_mem
When printf is given the format specifier %pE, it needs a way of obtaining the total output size that would be generated if the buffer was large enough, and string_escape_mem doesn't easily provide that. This is a refactorization of string_escape_mem in preparation of changing its external API to provide that information. The somewhat ugly early returns and subsequent seemingly redundant conditionals are to make the following patch touch as little as possible in string_helpers.c while still preserving the current behaviour of never outputting partial escape sequences. That behaviour must also change for %pE to work as one expects from every other printf specifier. Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'lib/string_helpers.c')
-rw-r--r--lib/string_helpers.c208
1 files changed, 105 insertions, 103 deletions
diff --git a/lib/string_helpers.c b/lib/string_helpers.c
index 8f8c4417f228..9c48ddad0f0d 100644
--- a/lib/string_helpers.c
+++ b/lib/string_helpers.c
@@ -239,29 +239,21 @@ int string_unescape(char *src, char *dst, size_t size, unsigned int flags)
239} 239}
240EXPORT_SYMBOL(string_unescape); 240EXPORT_SYMBOL(string_unescape);
241 241
242static int escape_passthrough(unsigned char c, char **dst, size_t *osz) 242static bool escape_passthrough(unsigned char c, char **dst, char *end)
243{ 243{
244 char *out = *dst; 244 char *out = *dst;
245 245
246 if (*osz < 1) 246 if (out < end)
247 return -ENOMEM; 247 *out = c;
248 248 *dst = out + 1;
249 *out++ = c; 249 return true;
250
251 *dst = out;
252 *osz -= 1;
253
254 return 1;
255} 250}
256 251
257static int escape_space(unsigned char c, char **dst, size_t *osz) 252static bool escape_space(unsigned char c, char **dst, char *end)
258{ 253{
259 char *out = *dst; 254 char *out = *dst;
260 unsigned char to; 255 unsigned char to;
261 256
262 if (*osz < 2)
263 return -ENOMEM;
264
265 switch (c) { 257 switch (c) {
266 case '\n': 258 case '\n':
267 to = 'n'; 259 to = 'n';
@@ -279,26 +271,30 @@ static int escape_space(unsigned char c, char **dst, size_t *osz)
279 to = 'f'; 271 to = 'f';
280 break; 272 break;
281 default: 273 default:
282 return 0; 274 return false;
283 } 275 }
284 276
285 *out++ = '\\'; 277 if (out + 2 > end) {
286 *out++ = to; 278 *dst = out + 2;
279 return true;
280 }
287 281
288 *dst = out; 282 if (out < end)
289 *osz -= 2; 283 *out = '\\';
284 ++out;
285 if (out < end)
286 *out = to;
287 ++out;
290 288
291 return 1; 289 *dst = out;
290 return true;
292} 291}
293 292
294static int escape_special(unsigned char c, char **dst, size_t *osz) 293static bool escape_special(unsigned char c, char **dst, char *end)
295{ 294{
296 char *out = *dst; 295 char *out = *dst;
297 unsigned char to; 296 unsigned char to;
298 297
299 if (*osz < 2)
300 return -ENOMEM;
301
302 switch (c) { 298 switch (c) {
303 case '\\': 299 case '\\':
304 to = '\\'; 300 to = '\\';
@@ -310,71 +306,98 @@ static int escape_special(unsigned char c, char **dst, size_t *osz)
310 to = 'e'; 306 to = 'e';
311 break; 307 break;
312 default: 308 default:
313 return 0; 309 return false;
314 } 310 }
315 311
316 *out++ = '\\'; 312 if (out + 2 > end) {
317 *out++ = to; 313 *dst = out + 2;
314 return true;
315 }
318 316
319 *dst = out; 317 if (out < end)
320 *osz -= 2; 318 *out = '\\';
319 ++out;
320 if (out < end)
321 *out = to;
322 ++out;
321 323
322 return 1; 324 *dst = out;
325 return true;
323} 326}
324 327
325static int escape_null(unsigned char c, char **dst, size_t *osz) 328static bool escape_null(unsigned char c, char **dst, char *end)
326{ 329{
327 char *out = *dst; 330 char *out = *dst;
328 331
329 if (*osz < 2)
330 return -ENOMEM;
331
332 if (c) 332 if (c)
333 return 0; 333 return false;
334 334
335 *out++ = '\\'; 335 if (out + 2 > end) {
336 *out++ = '0'; 336 *dst = out + 2;
337 return true;
338 }
337 339
338 *dst = out; 340 if (out < end)
339 *osz -= 2; 341 *out = '\\';
342 ++out;
343 if (out < end)
344 *out = '0';
345 ++out;
340 346
341 return 1; 347 *dst = out;
348 return true;
342} 349}
343 350
344static int escape_octal(unsigned char c, char **dst, size_t *osz) 351static bool escape_octal(unsigned char c, char **dst, char *end)
345{ 352{
346 char *out = *dst; 353 char *out = *dst;
347 354
348 if (*osz < 4) 355 if (out + 4 > end) {
349 return -ENOMEM; 356 *dst = out + 4;
357 return true;
358 }
350 359
351 *out++ = '\\'; 360 if (out < end)
352 *out++ = ((c >> 6) & 0x07) + '0'; 361 *out = '\\';
353 *out++ = ((c >> 3) & 0x07) + '0'; 362 ++out;
354 *out++ = ((c >> 0) & 0x07) + '0'; 363 if (out < end)
364 *out = ((c >> 6) & 0x07) + '0';
365 ++out;
366 if (out < end)
367 *out = ((c >> 3) & 0x07) + '0';
368 ++out;
369 if (out < end)
370 *out = ((c >> 0) & 0x07) + '0';
371 ++out;
355 372
356 *dst = out; 373 *dst = out;
357 *osz -= 4; 374 return true;
358
359 return 1;
360} 375}
361 376
362static int escape_hex(unsigned char c, char **dst, size_t *osz) 377static bool escape_hex(unsigned char c, char **dst, char *end)
363{ 378{
364 char *out = *dst; 379 char *out = *dst;
365 380
366 if (*osz < 4) 381 if (out + 4 > end) {
367 return -ENOMEM; 382 *dst = out + 4;
383 return true;
384 }
368 385
369 *out++ = '\\'; 386 if (out < end)
370 *out++ = 'x'; 387 *out = '\\';
371 *out++ = hex_asc_hi(c); 388 ++out;
372 *out++ = hex_asc_lo(c); 389 if (out < end)
390 *out = 'x';
391 ++out;
392 if (out < end)
393 *out = hex_asc_hi(c);
394 ++out;
395 if (out < end)
396 *out = hex_asc_lo(c);
397 ++out;
373 398
374 *dst = out; 399 *dst = out;
375 *osz -= 4; 400 return true;
376
377 return 1;
378} 401}
379 402
380/** 403/**
@@ -436,9 +459,10 @@ static int escape_hex(unsigned char c, char **dst, size_t *osz)
436int string_escape_mem(const char *src, size_t isz, char **dst, size_t osz, 459int string_escape_mem(const char *src, size_t isz, char **dst, size_t osz,
437 unsigned int flags, const char *esc) 460 unsigned int flags, const char *esc)
438{ 461{
439 char *out = *dst, *p = out; 462 char *p = *dst;
463 char *end = p + osz;
440 bool is_dict = esc && *esc; 464 bool is_dict = esc && *esc;
441 int ret = 0; 465 int ret;
442 466
443 while (isz--) { 467 while (isz--) {
444 unsigned char c = *src++; 468 unsigned char c = *src++;
@@ -458,55 +482,33 @@ int string_escape_mem(const char *src, size_t isz, char **dst, size_t osz,
458 (is_dict && !strchr(esc, c))) { 482 (is_dict && !strchr(esc, c))) {
459 /* do nothing */ 483 /* do nothing */
460 } else { 484 } else {
461 if (flags & ESCAPE_SPACE) { 485 if (flags & ESCAPE_SPACE && escape_space(c, &p, end))
462 ret = escape_space(c, &p, &osz); 486 continue;
463 if (ret < 0) 487
464 break; 488 if (flags & ESCAPE_SPECIAL && escape_special(c, &p, end))
465 if (ret > 0) 489 continue;
466 continue; 490
467 } 491 if (flags & ESCAPE_NULL && escape_null(c, &p, end))
468 492 continue;
469 if (flags & ESCAPE_SPECIAL) {
470 ret = escape_special(c, &p, &osz);
471 if (ret < 0)
472 break;
473 if (ret > 0)
474 continue;
475 }
476
477 if (flags & ESCAPE_NULL) {
478 ret = escape_null(c, &p, &osz);
479 if (ret < 0)
480 break;
481 if (ret > 0)
482 continue;
483 }
484 493
485 /* ESCAPE_OCTAL and ESCAPE_HEX always go last */ 494 /* ESCAPE_OCTAL and ESCAPE_HEX always go last */
486 if (flags & ESCAPE_OCTAL) { 495 if (flags & ESCAPE_OCTAL && escape_octal(c, &p, end))
487 ret = escape_octal(c, &p, &osz);
488 if (ret < 0)
489 break;
490 continue; 496 continue;
491 } 497
492 if (flags & ESCAPE_HEX) { 498 if (flags & ESCAPE_HEX && escape_hex(c, &p, end))
493 ret = escape_hex(c, &p, &osz);
494 if (ret < 0)
495 break;
496 continue; 499 continue;
497 }
498 } 500 }
499 501
500 ret = escape_passthrough(c, &p, &osz); 502 escape_passthrough(c, &p, end);
501 if (ret < 0)
502 break;
503 } 503 }
504 504
505 *dst = p; 505 if (p > end) {
506 506 *dst = end;
507 if (ret < 0) 507 return -ENOMEM;
508 return ret; 508 }
509 509
510 return p - out; 510 ret = p - *dst;
511 *dst = p;
512 return ret;
511} 513}
512EXPORT_SYMBOL(string_escape_mem); 514EXPORT_SYMBOL(string_escape_mem);