On Sun, 6 Feb 2022, Pali Rohár wrote:

Currently v*scanf functions are broken and crash when are called with more
than 30 arguments in va_list. This is because va_list v*scanf functions are
redirected to variadic *scanf functions and this redirect implemented in
scanf.S file has fixed limit for 30 arguments.

Number of arguments for msvcrt *scanf function can be determined from
format string by counting number of '%' characters which is the upper
limit. *scanf functions would not access more arguments than this number.
Every scanf parameter is pointer, it has fixed size and so upper stack size
limit can be exactly calculated.

Fix this scanf.S redirect implementation by dynamically allocating stack
for upper limit of pointer parameters.

---

I have tested this patch for i686 and x86_64. Both ARM (arm32 and aarch64)
changes are untested, so please test it if vsscanf() on these platforms
still works.

I wonder if we should try to keep the stack 16 byte aligned for i686 too - GCC generally tries to keep such alignment on i686 too (even if it isn't strictly required by the ABI). Then again, the only function we call there is the msvcrt.dll function, which shouldn't assume anything else than 4 byte alignment, so maybe it's fine.

I noticed that the arm version that I provided before did crash if providing less than 2 '%' conversions. I simplified the arm and aarch64 versions a little and fixed that, see the attached patch that goes on top of this. (I can squash it locally before pushing the patch too, sparing you a re-send of the patch, if we decide we don't want to tweak anything else.)

// Martin
From 74eaeb43a11365c2ac2ac175b420b9ec26a09596 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <mar...@martin.st>
Date: Tue, 8 Feb 2022 11:19:40 +0200
Subject: [PATCH] Further tweaks for scanf.S for arm

---
 mingw-w64-crt/stdio/scanf.S | 33 +++++++--------------------------
 1 file changed, 7 insertions(+), 26 deletions(-)

diff --git a/mingw-w64-crt/stdio/scanf.S b/mingw-w64-crt/stdio/scanf.S
index 323a8d5a8..41ff64598 100644
--- a/mingw-w64-crt/stdio/scanf.S
+++ b/mingw-w64-crt/stdio/scanf.S
@@ -172,14 +172,12 @@ __argtos:
     push    {r4-r8, lr}
     ldr     r12, [sp, #24]
 
-    cmp     r3, #0
-    beq     2f
-    subs    r3, r3, #1
     ldr     r5, [r2], #4
-    beq     2f
-    subs    r3, r3, #1
     ldr     r6, [r2], #4
-    beq     2f
+
+    subs    r3, r3, #2
+    mov     r8, #0
+    ble     2f
 
     /* Round the number of entries to an even number, to maintain
      * 8 byte stack alignment. */
@@ -214,32 +212,15 @@ __argtos:
     mov     x11, x3
     mov     x12, x4
 
-    cmp     x11, #0
-    b.eq    2f
-
-    subs    x11, x11, #1
     ldr     x2, [x10], #8
-    b.eq    2f
-
-    subs    x11, x11, #1
     ldr     x3, [x10], #8
-    b.eq    2f
-
-    subs    x11, x11, #1
     ldr     x4, [x10], #8
-    b.eq    2f
-
-    subs    x11, x11, #1
     ldr     x5, [x10], #8
-    b.eq    2f
-
-    subs    x11, x11, #1
     ldr     x6, [x10], #8
-    b.eq    2f
-
-    subs    x11, x11, #1
     ldr     x7, [x10], #8
-    b.eq    2f
+
+    subs    x11, x11, #6
+    b.le    2f
 
     /* Round the number of entries to an even number, to maintain
      * 16 byte stack alignment. */
-- 
2.25.1

_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to