The branch main has been updated by des:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=b9385720f34b536ef2568a642e8b1fad0450056f

commit b9385720f34b536ef2568a642e8b1fad0450056f
Author:     Dag-Erling Smørgrav <d...@freebsd.org>
AuthorDate: 2023-08-28 15:34:05 +0000
Commit:     Dag-Erling Smørgrav <d...@freebsd.org>
CommitDate: 2023-08-28 15:34:05 +0000

    libc: Add unit tests for N2630 and possible collateral damage.
    
    Reviewed by:    imp, emaste
    Differential Revision:  https://reviews.freebsd.org/D41512
---
 contrib/netbsd-tests/lib/libc/stdlib/t_strtol.c |   6 +
 lib/libc/tests/stdio/Makefile                   |   3 +
 lib/libc/tests/stdio/snprintf_test.c            | 138 +++++++++++++
 lib/libc/tests/stdio/sscanf_test.c              | 249 +++++++++++++++++++++++
 lib/libc/tests/stdio/swscanf_test.c             | 250 ++++++++++++++++++++++++
 5 files changed, 646 insertions(+)

diff --git a/contrib/netbsd-tests/lib/libc/stdlib/t_strtol.c 
b/contrib/netbsd-tests/lib/libc/stdlib/t_strtol.c
index 54e190760656..d1027fcc7bb1 100644
--- a/contrib/netbsd-tests/lib/libc/stdlib/t_strtol.c
+++ b/contrib/netbsd-tests/lib/libc/stdlib/t_strtol.c
@@ -94,6 +94,12 @@ ATF_TC_BODY(strtol_base, tc)
                { "01234567",                       342391,  0, NULL    },
                { "0123456789",                  123456789, 10, NULL    },
                { "0x75bcd15",                   123456789,  0, NULL    },
+#ifdef __FreeBSD__
+               { "0x",                                  0,  0, "x"     },
+               { "0b111010110111100110100010101", 123456789,  0, NULL  },
+               { "0b0123",                              1,  0, "23"    },
+               { "0b",                                  0,  0, "b"     },
+#endif
        };
 
        long long int lli;
diff --git a/lib/libc/tests/stdio/Makefile b/lib/libc/tests/stdio/Makefile
index 12ae44855da5..f7383e5b3ef4 100644
--- a/lib/libc/tests/stdio/Makefile
+++ b/lib/libc/tests/stdio/Makefile
@@ -16,6 +16,9 @@ ATF_TESTS_C+=         print_positional_test
 ATF_TESTS_C+=          printbasic_test
 ATF_TESTS_C+=          printfloat_test
 ATF_TESTS_C+=          scanfloat_test
+ATF_TESTS_C+=          snprintf_test
+ATF_TESTS_C+=          sscanf_test
+ATF_TESTS_C+=          swscanf_test
 
 SRCS.fopen2_test=      fopen_test.c
 
