diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/vsprintf.c | 82 |
1 files changed, 69 insertions, 13 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 2b18135446dc..8f56cdd52149 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
| @@ -2517,29 +2517,34 @@ int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args) | |||
| 2517 | { | 2517 | { |
| 2518 | struct printf_spec spec = {0}; | 2518 | struct printf_spec spec = {0}; |
| 2519 | char *str, *end; | 2519 | char *str, *end; |
| 2520 | int width; | ||
| 2520 | 2521 | ||
| 2521 | str = (char *)bin_buf; | 2522 | str = (char *)bin_buf; |
| 2522 | end = (char *)(bin_buf + size); | 2523 | end = (char *)(bin_buf + size); |
| 2523 | 2524 | ||
| 2524 | #define save_arg(type) \ | 2525 | #define save_arg(type) \ |
| 2525 | do { \ | 2526 | ({ \ |
| 2527 | unsigned long long value; \ | ||
| 2526 | if (sizeof(type) == 8) { \ | 2528 | if (sizeof(type) == 8) { \ |
| 2527 | unsigned long long value; \ | 2529 | unsigned long long val8; \ |
| 2528 | str = PTR_ALIGN(str, sizeof(u32)); \ | 2530 | str = PTR_ALIGN(str, sizeof(u32)); \ |
| 2529 | value = va_arg(args, unsigned long long); \ | 2531 | val8 = va_arg(args, unsigned long long); \ |
| 2530 | if (str + sizeof(type) <= end) { \ | 2532 | if (str + sizeof(type) <= end) { \ |
| 2531 | *(u32 *)str = *(u32 *)&value; \ | 2533 | *(u32 *)str = *(u32 *)&val8; \ |
| 2532 | *(u32 *)(str + 4) = *((u32 *)&value + 1); \ | 2534 | *(u32 *)(str + 4) = *((u32 *)&val8 + 1); \ |
| 2533 | } \ | 2535 | } \ |
| 2536 | value = val8; \ | ||
| 2534 | } else { \ | 2537 | } else { \ |
| 2535 | unsigned long value; \ | 2538 | unsigned int val4; \ |
| 2536 | str = PTR_ALIGN(str, sizeof(type)); \ | 2539 | str = PTR_ALIGN(str, sizeof(type)); \ |
| 2537 | value = va_arg(args, int); \ | 2540 | val4 = va_arg(args, int); \ |
| 2538 | if (str + sizeof(type) <= end) \ | 2541 | if (str + sizeof(type) <= end) \ |
| 2539 | *(typeof(type) *)str = (type)value; \ | 2542 | *(typeof(type) *)str = (type)(long)val4; \ |
| 2543 | value = (unsigned long long)val4; \ | ||
| 2540 | } \ | 2544 | } \ |
| 2541 | str += sizeof(type); \ | 2545 | str += sizeof(type); \ |
| 2542 | } while (0) | 2546 | value; \ |
| 2547 | }) | ||
| 2543 | 2548 | ||
| 2544 | while (*fmt) { | 2549 | while (*fmt) { |
| 2545 | int read = format_decode(fmt, &spec); | 2550 | int read = format_decode(fmt, &spec); |
| @@ -2555,7 +2560,10 @@ do { \ | |||
| 2555 | 2560 | ||
| 2556 | case FORMAT_TYPE_WIDTH: | 2561 | case FORMAT_TYPE_WIDTH: |
| 2557 | case FORMAT_TYPE_PRECISION: | 2562 | case FORMAT_TYPE_PRECISION: |
| 2558 | save_arg(int); | 2563 | width = (int)save_arg(int); |
| 2564 | /* Pointers may require the width */ | ||
| 2565 | if (*fmt == 'p') | ||
| 2566 | set_field_width(&spec, width); | ||
| 2559 | break; | 2567 | break; |
| 2560 | 2568 | ||
| 2561 | case FORMAT_TYPE_CHAR: | 2569 | case FORMAT_TYPE_CHAR: |
| @@ -2577,7 +2585,27 @@ do { \ | |||
| 2577 | } | 2585 | } |
| 2578 | 2586 | ||
| 2579 | case FORMAT_TYPE_PTR: | 2587 | case FORMAT_TYPE_PTR: |
| 2580 | save_arg(void *); | 2588 | /* Dereferenced pointers must be done now */ |
| 2589 | switch (*fmt) { | ||
| 2590 | /* Dereference of functions is still OK */ | ||
| 2591 | case 'S': | ||
| 2592 | case 's': | ||
| 2593 | case 'F': | ||
| 2594 | case 'f': | ||
| 2595 | save_arg(void *); | ||
| 2596 | break; | ||
| 2597 | default: | ||
| 2598 | if (!isalnum(*fmt)) { | ||
| 2599 | save_arg(void *); | ||
| 2600 | break; | ||
| 2601 | } | ||
| 2602 | str = pointer(fmt, str, end, va_arg(args, void *), | ||
| 2603 | spec); | ||
| 2604 | if (str + 1 < end) | ||
| 2605 | *str++ = '\0'; | ||
| 2606 | else | ||
| 2607 | end[-1] = '\0'; /* Must be nul terminated */ | ||
| 2608 | } | ||
| 2581 | /* skip all alphanumeric pointer suffixes */ | 2609 | /* skip all alphanumeric pointer suffixes */ |
| 2582 | while (isalnum(*fmt)) | 2610 | while (isalnum(*fmt)) |
| 2583 | fmt++; | 2611 | fmt++; |
| @@ -2729,11 +2757,39 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf) | |||
| 2729 | break; | 2757 | break; |
| 2730 | } | 2758 | } |
| 2731 | 2759 | ||
| 2732 | case FORMAT_TYPE_PTR: | 2760 | case FORMAT_TYPE_PTR: { |
| 2733 | str = pointer(fmt, str, end, get_arg(void *), spec); | 2761 | bool process = false; |
| 2762 | int copy, len; | ||
| 2763 | /* Non function dereferences were already done */ | ||
| 2764 | switch (*fmt) { | ||
| 2765 | case 'S': | ||
| 2766 | case 's': | ||
| 2767 | case 'F': | ||
| 2768 | case 'f': | ||
| 2769 | process = true; | ||
| 2770 | break; | ||
| 2771 | default: | ||
| 2772 | if (!isalnum(*fmt)) { | ||
| 2773 | process = true; | ||
| 2774 | break; | ||
| 2775 | } | ||
| 2776 | /* Pointer dereference was already processed */ | ||
| 2777 | if (str < end) { | ||
| 2778 | len = copy = strlen(args); | ||
| 2779 | if (copy > end - str) | ||
| 2780 | copy = end - str; | ||
| 2781 | memcpy(str, args, copy); | ||
| 2782 | str += len; | ||
| 2783 | args += len; | ||
| 2784 | } | ||
| 2785 | } | ||
| 2786 | if (process) | ||
| 2787 | str = pointer(fmt, str, end, get_arg(void *), spec); | ||
| 2788 | |||
| 2734 | while (isalnum(*fmt)) | 2789 | while (isalnum(*fmt)) |
| 2735 | fmt++; | 2790 | fmt++; |
| 2736 | break; | 2791 | break; |
| 2792 | } | ||
| 2737 | 2793 | ||
| 2738 | case FORMAT_TYPE_PERCENT_CHAR: | 2794 | case FORMAT_TYPE_PERCENT_CHAR: |
| 2739 | if (str < end) | 2795 | if (str < end) |
