The branch main has been updated by des:

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

commit 602e98dd35ea5041b800fb56a2b1ac34f6649310
Author:     Dag-Erling Smørgrav <d...@freebsd.org>
AuthorDate: 2025-08-08 22:17:19 +0000
Commit:     Dag-Erling Smørgrav <d...@freebsd.org>
CommitDate: 2025-08-08 22:46:03 +0000

    stdio: Fix bug in integer-parsing FSM
    
    If we encounter a zero in the havezero state, we should assume octal,
    just like we would if we encountered any other digit below 8.
    
    MFC after:      1 week
    PR:             288440
    Fixes:          d9dc1603d6e4 ("libc: Implement N2630.")
    Reviewed by:    mandree
    Differential Revision:  https://reviews.freebsd.org/D51832
---
 lib/libc/stdio/vfscanf.c            |  5 ++---
 lib/libc/stdio/vfwscanf.c           |  5 ++---
 lib/libc/tests/stdio/sscanf_test.c  | 25 +++++++++++++++++++++++++
 lib/libc/tests/stdio/swscanf_test.c | 25 +++++++++++++++++++++++++
 4 files changed, 54 insertions(+), 6 deletions(-)

diff --git a/lib/libc/stdio/vfscanf.c b/lib/libc/stdio/vfscanf.c
index a678710e1ecb..89e9e843969f 100644
--- a/lib/libc/stdio/vfscanf.c
+++ b/lib/libc/stdio/vfscanf.c
@@ -318,10 +318,9 @@ parseint_fsm(int c, enum parseint_state *state, int *base)
        case '0':
                if (*state == begin || *state == havesign) {
                        *state = havezero;
-               } else {
-                       *state = any;
+                       return 1;
                }
-               return 1;
+               /* FALL THROUGH */
        case '1':
        case '2':
        case '3':
diff --git a/lib/libc/stdio/vfwscanf.c b/lib/libc/stdio/vfwscanf.c
index 57206a8407d5..7ca64eb37811 100644
--- a/lib/libc/stdio/vfwscanf.c
+++ b/lib/libc/stdio/vfwscanf.c
@@ -298,10 +298,9 @@ parseint_fsm(wchar_t c, enum parseint_state *state, int 
*base)
        case '0':
                if (*state == begin || *state == havesign) {
                        *state = havezero;
-               } else {
-                       *state = any;
+                       return 1;
                }
-               return 1;
+               /* FALL THROUGH */
        case '1':
        case '2':
        case '3':