diff --git a/lib/libc/tests/stdio/snprintf_test.c 
b/lib/libc/tests/stdio/snprintf_test.c
new file mode 100644
index 000000000000..0c335bc1a512
--- /dev/null
+++ b/lib/libc/tests/stdio/snprintf_test.c
@@ -0,0 +1,138 @@
+/*-
+ * Copyright (c) 2023 Dag-Erling Smørgrav
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <assert.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include <atf-c.h>
+
+#define SNPRINTF_TEST(output, format, ...) \
+       do {                                                            \
+               char buf[256];                                          \
+               assert(output == NULL || strlen(output) < sizeof(buf)); \
+               int ret = snprintf(buf, sizeof(buf), format, __VA_ARGS__); \
+               if (output == NULL) {                                   \
+                       ATF_CHECK_EQ(-1, ret);                          \
+               } else {                                                \
+                       ATF_CHECK_EQ(strlen(output), ret);              \
+                       if (ret > 0) {                                  \
+                               ATF_CHECK_STREQ(output, buf);           \
+                       }                                               \
+               }                                                       \
+       } while (0)
+
+ATF_TC_WITHOUT_HEAD(snprintf_b);
+ATF_TC_BODY(snprintf_b, tc)
+{
+       SNPRINTF_TEST("0", "%b", 0);
+       SNPRINTF_TEST("           0", "%12b", 0);
+       SNPRINTF_TEST("000000000000", "%012b", 0);
+       SNPRINTF_TEST("1", "%b", 1);
+       SNPRINTF_TEST("           1", "%12b", 1);
+       SNPRINTF_TEST("000000000001", "%012b", 1);
+       SNPRINTF_TEST("1111111111111111111111111111111", "%b", INT_MAX);
+       SNPRINTF_TEST("0", "%#b", 0);
+       SNPRINTF_TEST("           0", "%#12b", 0);
+       SNPRINTF_TEST("000000000000", "%#012b", 0);
+       SNPRINTF_TEST("0b1", "%#b", 1);
+       SNPRINTF_TEST("         0b1", "%#12b", 1);
+       SNPRINTF_TEST("0b0000000001", "%#012b", 1);
+       SNPRINTF_TEST("0b1111111111111111111111111111111", "%#b", INT_MAX);
+}
+
+ATF_TC_WITHOUT_HEAD(snprintf_B);
+ATF_TC_BODY(snprintf_B, tc)
+{
+       SNPRINTF_TEST("0", "%B", 0);
+       SNPRINTF_TEST("           0", "%12B", 0);
+       SNPRINTF_TEST("000000000000", "%012B", 0);
+       SNPRINTF_TEST("1", "%B", 1);
+       SNPRINTF_TEST("           1", "%12B", 1);
+       SNPRINTF_TEST("000000000001", "%012B", 1);
+       SNPRINTF_TEST("1111111111111111111111111111111", "%B", INT_MAX);
+       SNPRINTF_TEST("0", "%#B", 0);
+       SNPRINTF_TEST("           0", "%#12B", 0);
+       SNPRINTF_TEST("000000000000", "%#012B", 0);
+       SNPRINTF_TEST("0B1", "%#B", 1);
+       SNPRINTF_TEST("         0B1", "%#12B", 1);
+       SNPRINTF_TEST("0B0000000001", "%#012B", 1);
+       SNPRINTF_TEST("0B1111111111111111111111111111111", "%#B", INT_MAX);
+}
+
+ATF_TC_WITHOUT_HEAD(snprintf_d);
+ATF_TC_BODY(snprintf_d, tc)
+{
+       SNPRINTF_TEST("0", "%d", 0);
+       SNPRINTF_TEST("           0", "%12d", 0);
+       SNPRINTF_TEST("000000000000", "%012d", 0);
+       SNPRINTF_TEST("1", "%d", 1);
+       SNPRINTF_TEST("           1", "%12d", 1);
+       SNPRINTF_TEST("000000000001", "%012d", 1);
+       SNPRINTF_TEST("2147483647", "%d", INT_MAX);
+       SNPRINTF_TEST("  2147483647", "%12d", INT_MAX);
+       SNPRINTF_TEST("002147483647", "%012d", INT_MAX);
+       SNPRINTF_TEST("2,147,483,647", "%'d", INT_MAX);
+}
+
+ATF_TC_WITHOUT_HEAD(snprintf_x);
+ATF_TC_BODY(snprintf_x, tc)
+{
+       SNPRINTF_TEST("0", "%x", 0);
+       SNPRINTF_TEST("           0", "%12x", 0);
+       SNPRINTF_TEST("000000000000", "%012x", 0);
+       SNPRINTF_TEST("1", "%x", 1);
+       SNPRINTF_TEST("           1", "%12x", 1);
+       SNPRINTF_TEST("000000000001", "%012x", 1);
+       SNPRINTF_TEST("7fffffff", "%x", INT_MAX);
+       SNPRINTF_TEST("    7fffffff", "%12x", INT_MAX);
+       SNPRINTF_TEST("00007fffffff", "%012x", INT_MAX);
+       SNPRINTF_TEST("0", "%#x", 0);
+       SNPRINTF_TEST("           0", "%#12x", 0);
+       SNPRINTF_TEST("000000000000", "%#012x", 0);
+       SNPRINTF_TEST("0x1", "%#x", 1);
+       SNPRINTF_TEST("         0x1", "%#12x", 1);
+       SNPRINTF_TEST("0x0000000001", "%#012x", 1);
+       SNPRINTF_TEST("0x7fffffff", "%#x", INT_MAX);
+       SNPRINTF_TEST("  0x7fffffff", "%#12x", INT_MAX);
+       SNPRINTF_TEST("0x007fffffff", "%#012x", INT_MAX);
+}
+
+ATF_TC_WITHOUT_HEAD(snprintf_X);
+ATF_TC_BODY(snprintf_X, tc)
+{
+       SNPRINTF_TEST("0", "%X", 0);
+       SNPRINTF_TEST("           0", "%12X", 0);
+       SNPRINTF_TEST("000000000000", "%012X", 0);
+       SNPRINTF_TEST("1", "%X", 1);
+       SNPRINTF_TEST("           1", "%12X", 1);
+       SNPRINTF_TEST("000000000001", "%012X", 1);
+       SNPRINTF_TEST("7FFFFFFF", "%X", INT_MAX);
+       SNPRINTF_TEST("    7FFFFFFF", "%12X", INT_MAX);
+       SNPRINTF_TEST("00007FFFFFFF", "%012X", INT_MAX);
+       SNPRINTF_TEST("0", "%#X", 0);
+       SNPRINTF_TEST("           0", "%#12X", 0);
+       SNPRINTF_TEST("000000000000", "%#012X", 0);
+       SNPRINTF_TEST("0X1", "%#X", 1);
+       SNPRINTF_TEST("         0X1", "%#12X", 1);
+       SNPRINTF_TEST("0X0000000001", "%#012X", 1);
+       SNPRINTF_TEST("0X7FFFFFFF", "%#X", INT_MAX);
+       SNPRINTF_TEST("  0X7FFFFFFF", "%#12X", INT_MAX);
+       SNPRINTF_TEST("0X007FFFFFFF", "%#012X", INT_MAX);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+       setlocale(LC_NUMERIC, "en_US.UTF-8");
+       ATF_TP_ADD_TC(tp, snprintf_b);
+       ATF_TP_ADD_TC(tp, snprintf_B);
+       ATF_TP_ADD_TC(tp, snprintf_d);
+       ATF_TP_ADD_TC(tp, snprintf_x);
+       ATF_TP_ADD_TC(tp, snprintf_X);
+       return (atf_no_error());
+}
diff --git a/lib/libc/tests/stdio/sscanf_test.c 
b/lib/libc/tests/stdio/sscanf_test.c
new file mode 100644
index 000000000000..24226f3b3a8d
--- /dev/null
+++ b/lib/libc/tests/stdio/sscanf_test.c
@@ -0,0 +1,249 @@
+/*-
+ * Copyright (c) 2023 Dag-Erling Smørgrav
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <locale.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include <atf-c.h>
+
+static const struct sscanf_test_case {
+       char input[8];
+       struct {
+               int ret, val, len;
+       } b, o, d, x, i;
+} sscanf_test_cases[] = {
+//     input           binary          octal           decimal         
hexadecimal     automatic
+       // all digits
+       { "0",          { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
0, 1 },  { 1,   0, 1 }, },
+       { "1",          { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,   
1, 1 },  { 1,   1, 1 }, },
+       { "2",          { 0,   0, 0 },  { 1,   2, 1 },  { 1,   2, 1 },  { 1,   
2, 1 },  { 1,   2, 1 }, },
+       { "3",          { 0,   0, 0 },  { 1,   3, 1 },  { 1,   3, 1 },  { 1,   
3, 1 },  { 1,   3, 1 }, },
+       { "4",          { 0,   0, 0 },  { 1,   4, 1 },  { 1,   4, 1 },  { 1,   
4, 1 },  { 1,   4, 1 }, },
+       { "5",          { 0,   0, 0 },  { 1,   5, 1 },  { 1,   5, 1 },  { 1,   
5, 1 },  { 1,   5, 1 }, },
+       { "6",          { 0,   0, 0 },  { 1,   6, 1 },  { 1,   6, 1 },  { 1,   
6, 1 },  { 1,   6, 1 }, },
+       { "7",          { 0,   0, 0 },  { 1,   7, 1 },  { 1,   7, 1 },  { 1,   
7, 1 },  { 1,   7, 1 }, },
+       { "8",          { 0,   0, 0 },  { 0,   0, 0 },  { 1,   8, 1 },  { 1,   
8, 1 },  { 1,   8, 1 }, },
+       { "9",          { 0,   0, 0 },  { 0,   0, 0 },  { 1,   9, 1 },  { 1,   
9, 1 },  { 1,   9, 1 }, },
+       { "A",          { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 1,  
10, 1 },  { 0,   0, 0 }, },
+       { "B",          { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 1,  
11, 1 },  { 0,   0, 0 }, },
+       { "C",          { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 1,  
12, 1 },  { 0,   0, 0 }, },
+       { "D",          { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 1,  
13, 1 },  { 0,   0, 0 }, },
+       { "E",          { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 1,  
14, 1 },  { 0,   0, 0 }, },
+       { "F",          { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 1,  
15, 1 },  { 0,   0, 0 }, },
+       { "X",          { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 0,   
0, 0 },  { 0,   0, 0 }, },
+       { "a",          { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 1,  
10, 1 },  { 0,   0, 0 }, },
+       { "b",          { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 1,  
11, 1 },  { 0,   0, 0 }, },
+       { "c",          { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 1,  
12, 1 },  { 0,   0, 0 }, },
+       { "d",          { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 1,  
13, 1 },  { 0,   0, 0 }, },
+       { "e",          { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 1,  
14, 1 },  { 0,   0, 0 }, },
+       { "f",          { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 1,  
15, 1 },  { 0,   0, 0 }, },
+       { "x",          { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 0,   
0, 0 },  { 0,   0, 0 }, },
+       // all digits with leading zero
+       { "00",         { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,   
0, 2 },  { 1,   0, 2 }, },
+       { "01",         { 1,   1, 2 },  { 1,   1, 2 },  { 1,   1, 2 },  { 1,   
1, 2 },  { 1,   1, 2 }, },
+       { "02",         { 1,   0, 1 },  { 1,   2, 2 },  { 1,   2, 2 },  { 1,   
2, 2 },  { 1,   2, 2 }, },
+       { "03",         { 1,   0, 1 },  { 1,   3, 2 },  { 1,   3, 2 },  { 1,   
3, 2 },  { 1,   3, 2 }, },
+       { "04",         { 1,   0, 1 },  { 1,   4, 2 },  { 1,   4, 2 },  { 1,   
4, 2 },  { 1,   4, 2 }, },
+       { "05",         { 1,   0, 1 },  { 1,   5, 2 },  { 1,   5, 2 },  { 1,   
5, 2 },  { 1,   5, 2 }, },
+       { "06",         { 1,   0, 1 },  { 1,   6, 2 },  { 1,   6, 2 },  { 1,   
6, 2 },  { 1,   6, 2 }, },
+       { "07",         { 1,   0, 1 },  { 1,   7, 2 },  { 1,   7, 2 },  { 1,   
7, 2 },  { 1,   7, 2 }, },
+       { "08",         { 1,   0, 1 },  { 1,   0, 1 },  { 1,   8, 2 },  { 1,   
8, 2 },  { 1,   0, 1 }, },
+       { "09",         { 1,   0, 1 },  { 1,   0, 1 },  { 1,   9, 2 },  { 1,   
9, 2 },  { 1,   0, 1 }, },
+       { "0A",         { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
10, 2 },  { 1,   0, 1 }, },
+       { "0B",         { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
11, 2 },  { 1,   0, 1 }, },
+       { "0C",         { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
12, 2 },  { 1,   0, 1 }, },
+       { "0D",         { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
13, 2 },  { 1,   0, 1 }, },
+       { "0E",         { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
14, 2 },  { 1,   0, 1 }, },
+       { "0F",         { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
15, 2 },  { 1,   0, 1 }, },
+       { "0X",         { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
0, 1 },  { 1,   0, 1 }, },
+       { "0a",         { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
10, 2 },  { 1,   0, 1 }, },
+       { "0b",         { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
11, 2 },  { 1,   0, 1 }, },
+       { "0c",         { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
12, 2 },  { 1,   0, 1 }, },
+       { "0d",         { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
13, 2 },  { 1,   0, 1 }, },
+       { "0e",         { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
14, 2 },  { 1,   0, 1 }, },
+       { "0f",         { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
15, 2 },  { 1,   0, 1 }, },
+       { "0x",         { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
0, 1 },  { 1,   0, 1 }, },
+       // all digits with leading one
+       { "10",         { 1,   2, 2 },  { 1,   8, 2 },  { 1,  10, 2 },  { 1,  
16, 2 },  { 1,  10, 2 }, },
+       { "11",         { 1,   3, 2 },  { 1,   9, 2 },  { 1,  11, 2 },  { 1,  
17, 2 },  { 1,  11, 2 }, },
+       { "12",         { 1,   1, 1 },  { 1,  10, 2 },  { 1,  12, 2 },  { 1,  
18, 2 },  { 1,  12, 2 }, },
+       { "13",         { 1,   1, 1 },  { 1,  11, 2 },  { 1,  13, 2 },  { 1,  
19, 2 },  { 1,  13, 2 }, },
+       { "14",         { 1,   1, 1 },  { 1,  12, 2 },  { 1,  14, 2 },  { 1,  
20, 2 },  { 1,  14, 2 }, },
+       { "15",         { 1,   1, 1 },  { 1,  13, 2 },  { 1,  15, 2 },  { 1,  
21, 2 },  { 1,  15, 2 }, },
+       { "16",         { 1,   1, 1 },  { 1,  14, 2 },  { 1,  16, 2 },  { 1,  
22, 2 },  { 1,  16, 2 }, },
+       { "17",         { 1,   1, 1 },  { 1,  15, 2 },  { 1,  17, 2 },  { 1,  
23, 2 },  { 1,  17, 2 }, },
+       { "18",         { 1,   1, 1 },  { 1,   1, 1 },  { 1,  18, 2 },  { 1,  
24, 2 },  { 1,  18, 2 }, },
+       { "19",         { 1,   1, 1 },  { 1,   1, 1 },  { 1,  19, 2 },  { 1,  
25, 2 },  { 1,  19, 2 }, },
+       { "1A",         { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,  
26, 2 },  { 1,   1, 1 }, },
+       { "1B",         { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,  
27, 2 },  { 1,   1, 1 }, },
+       { "1C",         { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,  
28, 2 },  { 1,   1, 1 }, },
+       { "1D",         { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,  
29, 2 },  { 1,   1, 1 }, },
+       { "1E",         { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,  
30, 2 },  { 1,   1, 1 }, },
+       { "1F",         { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,  
31, 2 },  { 1,   1, 1 }, },
+       { "1X",         { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,   
1, 1 },  { 1,   1, 1 }, },
+       { "1a",         { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,  
26, 2 },  { 1,   1, 1 }, },
+       { "1b",         { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,  
27, 2 },  { 1,   1, 1 }, },
+       { "1c",         { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,  
28, 2 },  { 1,   1, 1 }, },
+       { "1d",         { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,  
29, 2 },  { 1,   1, 1 }, },
+       { "1e",         { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,  
30, 2 },  { 1,   1, 1 }, },
+       { "1f",         { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,  
31, 2 },  { 1,   1, 1 }, },
+       { "1x",         { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,   
1, 1 },  { 1,   1, 1 }, },
+       // all digits with leading binary prefix
+       { "0b0",        { 1,   0, 3 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
176, 3 },  { 1,   0, 3 }, },
+       { "0b1",        { 1,   1, 3 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
177, 3 },  { 1,   1, 3 }, },
+       { "0b2",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
178, 3 },  { 1,   0, 1 }, },
+       { "0b3",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
179, 3 },  { 1,   0, 1 }, },
+       { "0b4",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
180, 3 },  { 1,   0, 1 }, },
+       { "0b5",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
181, 3 },  { 1,   0, 1 }, },
+       { "0b6",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
182, 3 },  { 1,   0, 1 }, },
+       { "0b7",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
183, 3 },  { 1,   0, 1 }, },
+       { "0b8",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
184, 3 },  { 1,   0, 1 }, },
+       { "0b9",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
185, 3 },  { 1,   0, 1 }, },
+       { "0bA",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
186, 3 },  { 1,   0, 1 }, },
+       { "0bB",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
187, 3 },  { 1,   0, 1 }, },
+       { "0bC",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
188, 3 },  { 1,   0, 1 }, },
+       { "0bD",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
189, 3 },  { 1,   0, 1 }, },
+       { "0bE",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
190, 3 },  { 1,   0, 1 }, },
+       { "0bF",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
191, 3 },  { 1,   0, 1 }, },
+       { "0bX",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
11, 2 },  { 1,   0, 1 }, },
+       { "0ba",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
186, 3 },  { 1,   0, 1 }, },
+       { "0bb",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
187, 3 },  { 1,   0, 1 }, },
+       { "0bc",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
188, 3 },  { 1,   0, 1 }, },
+       { "0bd",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
189, 3 },  { 1,   0, 1 }, },
+       { "0be",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
190, 3 },  { 1,   0, 1 }, },
+       { "0bf",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
191, 3 },  { 1,   0, 1 }, },
+       { "0bx",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
11, 2 },  { 1,   0, 1 }, },
+       // all digits with leading hexadecimal prefix
+       { "0x0",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
0, 3 },  { 1,   0, 3 }, },
+       { "0x1",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
1, 3 },  { 1,   1, 3 }, },
+       { "0x2",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
2, 3 },  { 1,   2, 3 }, },
+       { "0x3",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
3, 3 },  { 1,   3, 3 }, },
+       { "0x4",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
4, 3 },  { 1,   4, 3 }, },
+       { "0x5",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
5, 3 },  { 1,   5, 3 }, },
+       { "0x6",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
6, 3 },  { 1,   6, 3 }, },
+       { "0x7",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
7, 3 },  { 1,   7, 3 }, },
+       { "0x8",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
8, 3 },  { 1,   8, 3 }, },
+       { "0x9",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
9, 3 },  { 1,   9, 3 }, },
+       { "0xA",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
10, 3 },  { 1,  10, 3 }, },
+       { "0xB",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
11, 3 },  { 1,  11, 3 }, },
+       { "0xC",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
12, 3 },  { 1,  12, 3 }, },
+       { "0xD",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
13, 3 },  { 1,  13, 3 }, },
+       { "0xE",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
14, 3 },  { 1,  14, 3 }, },
+       { "0xF",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
15, 3 },  { 1,  15, 3 }, },
+       { "0xX",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
0, 1 },  { 1,   0, 1 }, },
+       { "0xa",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
10, 3 },  { 1,  10, 3 }, },
+       { "0xb",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
11, 3 },  { 1,  11, 3 }, },
+       { "0xc",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
12, 3 },  { 1,  12, 3 }, },
+       { "0xd",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
13, 3 },  { 1,  13, 3 }, },
+       { "0xe",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
14, 3 },  { 1,  14, 3 }, },
+       { "0xf",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
15, 3 },  { 1,  15, 3 }, },
+       { "0xX",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
0, 1 },  { 1,   0, 1 }, },
+       // terminator
+       { "" }
+};
+
+#define SSCANF_TEST(string, format, expret, expval, explen)            \
+       do {                                                            \
+               int ret = 0, val = 0, len = 0;                          \
+               ret = sscanf(string, format "%n", &val, &len);          \
+               ATF_CHECK_EQ(expret, ret);                              \
+               if (expret && ret) {                                    \
+                       ATF_CHECK_EQ(expval, val);                      \
+                       ATF_CHECK_EQ(explen, len);                      \
+               }                                                       \
+       } while (0)
+
+ATF_TC_WITHOUT_HEAD(sscanf_b);
+ATF_TC_BODY(sscanf_b, tc)
+{
+       const struct sscanf_test_case *stc;
+       char input[16];
+
+       for (stc = sscanf_test_cases; *stc->input; stc++) {
+               strcpy(input + 1, stc->input);
+               SSCANF_TEST(input + 1, "%b", stc->b.ret, stc->b.val, 
stc->b.len);
+               input[0] = '+';
+               SSCANF_TEST(input, "%b", stc->b.ret, stc->b.val, stc->b.len ? 
stc->b.len + 1 : 0);
+               input[0] = '-';
+               SSCANF_TEST(input, "%b", stc->b.ret, -stc->b.val, stc->b.len ? 
stc->b.len + 1 : 0);
+       }
+}
+
+ATF_TC_WITHOUT_HEAD(sscanf_o);
+ATF_TC_BODY(sscanf_o, tc)
+{
+       const struct sscanf_test_case *stc;
+       char input[16];
+
+       for (stc = sscanf_test_cases; *stc->input; stc++) {
+               strcpy(input + 1, stc->input);
+               SSCANF_TEST(input + 1, "%o", stc->o.ret, stc->o.val, 
stc->o.len);
+               input[0] = '+';
+               SSCANF_TEST(input, "%o", stc->o.ret, stc->o.val, stc->o.len ? 
stc->o.len + 1 : 0);
+               input[0] = '-';
+               SSCANF_TEST(input, "%o", stc->o.ret, -stc->o.val, stc->o.len ? 
stc->o.len + 1 : 0);
+       }
+}
+
+ATF_TC_WITHOUT_HEAD(sscanf_d);
+ATF_TC_BODY(sscanf_d, tc)
+{
+       const struct sscanf_test_case *stc;
+       char input[16];
+
+       for (stc = sscanf_test_cases; *stc->input; stc++) {
+               strcpy(input + 1, stc->input);
+               SSCANF_TEST(input + 1, "%d", stc->d.ret, stc->d.val, 
stc->d.len);
+               input[0] = '+';
+               SSCANF_TEST(input, "%d", stc->d.ret, stc->d.val, stc->d.len ? 
stc->d.len + 1 : 0);
+               input[0] = '-';
+               SSCANF_TEST(input, "%d", stc->d.ret, -stc->d.val, stc->d.len ? 
stc->d.len + 1 : 0);
+       }
+}
+
+ATF_TC_WITHOUT_HEAD(sscanf_x);
+ATF_TC_BODY(sscanf_x, tc)
+{
+       const struct sscanf_test_case *stc;
+       char input[16];
+
+       for (stc = sscanf_test_cases; *stc->input; stc++) {
+               strcpy(input + 1, stc->input);
+               SSCANF_TEST(input + 1, "%x", stc->x.ret, stc->x.val, 
stc->x.len);
+               input[0] = '+';
+               SSCANF_TEST(input, "%x", stc->x.ret, stc->x.val, stc->x.len ? 
stc->x.len + 1 : 0);
+               input[0] = '-';
+               SSCANF_TEST(input, "%x", stc->x.ret, -stc->x.val, stc->x.len ? 
stc->x.len + 1 : 0);
+       }
+}
+
+ATF_TC_WITHOUT_HEAD(sscanf_i);
+ATF_TC_BODY(sscanf_i, tc)
+{
+       const struct sscanf_test_case *stc;
+       char input[16];
+
+       for (stc = sscanf_test_cases; *stc->input; stc++) {
+               strcpy(input + 1, stc->input);
+               SSCANF_TEST(input + 1, "%i", stc->i.ret, stc->i.val, 
stc->i.len);
+               input[0] = '+';
+               SSCANF_TEST(input, "%i", stc->i.ret, stc->i.val, stc->i.len ? 
stc->i.len + 1 : 0);
+               input[0] = '-';
+               SSCANF_TEST(input, "%i", stc->i.ret, -stc->i.val, stc->i.len ? 
stc->i.len + 1 : 0);
+       }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+       setlocale(LC_NUMERIC, "en_US.UTF-8");
+       ATF_TP_ADD_TC(tp, sscanf_b);
+       ATF_TP_ADD_TC(tp, sscanf_o);
+       ATF_TP_ADD_TC(tp, sscanf_d);
+       ATF_TP_ADD_TC(tp, sscanf_x);
+       ATF_TP_ADD_TC(tp, sscanf_i);
+       return (atf_no_error());
+}
diff --git a/lib/libc/tests/stdio/swscanf_test.c 
b/lib/libc/tests/stdio/swscanf_test.c
new file mode 100644
index 000000000000..391a54e0ed5e
--- /dev/null
+++ b/lib/libc/tests/stdio/swscanf_test.c
@@ -0,0 +1,250 @@
+/*-
+ * Copyright (c) 2023 Dag-Erling Smørgrav
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <locale.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <wchar.h>
+
+#include <atf-c.h>
+
+static const struct swscanf_test_case {
+       wchar_t input[8];
+       struct {
+               int ret, val, len;
+       } b, o, d, x, i;
+} swscanf_test_cases[] = {
+//     input           binary          octal           decimal         
hexadecimal     automatic
+       // all digits
+       { L"0",         { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
0, 1 },  { 1,   0, 1 }, },
+       { L"1",         { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,   
1, 1 },  { 1,   1, 1 }, },
+       { L"2",         { 0,   0, 0 },  { 1,   2, 1 },  { 1,   2, 1 },  { 1,   
2, 1 },  { 1,   2, 1 }, },
+       { L"3",         { 0,   0, 0 },  { 1,   3, 1 },  { 1,   3, 1 },  { 1,   
3, 1 },  { 1,   3, 1 }, },
+       { L"4",         { 0,   0, 0 },  { 1,   4, 1 },  { 1,   4, 1 },  { 1,   
4, 1 },  { 1,   4, 1 }, },
+       { L"5",         { 0,   0, 0 },  { 1,   5, 1 },  { 1,   5, 1 },  { 1,   
5, 1 },  { 1,   5, 1 }, },
+       { L"6",         { 0,   0, 0 },  { 1,   6, 1 },  { 1,   6, 1 },  { 1,   
6, 1 },  { 1,   6, 1 }, },
+       { L"7",         { 0,   0, 0 },  { 1,   7, 1 },  { 1,   7, 1 },  { 1,   
7, 1 },  { 1,   7, 1 }, },
+       { L"8",         { 0,   0, 0 },  { 0,   0, 0 },  { 1,   8, 1 },  { 1,   
8, 1 },  { 1,   8, 1 }, },
+       { L"9",         { 0,   0, 0 },  { 0,   0, 0 },  { 1,   9, 1 },  { 1,   
9, 1 },  { 1,   9, 1 }, },
+       { L"A",         { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 1,  
10, 1 },  { 0,   0, 0 }, },
+       { L"B",         { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 1,  
11, 1 },  { 0,   0, 0 }, },
+       { L"C",         { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 1,  
12, 1 },  { 0,   0, 0 }, },
+       { L"D",         { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 1,  
13, 1 },  { 0,   0, 0 }, },
+       { L"E",         { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 1,  
14, 1 },  { 0,   0, 0 }, },
+       { L"F",         { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 1,  
15, 1 },  { 0,   0, 0 }, },
+       { L"X",         { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 0,   
0, 0 },  { 0,   0, 0 }, },
+       { L"a",         { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 1,  
10, 1 },  { 0,   0, 0 }, },
+       { L"b",         { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 1,  
11, 1 },  { 0,   0, 0 }, },
+       { L"c",         { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 1,  
12, 1 },  { 0,   0, 0 }, },
+       { L"d",         { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 1,  
13, 1 },  { 0,   0, 0 }, },
+       { L"e",         { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 1,  
14, 1 },  { 0,   0, 0 }, },
+       { L"f",         { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 1,  
15, 1 },  { 0,   0, 0 }, },
+       { L"x",         { 0,   0, 0 },  { 0,   0, 0 },  { 0,   0, 0 },  { 0,   
0, 0 },  { 0,   0, 0 }, },
+       // all digits with leading zero
+       { L"00",        { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,   
0, 2 },  { 1,   0, 2 }, },
+       { L"01",        { 1,   1, 2 },  { 1,   1, 2 },  { 1,   1, 2 },  { 1,   
1, 2 },  { 1,   1, 2 }, },
+       { L"02",        { 1,   0, 1 },  { 1,   2, 2 },  { 1,   2, 2 },  { 1,   
2, 2 },  { 1,   2, 2 }, },
+       { L"03",        { 1,   0, 1 },  { 1,   3, 2 },  { 1,   3, 2 },  { 1,   
3, 2 },  { 1,   3, 2 }, },
+       { L"04",        { 1,   0, 1 },  { 1,   4, 2 },  { 1,   4, 2 },  { 1,   
4, 2 },  { 1,   4, 2 }, },
+       { L"05",        { 1,   0, 1 },  { 1,   5, 2 },  { 1,   5, 2 },  { 1,   
5, 2 },  { 1,   5, 2 }, },
+       { L"06",        { 1,   0, 1 },  { 1,   6, 2 },  { 1,   6, 2 },  { 1,   
6, 2 },  { 1,   6, 2 }, },
+       { L"07",        { 1,   0, 1 },  { 1,   7, 2 },  { 1,   7, 2 },  { 1,   
7, 2 },  { 1,   7, 2 }, },
+       { L"08",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   8, 2 },  { 1,   
8, 2 },  { 1,   0, 1 }, },
+       { L"09",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   9, 2 },  { 1,   
9, 2 },  { 1,   0, 1 }, },
+       { L"0A",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
10, 2 },  { 1,   0, 1 }, },
+       { L"0B",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
11, 2 },  { 1,   0, 1 }, },
+       { L"0C",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
12, 2 },  { 1,   0, 1 }, },
+       { L"0D",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
13, 2 },  { 1,   0, 1 }, },
+       { L"0E",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
14, 2 },  { 1,   0, 1 }, },
+       { L"0F",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
15, 2 },  { 1,   0, 1 }, },
+       { L"0X",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
0, 1 },  { 1,   0, 1 }, },
+       { L"0a",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
10, 2 },  { 1,   0, 1 }, },
+       { L"0b",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
11, 2 },  { 1,   0, 1 }, },
+       { L"0c",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
12, 2 },  { 1,   0, 1 }, },
+       { L"0d",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
13, 2 },  { 1,   0, 1 }, },
+       { L"0e",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
14, 2 },  { 1,   0, 1 }, },
+       { L"0f",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
15, 2 },  { 1,   0, 1 }, },
+       { L"0x",        { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
0, 1 },  { 1,   0, 1 }, },
+       // all digits with leading one
+       { L"10",        { 1,   2, 2 },  { 1,   8, 2 },  { 1,  10, 2 },  { 1,  
16, 2 },  { 1,  10, 2 }, },
+       { L"11",        { 1,   3, 2 },  { 1,   9, 2 },  { 1,  11, 2 },  { 1,  
17, 2 },  { 1,  11, 2 }, },
+       { L"12",        { 1,   1, 1 },  { 1,  10, 2 },  { 1,  12, 2 },  { 1,  
18, 2 },  { 1,  12, 2 }, },
+       { L"13",        { 1,   1, 1 },  { 1,  11, 2 },  { 1,  13, 2 },  { 1,  
19, 2 },  { 1,  13, 2 }, },
+       { L"14",        { 1,   1, 1 },  { 1,  12, 2 },  { 1,  14, 2 },  { 1,  
20, 2 },  { 1,  14, 2 }, },
+       { L"15",        { 1,   1, 1 },  { 1,  13, 2 },  { 1,  15, 2 },  { 1,  
21, 2 },  { 1,  15, 2 }, },
+       { L"16",        { 1,   1, 1 },  { 1,  14, 2 },  { 1,  16, 2 },  { 1,  
22, 2 },  { 1,  16, 2 }, },
+       { L"17",        { 1,   1, 1 },  { 1,  15, 2 },  { 1,  17, 2 },  { 1,  
23, 2 },  { 1,  17, 2 }, },
+       { L"18",        { 1,   1, 1 },  { 1,   1, 1 },  { 1,  18, 2 },  { 1,  
24, 2 },  { 1,  18, 2 }, },
+       { L"19",        { 1,   1, 1 },  { 1,   1, 1 },  { 1,  19, 2 },  { 1,  
25, 2 },  { 1,  19, 2 }, },
+       { L"1A",        { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,  
26, 2 },  { 1,   1, 1 }, },
+       { L"1B",        { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,  
27, 2 },  { 1,   1, 1 }, },
+       { L"1C",        { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,  
28, 2 },  { 1,   1, 1 }, },
+       { L"1D",        { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,  
29, 2 },  { 1,   1, 1 }, },
+       { L"1E",        { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,  
30, 2 },  { 1,   1, 1 }, },
+       { L"1F",        { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,  
31, 2 },  { 1,   1, 1 }, },
+       { L"1X",        { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,   
1, 1 },  { 1,   1, 1 }, },
+       { L"1a",        { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,  
26, 2 },  { 1,   1, 1 }, },
+       { L"1b",        { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,  
27, 2 },  { 1,   1, 1 }, },
+       { L"1c",        { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,  
28, 2 },  { 1,   1, 1 }, },
+       { L"1d",        { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,  
29, 2 },  { 1,   1, 1 }, },
+       { L"1e",        { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,  
30, 2 },  { 1,   1, 1 }, },
+       { L"1f",        { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,  
31, 2 },  { 1,   1, 1 }, },
+       { L"1x",        { 1,   1, 1 },  { 1,   1, 1 },  { 1,   1, 1 },  { 1,   
1, 1 },  { 1,   1, 1 }, },
+       // all digits with leading binary prefix
+       { L"0b0",       { 1,   0, 3 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
176, 3 },  { 1,   0, 3 }, },
+       { L"0b1",       { 1,   1, 3 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
177, 3 },  { 1,   1, 3 }, },
+       { L"0b2",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
178, 3 },  { 1,   0, 1 }, },
+       { L"0b3",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
179, 3 },  { 1,   0, 1 }, },
+       { L"0b4",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
180, 3 },  { 1,   0, 1 }, },
+       { L"0b5",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
181, 3 },  { 1,   0, 1 }, },
+       { L"0b6",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
182, 3 },  { 1,   0, 1 }, },
+       { L"0b7",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
183, 3 },  { 1,   0, 1 }, },
+       { L"0b8",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
184, 3 },  { 1,   0, 1 }, },
+       { L"0b9",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
185, 3 },  { 1,   0, 1 }, },
+       { L"0bA",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
186, 3 },  { 1,   0, 1 }, },
+       { L"0bB",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
187, 3 },  { 1,   0, 1 }, },
+       { L"0bC",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
188, 3 },  { 1,   0, 1 }, },
+       { L"0bD",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
189, 3 },  { 1,   0, 1 }, },
+       { L"0bE",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
190, 3 },  { 1,   0, 1 }, },
+       { L"0bF",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
191, 3 },  { 1,   0, 1 }, },
+       { L"0bX",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
11, 2 },  { 1,   0, 1 }, },
+       { L"0ba",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
186, 3 },  { 1,   0, 1 }, },
+       { L"0bb",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
187, 3 },  { 1,   0, 1 }, },
+       { L"0bc",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
188, 3 },  { 1,   0, 1 }, },
+       { L"0bd",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
189, 3 },  { 1,   0, 1 }, },
+       { L"0be",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
190, 3 },  { 1,   0, 1 }, },
+       { L"0bf",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1, 
191, 3 },  { 1,   0, 1 }, },
+       { L"0bx",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
11, 2 },  { 1,   0, 1 }, },
+       // all digits with leading hexadecimal prefix
+       { L"0x0",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
0, 3 },  { 1,   0, 3 }, },
+       { L"0x1",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
1, 3 },  { 1,   1, 3 }, },
+       { L"0x2",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
2, 3 },  { 1,   2, 3 }, },
+       { L"0x3",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
3, 3 },  { 1,   3, 3 }, },
+       { L"0x4",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
4, 3 },  { 1,   4, 3 }, },
+       { L"0x5",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
5, 3 },  { 1,   5, 3 }, },
+       { L"0x6",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
6, 3 },  { 1,   6, 3 }, },
+       { L"0x7",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
7, 3 },  { 1,   7, 3 }, },
+       { L"0x8",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
8, 3 },  { 1,   8, 3 }, },
+       { L"0x9",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
9, 3 },  { 1,   9, 3 }, },
+       { L"0xA",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
10, 3 },  { 1,  10, 3 }, },
+       { L"0xB",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
11, 3 },  { 1,  11, 3 }, },
+       { L"0xC",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
12, 3 },  { 1,  12, 3 }, },
+       { L"0xD",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
13, 3 },  { 1,  13, 3 }, },
+       { L"0xE",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
14, 3 },  { 1,  14, 3 }, },
+       { L"0xF",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
15, 3 },  { 1,  15, 3 }, },
+       { L"0xX",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
0, 1 },  { 1,   0, 1 }, },
+       { L"0xa",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
10, 3 },  { 1,  10, 3 }, },
+       { L"0xb",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
11, 3 },  { 1,  11, 3 }, },
+       { L"0xc",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
12, 3 },  { 1,  12, 3 }, },
+       { L"0xd",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
13, 3 },  { 1,  13, 3 }, },
+       { L"0xe",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
14, 3 },  { 1,  14, 3 }, },
+       { L"0xf",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,  
15, 3 },  { 1,  15, 3 }, },
+       { L"0xX",       { 1,   0, 1 },  { 1,   0, 1 },  { 1,   0, 1 },  { 1,   
0, 1 },  { 1,   0, 1 }, },
+       // terminator
+       { L"" }
+};
+
+#define SWSCANF_TEST(string, format, expret, expval, explen)           \
+       do {                                                            \
+               int ret = 0, val = 0, len = 0;                          \
+               ret = swscanf(string, format "%n", &val, &len);         \
+               ATF_CHECK_EQ(expret, ret);                              \
+               if (expret && ret) {                                    \
+                       ATF_CHECK_EQ(expval, val);                      \
+                       ATF_CHECK_EQ(explen, len);                      \
+               }                                                       \
+       } while (0)
+
+ATF_TC_WITHOUT_HEAD(swscanf_b);
+ATF_TC_BODY(swscanf_b, tc)
+{
+       const struct swscanf_test_case *stc;
+       wchar_t input[16];
+
+       for (stc = swscanf_test_cases; *stc->input; stc++) {
+               wcscpy(input + 1, stc->input);
+               SWSCANF_TEST(input + 1, L"%b", stc->b.ret, stc->b.val, 
stc->b.len);
+               input[0] = L'+';
+               SWSCANF_TEST(input, L"%b", stc->b.ret, stc->b.val, stc->b.len ? 
stc->b.len + 1 : 0);
+               input[0] = L'-';
+               SWSCANF_TEST(input, L"%b", stc->b.ret, -stc->b.val, stc->b.len 
? stc->b.len + 1 : 0);
+       }
+}
+
+ATF_TC_WITHOUT_HEAD(swscanf_o);
+ATF_TC_BODY(swscanf_o, tc)
+{
+       const struct swscanf_test_case *stc;
+       wchar_t input[16];
+
+       for (stc = swscanf_test_cases; *stc->input; stc++) {
+               wcscpy(input + 1, stc->input);
+               SWSCANF_TEST(input + 1, L"%o", stc->o.ret, stc->o.val, 
stc->o.len);
+               input[0] = L'+';
+               SWSCANF_TEST(input, L"%o", stc->o.ret, stc->o.val, stc->o.len ? 
stc->o.len + 1 : 0);
+               input[0] = L'-';
+               SWSCANF_TEST(input, L"%o", stc->o.ret, -stc->o.val, stc->o.len 
? stc->o.len + 1 : 0);
+       }
+}
+
+ATF_TC_WITHOUT_HEAD(swscanf_d);
+ATF_TC_BODY(swscanf_d, tc)
+{
+       const struct swscanf_test_case *stc;
+       wchar_t input[16];
+
+       for (stc = swscanf_test_cases; *stc->input; stc++) {
+               wcscpy(input + 1, stc->input);
+               SWSCANF_TEST(input + 1, L"%d", stc->d.ret, stc->d.val, 
stc->d.len);
+               input[0] = L'+';
+               SWSCANF_TEST(input, L"%d", stc->d.ret, stc->d.val, stc->d.len ? 
stc->d.len + 1 : 0);
+               input[0] = L'-';
+               SWSCANF_TEST(input, L"%d", stc->d.ret, -stc->d.val, stc->d.len 
? stc->d.len + 1 : 0);
+       }
+}
+
+ATF_TC_WITHOUT_HEAD(swscanf_x);
+ATF_TC_BODY(swscanf_x, tc)
+{
+       const struct swscanf_test_case *stc;
+       wchar_t input[16];
+
+       for (stc = swscanf_test_cases; *stc->input; stc++) {
+               wcscpy(input + 1, stc->input);
+               SWSCANF_TEST(input + 1, L"%x", stc->x.ret, stc->x.val, 
stc->x.len);
+               input[0] = L'+';
+               SWSCANF_TEST(input, L"%x", stc->x.ret, stc->x.val, stc->x.len ? 
stc->x.len + 1 : 0);
+               input[0] = L'-';
+               SWSCANF_TEST(input, L"%x", stc->x.ret, -stc->x.val, stc->x.len 
? stc->x.len + 1 : 0);
+       }
+}
+
+ATF_TC_WITHOUT_HEAD(swscanf_i);
+ATF_TC_BODY(swscanf_i, tc)
+{
+       const struct swscanf_test_case *stc;
+       wchar_t input[16];
+
+       for (stc = swscanf_test_cases; *stc->input; stc++) {
+               wcscpy(input + 1, stc->input);
+               SWSCANF_TEST(input + 1, L"%i", stc->i.ret, stc->i.val, 
stc->i.len);
+               input[0] = L'+';
+               SWSCANF_TEST(input, L"%i", stc->i.ret, stc->i.val, stc->i.len ? 
stc->i.len + 1 : 0);
+               input[0] = L'-';
+               SWSCANF_TEST(input, L"%i", stc->i.ret, -stc->i.val, stc->i.len 
? stc->i.len + 1 : 0);
+       }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+       setlocale(LC_NUMERIC, "en_US.UTF-8");
+       ATF_TP_ADD_TC(tp, swscanf_b);
+       ATF_TP_ADD_TC(tp, swscanf_o);
+       ATF_TP_ADD_TC(tp, swscanf_d);
+       ATF_TP_ADD_TC(tp, swscanf_x);
+       ATF_TP_ADD_TC(tp, swscanf_i);
+       return (atf_no_error());
+}

Reply via email to