Эх сурвалжийг харах

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.
Xu Jun 3 жил өмнө
parent
commit
8589ed155d

+ 25 - 26
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();