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.
This commit is contained in:
Xu Jun 2022-04-14 14:02:19 +08:00 committed by GitHub
parent 87c67eb6f0
commit 8589ed155d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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();