aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/vsprintf.c82
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) \
2525do { \ 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)