aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-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);