aboutsummaryrefslogtreecommitdiffstats
path: root/lib/string_helpers.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/string_helpers.c')
-rw-r--r--lib/string_helpers.c193
1 files changed, 80 insertions, 113 deletions
diff --git a/lib/string_helpers.c b/lib/string_helpers.c
index 8f8c4417f228..1826c7407258 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,25 @@ 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 < end)
286 *out++ = to; 278 *out = '\\';
279 ++out;
280 if (out < end)
281 *out = to;
282 ++out;
287 283
288 *dst = out; 284 *dst = out;
289 *osz -= 2; 285 return true;
290
291 return 1;
292} 286}
293 287
294static int escape_special(unsigned char c, char **dst, size_t *osz) 288static bool escape_special(unsigned char c, char **dst, char *end)
295{ 289{
296 char *out = *dst; 290 char *out = *dst;
297 unsigned char to; 291 unsigned char to;
298 292
299 if (*osz < 2)
300 return -ENOMEM;
301
302 switch (c) { 293 switch (c) {
303 case '\\': 294 case '\\':
304 to = '\\'; 295 to = '\\';
@@ -310,71 +301,78 @@ static int escape_special(unsigned char c, char **dst, size_t *osz)
310 to = 'e'; 301 to = 'e';
311 break; 302 break;
312 default: 303 default:
313 return 0; 304 return false;
314 } 305 }
315 306
316 *out++ = '\\'; 307 if (out < end)
317 *out++ = to; 308 *out = '\\';
309 ++out;
310 if (out < end)
311 *out = to;
312 ++out;
318 313
319 *dst = out; 314 *dst = out;
320 *osz -= 2; 315 return true;
321
322 return 1;
323} 316}
324 317
325static int escape_null(unsigned char c, char **dst, size_t *osz) 318static bool escape_null(unsigned char c, char **dst, char *end)
326{ 319{
327 char *out = *dst; 320 char *out = *dst;
328 321
329 if (*osz < 2)
330 return -ENOMEM;
331
332 if (c) 322 if (c)
333 return 0; 323 return false;
334 324
335 *out++ = '\\'; 325 if (out < end)
336 *out++ = '0'; 326 *out = '\\';
327 ++out;
328 if (out < end)
329 *out = '0';
330 ++out;
337 331
338 *dst = out; 332 *dst = out;
339 *osz -= 2; 333 return true;
340
341 return 1;
342} 334}
343 335
344static int escape_octal(unsigned char c, char **dst, size_t *osz) 336static bool escape_octal(unsigned char c, char **dst, char *end)
345{ 337{
346 char *out = *dst; 338 char *out = *dst;
347 339
348 if (*osz < 4) 340 if (out < end)
349 return -ENOMEM; 341 *out = '\\';
350 342 ++out;
351 *out++ = '\\'; 343 if (out < end)
352 *out++ = ((c >> 6) & 0x07) + '0'; 344 *out = ((c >> 6) & 0x07) + '0';
353 *out++ = ((c >> 3) & 0x07) + '0'; 345 ++out;
354 *out++ = ((c >> 0) & 0x07) + '0'; 346 if (out < end)
347 *out = ((c >> 3) & 0x07) + '0';
348 ++out;
349 if (out < end)
350 *out = ((c >> 0) & 0x07) + '0';
351 ++out;
355 352
356 *dst = out; 353 *dst = out;
357 *osz -= 4; 354 return true;
358
359 return 1;
360} 355}
361 356
362static int escape_hex(unsigned char c, char **dst, size_t *osz) 357static bool escape_hex(unsigned char c, char **dst, char *end)
363{ 358{
364 char *out = *dst; 359 char *out = *dst;
365 360
366 if (*osz < 4) 361 if (out < end)
367 return -ENOMEM; 362 *out = '\\';
368 363 ++out;
369 *out++ = '\\'; 364 if (out < end)
370 *out++ = 'x'; 365 *out = 'x';
371 *out++ = hex_asc_hi(c); 366 ++out;
372 *out++ = hex_asc_lo(c); 367 if (out < end)
368 *out = hex_asc_hi(c);
369 ++out;
370 if (out < end)
371 *out = hex_asc_lo(c);
372 ++out;
373 373
374 *dst = out; 374 *dst = out;
375 *osz -= 4; 375 return true;
376
377 return 1;
378} 376}
379 377
380/** 378/**
@@ -426,19 +424,17 @@ static int escape_hex(unsigned char c, char **dst, size_t *osz)
426 * it if needs. 424 * it if needs.
427 * 425 *
428 * Return: 426 * Return:
429 * The amount of the characters processed to the destination buffer, or 427 * The total size of the escaped output that would be generated for
430 * %-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
431 * returned. 429 * truncated, compare the return value to osz. There is room left in
432 * 430 * dst for a '\0' terminator if and only if ret < osz.
433 * Even in the case of error @dst pointer will be updated to point to the byte
434 * after the last processed character.
435 */ 431 */
436int 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,
437 unsigned int flags, const char *esc) 433 unsigned int flags, const char *esc)
438{ 434{
439 char *out = *dst, *p = out; 435 char *p = dst;
436 char *end = p + osz;
440 bool is_dict = esc && *esc; 437 bool is_dict = esc && *esc;
441 int ret = 0;
442 438
443 while (isz--) { 439 while (isz--) {
444 unsigned char c = *src++; 440 unsigned char c = *src++;
@@ -458,55 +454,26 @@ int string_escape_mem(const char *src, size_t isz, char **dst, size_t osz,
458 (is_dict && !strchr(esc, c))) { 454 (is_dict && !strchr(esc, c))) {
459 /* do nothing */ 455 /* do nothing */
460 } else { 456 } else {
461 if (flags & ESCAPE_SPACE) { 457 if (flags & ESCAPE_SPACE && escape_space(c, &p, end))
462 ret = escape_space(c, &p, &osz); 458 continue;
463 if (ret < 0) 459
464 break; 460 if (flags & ESCAPE_SPECIAL && escape_special(c, &p, end))
465 if (ret > 0) 461 continue;
466 continue; 462
467 } 463 if (flags & ESCAPE_NULL && escape_null(c, &p, end))
468 464 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 465
485 /* ESCAPE_OCTAL and ESCAPE_HEX always go last */ 466 /* ESCAPE_OCTAL and ESCAPE_HEX always go last */
486 if (flags & ESCAPE_OCTAL) { 467 if (flags & ESCAPE_OCTAL && escape_octal(c, &p, end))
487 ret = escape_octal(c, &p, &osz);
488 if (ret < 0)
489 break;
490 continue; 468 continue;
491 } 469
492 if (flags & ESCAPE_HEX) { 470 if (flags & ESCAPE_HEX && escape_hex(c, &p, end))
493 ret = escape_hex(c, &p, &osz);
494 if (ret < 0)
495 break;
496 continue; 471 continue;
497 }
498 } 472 }
499 473
500 ret = escape_passthrough(c, &p, &osz); 474 escape_passthrough(c, &p, end);
501 if (ret < 0)
502 break;
503 } 475 }
504 476
505 *dst = p; 477 return p - dst;
506
507 if (ret < 0)
508 return ret;
509
510 return p - out;
511} 478}
512EXPORT_SYMBOL(string_escape_mem); 479EXPORT_SYMBOL(string_escape_mem);