diff --git a/lib/libc/tests/stdio/sscanf_test.c 
b/lib/libc/tests/stdio/sscanf_test.c
index e916873d38c3..e43292820eeb 100644
--- a/lib/libc/tests/stdio/sscanf_test.c
+++ b/lib/libc/tests/stdio/sscanf_test.c
@@ -68,6 +68,31 @@ static const struct sscanf_test_case {
        { "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 two leading zeroes
+       { "000",        { 1,   0, 3 },  { 1,   0, 3 },  { 1,   0, 3 },  { 1,   
0, 3 },  { 1,   0, 3 }, },
+       { "001",        { 1,   1, 3 },  { 1,   1, 3 },  { 1,   1, 3 },  { 1,   
1, 3 },  { 1,   1, 3 }, },
+       { "002",        { 1,   0, 2 },  { 1,   2, 3 },  { 1,   2, 3 },  { 1,   
2, 3 },  { 1,   2, 3 }, },
+       { "003",        { 1,   0, 2 },  { 1,   3, 3 },  { 1,   3, 3 },  { 1,   
3, 3 },  { 1,   3, 3 }, },
+       { "004",        { 1,   0, 2 },  { 1,   4, 3 },  { 1,   4, 3 },  { 1,   
4, 3 },  { 1,   4, 3 }, },
+       { "005",        { 1,   0, 2 },  { 1,   5, 3 },  { 1,   5, 3 },  { 1,   
5, 3 },  { 1,   5, 3 }, },
+       { "006",        { 1,   0, 2 },  { 1,   6, 3 },  { 1,   6, 3 },  { 1,   
6, 3 },  { 1,   6, 3 }, },
+       { "007",        { 1,   0, 2 },  { 1,   7, 3 },  { 1,   7, 3 },  { 1,   
7, 3 },  { 1,   7, 3 }, },
+       { "008",        { 1,   0, 2 },  { 1,   0, 2 },  { 1,   8, 3 },  { 1,   
8, 3 },  { 1,   0, 2 }, },
+       { "009",        { 1,   0, 2 },  { 1,   0, 2 },  { 1,   9, 3 },  { 1,   
9, 3 },  { 1,   0, 2 }, },
+       { "00A",        { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,  
10, 3 },  { 1,   0, 2 }, },
+       { "00B",        { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,  
11, 3 },  { 1,   0, 2 }, },
+       { "00C",        { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,  
12, 3 },  { 1,   0, 2 }, },
+       { "00D",        { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,  
13, 3 },  { 1,   0, 2 }, },
+       { "00E",        { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,  
14, 3 },  { 1,   0, 2 }, },
+       { "00F",        { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,  
15, 3 },  { 1,   0, 2 }, },
+       { "00X",        { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,   
0, 2 },  { 1,   0, 2 }, },
+       { "00a",        { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,  
10, 3 },  { 1,   0, 2 }, },
+       { "00b",        { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,  
11, 3 },  { 1,   0, 2 }, },
+       { "00c",        { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,  
12, 3 },  { 1,   0, 2 }, },
+       { "00d",        { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,  
13, 3 },  { 1,   0, 2 }, },
+       { "00e",        { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,  
14, 3 },  { 1,   0, 2 }, },
+       { "00f",        { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,  
15, 3 },  { 1,   0, 2 }, },
+       { "00x",        { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,   
0, 2 },  { 1,   0, 2 }, },
        // 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 }, },
diff --git a/lib/libc/tests/stdio/swscanf_test.c 
b/lib/libc/tests/stdio/swscanf_test.c
index f7ad30b963a7..f0638081e16f 100644
--- a/lib/libc/tests/stdio/swscanf_test.c
+++ b/lib/libc/tests/stdio/swscanf_test.c
@@ -71,6 +71,31 @@ static const struct swscanf_test_case {
        { 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 two leading zeroes
+       { L"000",       { 1,   0, 3 },  { 1,   0, 3 },  { 1,   0, 3 },  { 1,   
0, 3 },  { 1,   0, 3 }, },
+       { L"001",       { 1,   1, 3 },  { 1,   1, 3 },  { 1,   1, 3 },  { 1,   
1, 3 },  { 1,   1, 3 }, },
+       { L"002",       { 1,   0, 2 },  { 1,   2, 3 },  { 1,   2, 3 },  { 1,   
2, 3 },  { 1,   2, 3 }, },
+       { L"003",       { 1,   0, 2 },  { 1,   3, 3 },  { 1,   3, 3 },  { 1,   
3, 3 },  { 1,   3, 3 }, },
+       { L"004",       { 1,   0, 2 },  { 1,   4, 3 },  { 1,   4, 3 },  { 1,   
4, 3 },  { 1,   4, 3 }, },
+       { L"005",       { 1,   0, 2 },  { 1,   5, 3 },  { 1,   5, 3 },  { 1,   
5, 3 },  { 1,   5, 3 }, },
+       { L"006",       { 1,   0, 2 },  { 1,   6, 3 },  { 1,   6, 3 },  { 1,   
6, 3 },  { 1,   6, 3 }, },
+       { L"007",       { 1,   0, 2 },  { 1,   7, 3 },  { 1,   7, 3 },  { 1,   
7, 3 },  { 1,   7, 3 }, },
+       { L"008",       { 1,   0, 2 },  { 1,   0, 2 },  { 1,   8, 3 },  { 1,   
8, 3 },  { 1,   0, 2 }, },
+       { L"009",       { 1,   0, 2 },  { 1,   0, 2 },  { 1,   9, 3 },  { 1,   
9, 3 },  { 1,   0, 2 }, },
+       { L"00A",       { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,  
10, 3 },  { 1,   0, 2 }, },
+       { L"00B",       { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,  
11, 3 },  { 1,   0, 2 }, },
+       { L"00C",       { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,  
12, 3 },  { 1,   0, 2 }, },
+       { L"00D",       { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,  
13, 3 },  { 1,   0, 2 }, },
+       { L"00E",       { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,  
14, 3 },  { 1,   0, 2 }, },
+       { L"00F",       { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,  
15, 3 },  { 1,   0, 2 }, },
+       { L"00X",       { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,   
0, 2 },  { 1,   0, 2 }, },
+       { L"00a",       { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,  
10, 3 },  { 1,   0, 2 }, },
+       { L"00b",       { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,  
11, 3 },  { 1,   0, 2 }, },
+       { L"00c",       { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,  
12, 3 },  { 1,   0, 2 }, },
+       { L"00d",       { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,  
13, 3 },  { 1,   0, 2 }, },
+       { L"00e",       { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,  
14, 3 },  { 1,   0, 2 }, },
+       { L"00f",       { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,  
15, 3 },  { 1,   0, 2 }, },
+       { L"00x",       { 1,   0, 2 },  { 1,   0, 2 },  { 1,   0, 2 },  { 1,   
0, 2 },  { 1,   0, 2 }, },
        // 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 }, },

Reply via email to