|
|
Message-ID: <20260805141033.841558-4-matthias.goergens@gmail.com>
Date: Wed, 5 Aug 2026 22:10:26 +0800
From: Matthias Goergens <matthias.goergens@...il.com>
To: musl@...ts.openwall.com
Cc: Matthias Goergens <matthias.goergens@...il.com>
Subject: [PATCH 03/10] regression: test scanf field width overflow
Field widths through INT_MAX must reach normal conversion; larger
widths must be rejected as an invalid format instead of wrapping to
a small or negative value. The accumulation must not overflow even
intermediately, as it first did at the valid width 2147483600.
Covered by the musl patch "stdio: avoid field width overflow in
scanf".
---
src/regression/scanf-field-width-overflow.c | 59 +++++++++++++++++++++
1 file changed, 59 insertions(+)
create mode 100644 src/regression/scanf-field-width-overflow.c
diff --git a/src/regression/scanf-field-width-overflow.c b/src/regression/scanf-field-width-overflow.c
new file mode 100644
index 0000000..0e58757
--- /dev/null
+++ b/src/regression/scanf-field-width-overflow.c
@@ -0,0 +1,59 @@
+// scanf field widths were accumulated in int as 10*width + *p - '0',
+// which can overflow even when the final decimal value fits (first at
+// the valid width 2147483600, because the digit character is added
+// before '0' is subtracted). Widths through INT_MAX must be accepted;
+// larger widths must be rejected as an invalid format instead of
+// wrapping to a small or negative value.
+#include <limits.h>
+#include <stdio.h>
+#include <wchar.h>
+#include "test.h"
+
+struct narrow_case {
+ const char *format;
+ int expected;
+};
+
+struct wide_case {
+ const wchar_t *format;
+ int expected;
+};
+
+int main(void)
+{
+ char dummy;
+ static const struct narrow_case narrow[] = {
+ /* clean widths: reach normal conversion, input "x" matches once */
+ {"%*2147483599c", 0},
+ {"%*2147483600c", 0}, /* intermediate overflow boundary */
+ {"%*2147483647c", 0}, /* INT_MAX */
+ /* overlarge widths: invalid format, EOF, no input consumed */
+ {"%*2147483648c", EOF},
+ {"%*9999999999999999999999999999999999999999c", EOF},
+ };
+ static const struct wide_case wide[] = {
+ {L"%*2147483599c", 0},
+ {L"%*2147483600c", 0},
+ {L"%*2147483647c", 0},
+ {L"%*2147483648c", EOF},
+ {L"%*9999999999999999999999999999999999999999c", EOF},
+ };
+ size_t i;
+ int r;
+
+ for (i = 0; i < sizeof narrow / sizeof narrow[0]; i++) {
+ r = sscanf("x", narrow[i].format, &dummy);
+ if (r != narrow[i].expected)
+ t_error("sscanf(\"x\", \"%s\") = %d, want %d\n",
+ narrow[i].format, r, narrow[i].expected);
+ }
+ for (i = 0; i < sizeof wide / sizeof wide[0]; i++) {
+ r = swscanf(L"x", wide[i].format, &dummy);
+ if (r != wide[i].expected)
+ t_error("swscanf(L\"x\", L\"%ls\") = %d, want %d\n",
+ wide[i].format, r, wide[i].expected);
+ }
+ if (2147483647 != INT_MAX)
+ t_error("test assumes 32-bit int\n");
+ return t_status;
+}
--
2.55.0
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.