From 8589ed155da84245ac87cd59c4685f411e14c67f Mon Sep 17 00:00:00 2001 From: Xu Jun <693788454@qq.com> Date: Thu, 14 Apr 2022 14:02:19 +0800 Subject: [PATCH] Fix %ld specifier issue in libc-builtin printf wrapper (#1088) The format specifiers of %ld/%lu/%li/%lx/%lp/%lo (or %z* and %t* like) should be treated as 32-bit integer in wasm. And merge the handle of unsigned/signed for %u/%d and %llu/%lld specifier when calling snprintf. --- .../libc-builtin/libc_builtin_wrapper.c | 51 +++++++++---------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c b/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c index e4893239..cb42352d 100644 --- a/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c +++ b/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c @@ -125,7 +125,6 @@ _vprintf_wa(out_func_t out, void *ctx, const char *fmt, _va_list ap, int long_ctr = 0; uint8 *native_end_addr; const char *fmt_start_addr = NULL; - bool is_signed; if (!wasm_runtime_get_native_addr_range(module_inst, (uint8 *)ap, NULL, &native_end_addr)) @@ -142,7 +141,6 @@ _vprintf_wa(out_func_t out, void *ctx, const char *fmt, _va_list ap, might_format = 1; long_ctr = 0; fmt_start_addr = fmt; - is_signed = false; } } else { @@ -162,7 +160,11 @@ _vprintf_wa(out_func_t out, void *ctx, const char *fmt, _va_list ap, case '7': case '8': case '9': + goto still_might_format; + case 't': /* ptrdiff_t */ + case 'z': /* size_t (32bit on wasm) */ + long_ctr = 1; goto still_might_format; case 'j': @@ -173,7 +175,6 @@ _vprintf_wa(out_func_t out, void *ctx, const char *fmt, _va_list ap, case 'l': long_ctr++; /* Fall through */ - case 'z': case 'h': /* FIXME: do nothing for these modifiers */ goto still_might_format; @@ -181,8 +182,6 @@ _vprintf_wa(out_func_t out, void *ctx, const char *fmt, _va_list ap, case 'o': case 'd': case 'i': - is_signed = true; - /* Fall through */ case 'u': case 'p': case 'x': @@ -193,34 +192,34 @@ _vprintf_wa(out_func_t out, void *ctx, const char *fmt, _va_list ap, PREPARE_TEMP_FORMAT(); if (long_ctr < 2) { - CHECK_VA_ARG(ap, uint32); + int32 d; - if (is_signed) { - int32 d; - d = _va_arg(ap, int32); - n = snprintf(buf, sizeof(buf), fmt_buf, d); - } - else { - uint32 u; - u = _va_arg(ap, uint32); - n = snprintf(buf, sizeof(buf), fmt_buf, u); + CHECK_VA_ARG(ap, uint32); + d = _va_arg(ap, int32); + + if (long_ctr == 1) { + uint32 fmt_end_idx = fmt - fmt_start_addr; + + if (fmt_buf[fmt_end_idx - 1] == 'l' + || fmt_buf[fmt_end_idx - 1] == 'z' + || fmt_buf[fmt_end_idx - 1] == 't') { + /* The %ld, %zd and %td should be treated as + * 32bit integer in wasm */ + fmt_buf[fmt_end_idx - 1] = fmt_buf[fmt_end_idx]; + fmt_buf[fmt_end_idx] = '\0'; + } } + + n = snprintf(buf, sizeof(buf), fmt_buf, d); } else { + int64 lld; + /* Make 8-byte aligned */ ap = (_va_list)(((uintptr_t)ap + 7) & ~(uintptr_t)7); CHECK_VA_ARG(ap, uint64); - - if (is_signed) { - int64 lld; - lld = _va_arg(ap, int64); - n = snprintf(buf, sizeof(buf), fmt_buf, lld); - } - else { - uint64 llu; - llu = _va_arg(ap, uint64); - n = snprintf(buf, sizeof(buf), fmt_buf, llu); - } + lld = _va_arg(ap, int64); + n = snprintf(buf, sizeof(buf), fmt_buf, lld); } OUTPUT_TEMP_FORMAT();