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
This commit is contained in:
Jose Luis Duran
2025-11-26 20:34:55 +00:00
parent 19e153004f
commit 1fd018972a
3 changed files with 18 additions and 6 deletions
+11 -1
View File
@@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE. .\" SUCH DAMAGE.
.\" .\"
.Dd December 6, 2023 .Dd November 24, 2025
.Dt STRFMON 3 .Dt STRFMON 3
.Os .Os
.Sh NAME .Sh NAME
@@ -182,6 +182,16 @@ function will fail if:
Conversion stopped due to lack of space in the buffer. Conversion stopped due to lack of space in the buffer.
.It Bq Er EINVAL .It Bq Er EINVAL
The format string is invalid. 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 .It Bq Er ENOMEM
Not enough memory for temporary buffers. Not enough memory for temporary buffers.
.El .El
+3 -1
View File
@@ -171,7 +171,9 @@ vstrfmon_l(char *__restrict s, size_t maxsize, locale_t loc,
flags &= ~(NEED_GROUPING); flags &= ~(NEED_GROUPING);
continue; continue;
case '+': /* use locale defined signs */ 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; goto format_error;
flags |= (SIGN_POSN_USED | LOCALE_POSN); flags |= (SIGN_POSN_USED | LOCALE_POSN);
continue; continue;
+4 -4
View File
@@ -234,11 +234,11 @@ ATF_TC_BODY(strfmon_plus_or_parenthesis, tc)
if (setlocale(LC_MONETARY, "C") == NULL) if (setlocale(LC_MONETARY, "C") == NULL)
atf_tc_skip("unable to setlocale(): %s", tests[i].locale); atf_tc_skip("unable to setlocale(): %s", tests[i].locale);
/* ATF_CHECK_ERRNO(EINVAL, strfmon(actual, sizeof(actual) - 1, ATF_CHECK_ERRNO(EINVAL, strfmon(actual, sizeof(actual) - 1,
"[%+n] [%+n]", 123.45, -123.45)); XXX */ "[%+n] [%+n]", 123.45, -123.45));
/* ATF_CHECK_ERRNO(EINVAL, strfmon(actual, sizeof(actual) - 1, ATF_CHECK_ERRNO(EINVAL, strfmon(actual, sizeof(actual) - 1,
"[%+i] [%+i]", 123.45, -123.45)); XXX */ "[%+i] [%+i]", 123.45, -123.45));
} }
ATF_TC(strfmon_l); ATF_TC(strfmon_l);