git: aca3bd160257 - main - libc: Fix fixed-width case in the new integer parser.

From: Dag-Erling Smørgrav <des_at_FreeBSD.org>
Date: Mon, 28 Aug 2023 23:38:31 UTC
The branch main has been updated by des:

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

commit aca3bd1602577591e5cd237c4bb0bb71b3be0c75
Author:     Dag-Erling Smørgrav <des@FreeBSD.org>
AuthorDate: 2023-08-28 23:38:09 +0000
Commit:     Dag-Erling Smørgrav <des@FreeBSD.org>
CommitDate: 2023-08-28 23:38:19 +0000

    libc: Fix fixed-width case in the new integer parser.
    
    Fixes:          d9dc1603d6e4
    Differential Revision:  https://reviews.freebsd.org/D41622
---
 lib/libc/stdio/vfscanf.c            |  2 +-
 lib/libc/stdio/vfwscanf.c           |  2 +-
 lib/libc/tests/stdio/sscanf_test.c  | 17 +++++++++++++++++
 lib/libc/tests/stdio/swscanf_test.c | 17 +++++++++++++++++
 4 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/lib/libc/stdio/vfscanf.c b/lib/libc/stdio/vfscanf.c
index b4db62c216ed..9727c9e70c34 100644
--- a/lib/libc/stdio/vfscanf.c
+++ b/lib/libc/stdio/vfscanf.c
@@ -452,7 +452,7 @@ parseint(FILE *fp, char * __restrict buf, int width, int base)
 	} else if (state == haveprefix) {
 		p--;
 		(void) __ungetc(c, fp);
-	} else if (c != EOF) {
+	} else if (width && c != EOF) {
 		(void) __ungetc(c, fp);
 	}
 	return (p - buf);
diff --git a/lib/libc/stdio/vfwscanf.c b/lib/libc/stdio/vfwscanf.c
index 3300751eafb6..b03c9dba0699 100644
--- a/lib/libc/stdio/vfwscanf.c
+++ b/lib/libc/stdio/vfwscanf.c
@@ -435,7 +435,7 @@ parseint(FILE *fp, wchar_t * __restrict buf, int width, int base,
 	} else if (state == haveprefix) {
 		wcp--;
 		__ungetwc(c, fp, locale);
-	} else if (c != WEOF) {
+	} else if (width && c != WEOF) {
 		__ungetwc(c, fp, locale);
 	}
 	return (wcp - buf);
diff --git a/lib/libc/tests/stdio/sscanf_test.c b/lib/libc/tests/stdio/sscanf_test.c
index 24226f3b3a8d..462b4a6586da 100644
--- a/lib/libc/tests/stdio/sscanf_test.c
+++ b/lib/libc/tests/stdio/sscanf_test.c
@@ -237,6 +237,22 @@ ATF_TC_BODY(sscanf_i, tc)
 	}
 }
 
+/*
+ * Test termination cases: non-numeric character, fixed width, EOF
+ */
+ATF_TC_WITHOUT_HEAD(sscanf_termination);
+ATF_TC_BODY(sscanf_termination, tc)
+{
+	int a = 0, b = 0, c = 0;
+	char d = 0;
+
+	ATF_CHECK_EQ(4, sscanf("3.1415", "%d%c%2d%d", &a, &d, &b, &c));
+	ATF_CHECK_EQ(3, a);
+	ATF_CHECK_EQ(14, b);
+	ATF_CHECK_EQ(15, c);
+	ATF_CHECK_EQ('.', d);
+}
+
 ATF_TP_ADD_TCS(tp)
 {
 	setlocale(LC_NUMERIC, "en_US.UTF-8");
@@ -245,5 +261,6 @@ ATF_TP_ADD_TCS(tp)
 	ATF_TP_ADD_TC(tp, sscanf_d);
 	ATF_TP_ADD_TC(tp, sscanf_x);
 	ATF_TP_ADD_TC(tp, sscanf_i);
+	ATF_TP_ADD_TC(tp, sscanf_termination);
 	return (atf_no_error());
 }
diff --git a/lib/libc/tests/stdio/swscanf_test.c b/lib/libc/tests/stdio/swscanf_test.c
index 391a54e0ed5e..10eaf786e5fa 100644
--- a/lib/libc/tests/stdio/swscanf_test.c
+++ b/lib/libc/tests/stdio/swscanf_test.c
@@ -238,6 +238,22 @@ ATF_TC_BODY(swscanf_i, tc)
 	}
 }
 
+/*
+ * Test termination cases: non-numeric character, fixed width, EOF
+ */
+ATF_TC_WITHOUT_HEAD(swscanf_termination);
+ATF_TC_BODY(swscanf_termination, tc)
+{
+	int a = 0, b = 0, c = 0;
+	char d = 0;
+
+	ATF_CHECK_EQ(4, swscanf(L"3.1415", L"%d%c%2d%d", &a, &d, &b, &c));
+	ATF_CHECK_EQ(3, a);
+	ATF_CHECK_EQ(14, b);
+	ATF_CHECK_EQ(15, c);
+	ATF_CHECK_EQ(L'.', d);
+}
+
 ATF_TP_ADD_TCS(tp)
 {
 	setlocale(LC_NUMERIC, "en_US.UTF-8");
@@ -246,5 +262,6 @@ ATF_TP_ADD_TCS(tp)
 	ATF_TP_ADD_TC(tp, swscanf_d);
 	ATF_TP_ADD_TC(tp, swscanf_x);
 	ATF_TP_ADD_TC(tp, swscanf_i);
+	ATF_TP_ADD_TC(tp, swscanf_termination);
 	return (atf_no_error());
 }