about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2024-10-03 13:51:56 +0200
committerptitSeb <sebastien.chev@gmail.com>2024-10-03 13:51:56 +0200
commit0e91ad3ed3f2720b988d6aefec0d09b0cadf6dad (patch)
tree176891e2b25afc840ba0ba0ecb78e49f461da948 /src
parentc5e894aab2ef924f4f8c3d7a65932e2c68c3086c (diff)
downloadbox64-0e91ad3ed3f2720b988d6aefec0d09b0cadf6dad.tar.gz
box64-0e91ad3ed3f2720b988d6aefec0d09b0cadf6dad.zip
[BOX32] Fixed scanf type function when grabing long/ptr type of data
Diffstat (limited to 'src')
-rw-r--r--src/emu/x64emu_private.h4
-rwxr-xr-xsrc/include/myalign32.h6
-rwxr-xr-xsrc/libtools/myalign32.c316
-rwxr-xr-xsrc/wrapped32/wrappedlibc.c18
4 files changed, 323 insertions, 21 deletions
diff --git a/src/emu/x64emu_private.h b/src/emu/x64emu_private.h
index 6b6c75e7..0c02f5ed 100644
--- a/src/emu/x64emu_private.h
+++ b/src/emu/x64emu_private.h
@@ -58,6 +58,8 @@ typedef struct emu_flags_s {
 #define JUMPBUFF struct __jmp_buf_tag
 #endif
 
+#define N_SCRATCH 200
+
 typedef struct x64emu_s {
     // cpu
     reg64_t     regs[16];
@@ -119,7 +121,7 @@ typedef struct x64emu_s {
     #endif
     // scratch stack, used for alignment of double and 64bits ints on arm. 200 elements should be enough
     __int128_t  dummy_align;    // here to have scratch 128bits aligned
-    uint64_t    scratch[200];
+    uint64_t    scratch[N_SCRATCH];
     // local stack, do be deleted when emu is freed
     void*       stack2free; // this is the stack to free (can be NULL)
     void*       init_stack; // initial stack (owned or not)
diff --git a/src/include/myalign32.h b/src/include/myalign32.h
index bf382c65..57ae0194 100755
--- a/src/include/myalign32.h
+++ b/src/include/myalign32.h
@@ -77,9 +77,11 @@ typedef struct  va_list {
 #define PREPARE_VALIST_32_(A) CREATE_SYSV_VALIST_32(A)
 
 void myStackAlign32(const char* fmt, uint32_t* st, uint64_t* mystack);
-void myStackAlignScanf32(const char* fmt, uint32_t* st, uint64_t* mystack);
+size_t myStackAlignScanf32(const char* fmt, uint32_t* st, uint64_t* mystack, size_t nb_elem); // return the number of long/ptr_t conversion pending
+void myStackAlignScanf32_final(const char* fmt, uint32_t* st, uint64_t* mystack, size_t nb_elem, int n); // convert the long/ptr_t scanf results
 void myStackAlignGVariantNew32(const char* fmt, uint32_t* st, uint64_t* mystack);
-void myStackAlignScanfW32(const char* fmt, uint32_t* st, uint64_t* mystack);
+size_t myStackAlignScanfW32(const char* fmt, uint32_t* st, uint64_t* mystack, size_t nb_elem);
+void myStackAlignScanfW32_final(const char* fmt, uint32_t* st, uint64_t* mystack, size_t nb_elem, int n);
 void myStackAlignW32(const char* fmt, uint32_t* st, uint64_t* mystack);
 
 void UnalignStat64_32(const void* source, void* dest);
diff --git a/src/libtools/myalign32.c b/src/libtools/myalign32.c
index 47aa3ff3..83a4fbdd 100755
--- a/src/libtools/myalign32.c
+++ b/src/libtools/myalign32.c
@@ -139,13 +139,14 @@ void myStackAlign32(const char* fmt, uint32_t* st, uint64_t* mystack)
     }
 }
 
-void myStackAlignScanf32(const char* fmt, uint32_t* st, uint64_t* mystack)
+size_t myStackAlignScanf32(const char* fmt, uint32_t* st, uint64_t* mystack, size_t nb_elem)
 {
     
     if(!fmt)
-        return;
+        return 0;
     // loop...
     const char* p = fmt;
+    size_t conv = 0;
     int state = 0;
     int ign = 0;
     while(*p)
@@ -179,10 +180,10 @@ void myStackAlignScanf32(const char* fmt, uint32_t* st, uint64_t* mystack)
                     case 'f': state += 10; break;    //  float
                     case 'd':
                     case 'i':
-                    case 'o':
+                    case 'o': state += 20; break;   // int
                     case 'u':
                     case 'x':
-                    case 'X': state += 20; break;   // int
+                    case 'X': state += 40; break;   // usigned int
                     case 'h': ++p; break;  // ignored...
                     case '\'':
                     case '0':
@@ -211,6 +212,22 @@ void myStackAlignScanf32(const char* fmt, uint32_t* st, uint64_t* mystack)
                         state=20; // other stuff, put an int...
                 }
                 break;
+            case 22:    // long uint
+            case 25:    // size_t int
+            case 42:    // long uint
+            case 45:
+            case 30:    // pointer
+                if(!ign) {
+                    ++conv;
+                    mystack[nb_elem-conv] = 0;
+                    *mystack = (uintptr_t)&mystack[nb_elem-conv];
+                    ++st;
+                    ++mystack;
+                }
+                state = 0;
+                ++p;
+                break;
+            
             case 11:    //double
             case 12:    //%lg, still double
             case 13:    //%llg, still double
@@ -218,11 +235,139 @@ void myStackAlignScanf32(const char* fmt, uint32_t* st, uint64_t* mystack)
             case 15:    //%zg
             case 20:    // fallback
             case 21:
-            case 22:
             case 23:    // 64bits int
             case 24:    // normal int / pointer
+            case 40:
+            case 41:
+            case 43:
+            case 44:
+                if(!ign) {
+                    *mystack = *st;
+                    ++st;
+                    ++mystack;
+                }
+                state = 0;
+                ++p;
+                break;
+            default:
+                // whaaaat?
+                state = 0;
+        }
+    }
+    return conv;
+}
+
+void myStackAlignScanf32_final(const char* fmt, uint32_t* st, uint64_t* mystack, size_t nb_elem, int n)
+{
+    
+    if(!fmt || n<=0)
+        return;
+    // loop...
+    const char* p = fmt;
+    size_t conv = 0;
+    int state = 0;
+    int ign = 0;
+    while(*p)
+    {
+        switch(state) {
+            case 0:
+                ign = 0;
+                switch(*p) {
+                    case '%': state = 1; ++p; break;
+                    default:
+                        ++p;
+                }
+                break;
+            case 1: // normal
+            case 2: // l
+            case 3: // ll
+            case 4: // L
+            case 5: // z
+                switch(*p) {
+                    case '%': state = 0;  ++p; break; //%% = back to 0
+                    case 'l': ++state; if (state>3) state=3; ++p; break;
+                    case 'L': state = 4; ++p; break;
+                    case 'z': state = 5; ++p; break;
+                    case 'a':
+                    case 'A':
+                    case 'e':
+                    case 'E':
+                    case 'g':
+                    case 'G':
+                    case 'F':
+                    case 'f': state += 10; break;    //  float
+                    case 'd':
+                    case 'i':
+                    case 'o': state += 20; break;   // int
+                    case 'u':
+                    case 'x':
+                    case 'X': state += 40; break;   // usigned int
+                    case 'h': ++p; break;  // ignored...
+                    case '\'':
+                    case '0':
+                    case '1':
+                    case '2':
+                    case '3':
+                    case '4':
+                    case '5':
+                    case '6':
+                    case '7':
+                    case '8':
+                    case '9':
+                    case '.': 
+                    case '#':
+                    case '+': 
+                    case '-': ++p; break; // formating, ignored
+                    case 'm': state = 0; ++p; break; // no argument
+                    case 'n':
+                    case 'p':
+                    case 'S':
+                    case 's': state = 30; break; // pointers
+                    case '$': ++p; break; // should issue a warning, it's not handled...
+                    case '*': ign=1; ++p; break; // ignore arg
+                    case ' ': state=0; ++p; break;
+                    default:
+                        state=20; // other stuff, put an int...
+                }
+                break;
+            case 22:    // long int
             case 25:    // size_t int
-            case 30:
+            case 42:    // long uint
+            case 45:
+            case 30:    // pointer
+                if(!ign) {
+                    ++conv;
+                    if(state==22 || state==0x25) {
+                        int32_t* dst = from_ptrv(*st);
+                        *dst = to_long(mystack[nb_elem-conv]);
+                    } else if(state==30) {
+                        ptr_t* dst = from_ptrv(*st);
+                        *dst = to_ptr(mystack[nb_elem-conv]);
+                    } else {
+                        uint32_t* dst = from_ptrv(*st);
+                        *dst = to_ulong(mystack[nb_elem-conv]);
+                    }
+                    ++st;
+                    ++mystack;
+                }
+                state = 0;
+                ++p;
+                if(!--n) return;
+                break;
+            
+            case 11:    //double
+            case 12:    //%lg, still double
+            case 13:    //%llg, still double
+            case 14:    //%Lg long double
+            case 15:    //%zg
+            case 20:    // fallback
+            case 21:
+            case 23:    // 64bits int
+            case 24:    // normal int / pointer
+            case 40:
+            case 41:
+            case 43:
+            case 44:
                 if(!ign) {
                     *mystack = *st;
                     ++st;
@@ -230,6 +375,7 @@ void myStackAlignScanf32(const char* fmt, uint32_t* st, uint64_t* mystack)
                 }
                 state = 0;
                 ++p;
+                if(!--n) return;
                 break;
             default:
                 // whaaaat?
@@ -238,14 +384,15 @@ void myStackAlignScanf32(const char* fmt, uint32_t* st, uint64_t* mystack)
     }
 }
 
-void myStackAlignScanfW32(const char* fmt, uint32_t* st, uint64_t* mystack)
+size_t myStackAlignScanfW32(const char* fmt, uint32_t* st, uint64_t* mystack, size_t nb_elem)
 {
     
     if(!fmt)
-        return;
+        return 0;
     // loop...
     const wchar_t* p = (const wchar_t*)fmt;
     int state = 0;
+    size_t conv = 0;
     int ign = 0;
     while(*p)
     {
@@ -278,10 +425,10 @@ void myStackAlignScanfW32(const char* fmt, uint32_t* st, uint64_t* mystack)
                     case 'f': state += 10; break;    //  float
                     case 'd':
                     case 'i':
-                    case 'o':
+                    case 'o': state += 20; break;   // int
                     case 'u':
                     case 'x':
-                    case 'X': state += 20; break;   // int
+                    case 'X': state += 40; break;   // usigned int
                     case 'h': ++p; break;  // ignored...
                     case '\'':
                     case '0':
@@ -310,6 +457,22 @@ void myStackAlignScanfW32(const char* fmt, uint32_t* st, uint64_t* mystack)
                         state=20; // other stuff, put an int...
                 }
                 break;
+            case 22:    // long uint
+            case 25:    // size_t int
+            case 42:    // long uint
+            case 45:
+            case 30:    // pointer
+                if(!ign) {
+                    ++conv;
+                    mystack[nb_elem-conv] = 0;
+                    *mystack = (uintptr_t)&mystack[nb_elem-conv];
+                    ++st;
+                    ++mystack;
+                }
+                state = 0;
+                ++p;
+                break;
+            
             case 11:    //double
             case 12:    //%lg, still double
             case 13:    //%llg, still double
@@ -317,11 +480,139 @@ void myStackAlignScanfW32(const char* fmt, uint32_t* st, uint64_t* mystack)
             case 15:    //%zg
             case 20:    // fallback
             case 21:
-            case 22:
             case 23:    // 64bits int
             case 24:    // normal int / pointer
+            case 40:
+            case 41:
+            case 43:
+            case 44:
+                if(!ign) {
+                    *mystack = *st;
+                    ++st;
+                    ++mystack;
+                }
+                state = 0;
+                ++p;
+                break;
+            default:
+                // whaaaat?
+                state = 0;
+        }
+    }
+    return conv;
+}
+
+void myStackAlignScanfW32_final(const char* fmt, uint32_t* st, uint64_t* mystack, size_t nb_elem, int n)
+{
+    
+    if(!fmt || n<=0)
+        return;
+    // loop...
+    const wchar_t* p = (const wchar_t*)fmt;
+    int state = 0;
+    size_t conv = 0;
+    int ign = 0;
+    while(*p)
+    {
+        switch(state) {
+            case 0:
+                ign = 0;
+                switch(*p) {
+                    case '%': state = 1; ++p; break;
+                    default:
+                        ++p;
+                }
+                break;
+            case 1: // normal
+            case 2: // l
+            case 3: // ll
+            case 4: // L
+            case 5: // z
+                switch(*p) {
+                    case '%': state = 0;  ++p; break; //%% = back to 0
+                    case 'l': ++state; if (state>3) state=3; ++p; break;
+                    case 'L': state = 4; ++p; break;
+                    case 'z': state = 5; ++p; break;
+                    case 'a':
+                    case 'A':
+                    case 'e':
+                    case 'E':
+                    case 'g':
+                    case 'G':
+                    case 'F':
+                    case 'f': state += 10; break;    //  float
+                    case 'd':
+                    case 'i':
+                    case 'o': state += 20; break;   // int
+                    case 'u':
+                    case 'x':
+                    case 'X': state += 40; break;   // usigned int
+                    case 'h': ++p; break;  // ignored...
+                    case '\'':
+                    case '0':
+                    case '1':
+                    case '2':
+                    case '3':
+                    case '4':
+                    case '5':
+                    case '6':
+                    case '7':
+                    case '8':
+                    case '9':
+                    case '.': 
+                    case '#':
+                    case '+': 
+                    case '-': ++p; break; // formating, ignored
+                    case 'm': state = 0; ++p; break; // no argument
+                    case 'n':
+                    case 'p':
+                    case 'S':
+                    case 's': state = 30; break; // pointers
+                    case '$': ++p; break; // should issue a warning, it's not handled...
+                    case '*': ign=1; ++p; break; // ignore arg
+                    case ' ': state=0; ++p; break;
+                    default:
+                        state=20; // other stuff, put an int...
+                }
+                break;
+            case 22:    // long uint
             case 25:    // size_t int
-            case 30:
+            case 42:    // long uint
+            case 45:
+            case 30:    // pointer
+                if(!ign) {
+                    ++conv;
+                    if(state==22 || state==0x25) {
+                        int32_t* dst = from_ptrv(*st);
+                        *dst = to_long(mystack[nb_elem-conv]);
+                    } else if(state==30) {
+                        ptr_t* dst = from_ptrv(*st);
+                        *dst = to_ptr(mystack[nb_elem-conv]);
+                    } else {
+                        uint32_t* dst = from_ptrv(*st);
+                        *dst = to_ulong(mystack[nb_elem-conv]);
+                    }
+                    ++st;
+                    ++mystack;
+                }
+                state = 0;
+                ++p;
+                if(!--n) return;
+                break;
+            
+            case 11:    //double
+            case 12:    //%lg, still double
+            case 13:    //%llg, still double
+            case 14:    //%Lg long double
+            case 15:    //%zg
+            case 20:    // fallback
+            case 21:
+            case 23:    // 64bits int
+            case 24:    // normal int / pointer
+            case 40:
+            case 41:
+            case 43:
+            case 44:
                 if(!ign) {
                     *mystack = *st;
                     ++st;
@@ -329,6 +620,7 @@ void myStackAlignScanfW32(const char* fmt, uint32_t* st, uint64_t* mystack)
                 }
                 state = 0;
                 ++p;
+                if(!--n) return;
                 break;
             default:
                 // whaaaat?
diff --git a/src/wrapped32/wrappedlibc.c b/src/wrapped32/wrappedlibc.c
index 7552d31c..9d7c31c0 100755
--- a/src/wrapped32/wrappedlibc.c
+++ b/src/wrapped32/wrappedlibc.c
@@ -856,9 +856,11 @@ EXPORT int my32___vsprintf_chk(x64emu_t* emu, void* buff, int flags, size_t len,
 
 EXPORT int my32_vfscanf(x64emu_t* emu, void* stream, void* fmt, void* b) // probably uneeded to do a GOM, a simple wrap should enough
 {
-    myStackAlignScanf32((const char*)fmt, (uint32_t*)b, emu->scratch);
+    int n = myStackAlignScanf32((const char*)fmt, (uint32_t*)b, emu->scratch, N_SCRATCH);
     PREPARE_VALIST_32;
-    return vfscanf(stream, fmt, VARARGS_32);
+    int ret = vfscanf(stream, fmt, VARARGS_32);
+    if(n) myStackAlignScanf32_final((const char*)fmt, (uint32_t*)b, emu->scratch, N_SCRATCH, ret);
+    return ret;
 }
 EXPORT int my32__IO_vfscanf(x64emu_t* emu, void* stream, void* fmt, void* b) __attribute__((alias("my32_vfscanf")));
 EXPORT int my32___isoc99_vfscanf(x64emu_t* emu, void* stream, void* fmt, void* b) __attribute__((alias("my32_vfscanf")));
@@ -867,9 +869,11 @@ EXPORT int my32_fscanf(x64emu_t* emu, void* stream, void* fmt, void* b) __attrib
 
 EXPORT int my32_vsscanf(x64emu_t* emu, void* buff, void* fmt, void* b)
 {
-    myStackAlignScanf32((const char*)fmt, (uint32_t*)b, emu->scratch);
+    int n = myStackAlignScanf32((const char*)fmt, (uint32_t*)b, emu->scratch, N_SCRATCH);
     PREPARE_VALIST_32;
-    return vsscanf(buff, fmt, VARARGS_32);
+    int ret = vsscanf(buff, fmt, VARARGS_32);
+    if(ret>0) myStackAlignScanf32_final((const char*)fmt, (uint32_t*)b, emu->scratch, N_SCRATCH, ret);
+    return ret;
 }
 EXPORT int my32___isoc99_vsscanf(x64emu_t* emu, void* stream, void* fmt, void* b) __attribute__((alias("my32_vsscanf")));
 EXPORT int my32__vsscanf(x64emu_t* emu, void* buff, void* fmt, void* b) __attribute__((alias("my32_vsscanf")));
@@ -933,9 +937,11 @@ EXPORT int my32___vswprintf_chk(x64emu_t* emu, void* buff, size_t s, int flags,
 
 EXPORT int my32_vswscanf(x64emu_t* emu, void* buff, void* fmt, void* b)
 {
-    myStackAlignScanfW32((const char*)fmt, (uint32_t*)b, emu->scratch);
+    int n = myStackAlignScanfW32((const char*)fmt, (uint32_t*)b, emu->scratch, N_SCRATCH);
     PREPARE_VALIST_32;
-    vswscanf(buff, fmt, VARARGS_32);
+    int ret = vswscanf(buff, fmt, VARARGS_32);
+    if(n) myStackAlignScanfW32_final((const char*)fmt, (uint32_t*)b, emu->scratch, N_SCRATCH, ret);
+    return ret;
 }
 
 EXPORT int my32__vswscanf(x64emu_t* emu, void* buff, void* fmt, void* b) __attribute__((alias("my32_vswscanf")));