From afc4a482123dd98e555ce40272ca888ceabe552e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= Date: Fri, 24 Apr 2026 12:41:21 +0000 Subject: [PATCH] more langtag length limits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Caolán McNamara Change-Id: Ie6a84f836be42e4edc16871d8d4dd12a99046d38 Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/1592 Tested-by: Jenkins CPCI (cherry picked from commit cca41c7cfbfb77777fe8a58be53f6f2ba84638ab) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/207068 Tested-by: Jenkins Reviewed-by: Julien Nabet --- i18nlangtag/qa/cppunit/test_languagetag.cxx | 36 +++++++++++++++++++ .../source/languagetag/languagetag.cxx | 8 +++-- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/i18nlangtag/qa/cppunit/test_languagetag.cxx b/i18nlangtag/qa/cppunit/test_languagetag.cxx index b2ee760fb404..657ddc1d5aa4 100644 --- a/i18nlangtag/qa/cppunit/test_languagetag.cxx +++ b/i18nlangtag/qa/cppunit/test_languagetag.cxx @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -37,6 +38,8 @@ public: void testDisplayNames(); void testLanguagesWithoutHyphenation(); void testLongBcp47ToStackString(); + void testLongLanguageToStackString(); + void testLongLanguageCountryToStackString(); CPPUNIT_TEST_SUITE(TestLanguageTag); CPPUNIT_TEST(testAllTags); @@ -44,6 +47,8 @@ public: CPPUNIT_TEST(testDisplayNames); CPPUNIT_TEST(testLanguagesWithoutHyphenation); CPPUNIT_TEST(testLongBcp47ToStackString); + CPPUNIT_TEST(testLongLanguageToStackString); + CPPUNIT_TEST(testLongLanguageCountryToStackString); CPPUNIT_TEST_SUITE_END(); }; @@ -1109,6 +1114,37 @@ void TestLanguageTag::testLongBcp47ToStackString() CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aBuf.getLength()); } +OUString makeRepeated(sal_Unicode c, sal_Int32 n) +{ + OUStringBuffer aBuf(n); + for (sal_Int32 i = 0; i < n; ++i) + aBuf.append(c); + return aBuf.makeStringAndClear(); +} + +void TestLanguageTag::testLongLanguageToStackString() +{ + // A non-qlt locale with an overlong Language field and no Country + // must not overflow the StackString64 buffer. + lang::Locale aLocale; + aLocale.Language = makeRepeated(u'a', 80); + StackString64 aBuf; + LanguageTag::convertToBcp47(aBuf, aLocale, false); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aBuf.getLength()); +} + +void TestLanguageTag::testLongLanguageCountryToStackString() +{ + // A non-qlt locale whose Language + "-" + Country exceeds the + // StackString64 buffer must not overflow. + lang::Locale aLocale; + aLocale.Language = makeRepeated(u'a', 40); + aLocale.Country = makeRepeated(u'B', 40); + StackString64 aBuf; + LanguageTag::convertToBcp47(aBuf, aLocale, false); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aBuf.getLength()); +} + CPPUNIT_TEST_SUITE_REGISTRATION( TestLanguageTag ); } diff --git a/i18nlangtag/source/languagetag/languagetag.cxx b/i18nlangtag/source/languagetag/languagetag.cxx index 2f7258f7c1ac..8894d44f81b1 100644 --- a/i18nlangtag/source/languagetag/languagetag.cxx +++ b/i18nlangtag/source/languagetag/languagetag.cxx @@ -2892,6 +2892,7 @@ static void appendAscii(StackString64& rBuf, const OUString& s) // static void LanguageTagImpl::convertToBcp47( StackString64& rBuf, const css::lang::Locale& rLocale ) { + assert(rBuf.getLength() == 0); if (rLocale.Language.isEmpty()) { // aBcp47 stays empty @@ -2907,8 +2908,11 @@ void LanguageTagImpl::convertToBcp47( StackString64& rBuf, const css::lang::Loca * now just concatenate language and country. In case we stumbled over * variant aware code we'd have to take care of that. */ if (rLocale.Country.isEmpty()) - appendAscii(rBuf, rLocale.Language); - else + { + if (rLocale.Language.getLength() < 64) + appendAscii(rBuf, rLocale.Language); + } + else if (rLocale.Language.getLength() + 1 + rLocale.Country.getLength() < 64) { appendAscii(rBuf, rLocale.Language); rBuf.append("-");