git: 6b0e99570fa2 - stable/13 - strfmon: EINVAL if the '+' flag and both signs are empty
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 03 Dec 2025 02:38:52 UTC
The branch stable/13 has been updated by jlduran:
URL: https://cgit.FreeBSD.org/src/commit/?id=6b0e99570fa208cc299c047591b7ded7b1b9a58d
commit 6b0e99570fa208cc299c047591b7ded7b1b9a58d
Author: Jose Luis Duran <jlduran@FreeBSD.org>
AuthorDate: 2025-11-26 20:34:55 +0000
Commit: Jose Luis Duran <jlduran@FreeBSD.org>
CommitDate: 2025-12-03 02:35:42 +0000
strfmon: EINVAL if the '+' flag and both signs are empty
According to the Open Group Base Specifications Issue 8[1], strfmon(3)
should return EINVAL when the '+' flag was included in a conversion
specification and the locale's positive_sign and negative_sign values
would both be returned by localeconv(3) as empty strings.
Austin Group Defect 1199[2] is applied, adding the [EINVAL] error.
[1]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/strfmon.html
[2]: https://www.austingroupbugs.net/view.php?id=1199
Reviewed by: kib
MFC after: 1 week
Differential Revision: https://reviews.freebsd.org/D53912
(cherry picked from commit 1fd018972a18b682521bb8f004dfd162327e5db2)
---
lib/libc/stdlib/strfmon.3 | 12 +++++++++++-
lib/libc/stdlib/strfmon.c | 4 +++-
lib/libc/tests/stdlib/strfmon_test.c | 8 ++++----
3 files changed, 18 insertions(+), 6 deletions(-)
diff --git a/lib/libc/stdlib/strfmon.3 b/lib/libc/stdlib/strfmon.3
index 20cc560d401d..d537d9d05fa7 100644
--- a/lib/libc/stdlib/strfmon.3
+++ b/lib/libc/stdlib/strfmon.3
@@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd December 6, 2023
+.Dd November 24, 2025
.Dt STRFMON 3
.Os
.Sh NAME
@@ -182,6 +182,16 @@ function will fail if:
Conversion stopped due to lack of space in the buffer.
.It Bq Er EINVAL
The format string is invalid.
+.It Bq Er EINVAL
+The
+.Cm +
+flag was included in a conversion specification and the locale's
+.Va positive_sign
+and
+.Va negative_sign
+values would both be returned by
+.Xr localeconv 3
+as empty strings.
.It Bq Er ENOMEM
Not enough memory for temporary buffers.
.El
diff --git a/lib/libc/stdlib/strfmon.c b/lib/libc/stdlib/strfmon.c
index caccbdb476b0..2dfc7d99510e 100644
--- a/lib/libc/stdlib/strfmon.c
+++ b/lib/libc/stdlib/strfmon.c
@@ -172,7 +172,9 @@ literal:
flags &= ~(NEED_GROUPING);
continue;
case '+': /* use locale defined signs */
- if (flags & SIGN_POSN_USED)
+ if ((flags & SIGN_POSN_USED) ||
+ ((lc->positive_sign[0] == '\0') &&
+ (lc->negative_sign[0] == '\0')))
goto format_error;
flags |= (SIGN_POSN_USED | LOCALE_POSN);
continue;
diff --git a/lib/libc/tests/stdlib/strfmon_test.c b/lib/libc/tests/stdlib/strfmon_test.c
index 0126c2f3f8a8..7fc0afc9e229 100644
--- a/lib/libc/tests/stdlib/strfmon_test.c
+++ b/lib/libc/tests/stdlib/strfmon_test.c
@@ -235,11 +235,11 @@ ATF_TC_BODY(strfmon_plus_or_parenthesis, tc)
if (setlocale(LC_MONETARY, "C") == NULL)
atf_tc_skip("unable to setlocale(): %s", tests[i].locale);
- /* ATF_CHECK_ERRNO(EINVAL, strfmon(actual, sizeof(actual) - 1,
- "[%+n] [%+n]", 123.45, -123.45)); XXX */
+ ATF_CHECK_ERRNO(EINVAL, strfmon(actual, sizeof(actual) - 1,
+ "[%+n] [%+n]", 123.45, -123.45));
- /* ATF_CHECK_ERRNO(EINVAL, strfmon(actual, sizeof(actual) - 1,
- "[%+i] [%+i]", 123.45, -123.45)); XXX */
+ ATF_CHECK_ERRNO(EINVAL, strfmon(actual, sizeof(actual) - 1,
+ "[%+i] [%+i]", 123.45, -123.45));
}
ATF_TC(strfmon_l);