diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/string_helpers.c | 208 |
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 | } |
240 | EXPORT_SYMBOL(string_unescape); | 240 | EXPORT_SYMBOL(string_unescape); |
241 | 241 | ||
242 | static int escape_passthrough(unsigned char c, char **dst, size_t *osz) | 242 | static 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 | ||
257 | static int escape_space(unsigned char c, char **dst, size_t *osz) | 252 | static 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 | ||
294 | static int escape_special(unsigned char c, char **dst, size_t *osz) | 293 | static 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 | ||
325 | static int escape_null(unsigned char c, char **dst, size_t *osz) | 328 | static 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 | ||
344 | static int escape_octal(unsigned char c, char **dst, size_t *osz) | 351 | static 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 | ||
362 | static int escape_hex(unsigned char c, char **dst, size_t *osz) | 377 | static 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) | |||
436 | int string_escape_mem(const char *src, size_t isz, char **dst, size_t osz, | 459 | int 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 | } |
512 | EXPORT_SYMBOL(string_escape_mem); | 514 | EXPORT_SYMBOL(string_escape_mem); |