git: 9e03b903e377 - main - strfmon: Avoid an out-of-bounds access

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Tue, 25 Oct 2022 21:51:25 UTC
The branch main has been updated by kib:

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

commit 9e03b903e377c75a60cbbb89ed78955769a1c804
Author:     Jose Luis Duran <jlduran@gmail.com>
AuthorDate: 2022-10-13 15:51:27 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2022-10-25 21:40:17 +0000

    strfmon: Avoid an out-of-bounds access
    
    Avoid an out-of-bounds access when trying to set the space_char using an
    international currency format (%i) and the C/POSIX locale.
    
    The current code tries to read the SPACE from int_curr_symbol[3]:
    
        currency_symbol = strdup(lc->int_curr_symbol);
        space_char = *(currency_symbol+3);
    
    But on C/POSIX locales, int_curr_symbol is empty.
    
    Three implementations have been examined: NetBSD[1], Darwin[2], and
    Illumos[3].  Only NetBSD has fixed it[4].
    
    Darwin and NetBSD also trim the mandatory final SPACE character after
    reading it.
    
        Locale         Format    Darwin/NetBSD    FreeBSD/Illumos
        en_US.UTF-8    [%i]      [USD123.45]      [USD 123.45]
        fr_FR.UTF-8    [%i]      [123,45 EUR]     [123,45 EUR ]
    
    This commit only fixes the out-of-bounds access.
    
    [1]: https://github.com/NetBSD/src/blob/trunk/lib/libc/stdlib/strfmon.c
    [2]: https://opensource.apple.com/source/Libc/Libc-1439.141.1/stdlib/NetBSD/strfmon.c.auto.html
    [3]: https://github.com/illumos/illumos-gate/blob/master/usr/src/lib/libc/port/locale/strfmon.c
    [4]: https://github.com/NetBSD/src/commit/3d7b5d498aa9609f2bc9ece9c734c5f493a8e239
    
    Reviewed by:    kib
    PR:     267282
    Github PR:      #619
    MFC after:      1 week
---
 lib/libc/stdlib/strfmon.c            | 5 +++--
 lib/libc/tests/stdlib/strfmon_test.c | 2 +-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/lib/libc/stdlib/strfmon.c b/lib/libc/stdlib/strfmon.c
index fbb1f79a87d5..2526ab8fd8b1 100644
--- a/lib/libc/stdlib/strfmon.c
+++ b/lib/libc/stdlib/strfmon.c
@@ -239,8 +239,9 @@ vstrfmon_l(char * __restrict s, size_t maxsize, locale_t loc,
 			free(currency_symbol);
 		if (flags & USE_INTL_CURRENCY) {
 			currency_symbol = strdup(lc->int_curr_symbol);
-			if (currency_symbol != NULL)
-				space_char = *(currency_symbol+3);
+			if (currency_symbol != NULL &&
+			    strlen(currency_symbol) > 3)
+				space_char = currency_symbol[3];
 		} else
 			currency_symbol = strdup(lc->currency_symbol);
 
diff --git a/lib/libc/tests/stdlib/strfmon_test.c b/lib/libc/tests/stdlib/strfmon_test.c
index 3e77a4f5290f..dc328e974bb8 100644
--- a/lib/libc/tests/stdlib/strfmon_test.c
+++ b/lib/libc/tests/stdlib/strfmon_test.c
@@ -197,7 +197,7 @@ ATF_TC_BODY(strfmon_international_currency_code, tc)
 	} tests[] = {
 	    { "en_US.UTF-8", "[USD 123.45]" }, /* XXX */
 	    { "de_DE.UTF-8", "[123,45 EUR ]" }, /* XXX */
-	    { "C", "[123.45]" }, /* XXX OOB access */
+	    { "C", "[123.45]" },
 	};
 	size_t i;
 	char actual[100];