From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id B17A9158090 for ; Wed, 18 May 2022 11:13:10 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 02489E08AD; Wed, 18 May 2022 11:13:10 +0000 (UTC) Received: from smtp.gentoo.org (woodpecker.gentoo.org [140.211.166.183]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id D3F68E08AD for ; Wed, 18 May 2022 11:13:09 +0000 (UTC) Received: from oystercatcher.gentoo.org (oystercatcher.gentoo.org [148.251.78.52]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id A8B25341594 for ; Wed, 18 May 2022 11:13:08 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id 1AB23105 for ; Wed, 18 May 2022 11:13:07 +0000 (UTC) From: "Andreas Sturmlechner" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Andreas Sturmlechner" Message-ID: <1652872373.3d3cad32d1310cafeeed46b374ef3120c0195ff7.asturm@gentoo> Subject: [gentoo-commits] repo/gentoo:master commit in: dev-libs/icu/, dev-libs/icu/files/ X-VCS-Repository: repo/gentoo X-VCS-Files: dev-libs/icu/files/icu-71.1-CVE-2022-1638.patch dev-libs/icu/icu-71.1-r1.ebuild X-VCS-Directories: dev-libs/icu/ dev-libs/icu/files/ X-VCS-Committer: asturm X-VCS-Committer-Name: Andreas Sturmlechner X-VCS-Revision: 3d3cad32d1310cafeeed46b374ef3120c0195ff7 X-VCS-Branch: master Date: Wed, 18 May 2022 11:13:07 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-Archives-Salt: 413f38dd-f23f-43f6-b4f2-158fc043c6df X-Archives-Hash: e57a57028d8680514a60b8dc01f07819 commit: 3d3cad32d1310cafeeed46b374ef3120c0195ff7 Author: Andreas Sturmlechner gentoo org> AuthorDate: Wed May 18 10:54:00 2022 +0000 Commit: Andreas Sturmlechner gentoo org> CommitDate: Wed May 18 11:12:53 2022 +0000 URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=3d3cad32 dev-libs/icu: Fix CVE-2022-1638 Bug: https://bugs.gentoo.org/843731 Package-Manager: Portage-3.0.30, Repoman-3.0.3 Signed-off-by: Andreas Sturmlechner gentoo.org> dev-libs/icu/files/icu-71.1-CVE-2022-1638.patch | 202 ++++++++++++++++++++++++ dev-libs/icu/icu-71.1-r1.ebuild | 154 ++++++++++++++++++ 2 files changed, 356 insertions(+) diff --git a/dev-libs/icu/files/icu-71.1-CVE-2022-1638.patch b/dev-libs/icu/files/icu-71.1-CVE-2022-1638.patch new file mode 100644 index 000000000000..216ed7894473 --- /dev/null +++ b/dev-libs/icu/files/icu-71.1-CVE-2022-1638.patch @@ -0,0 +1,202 @@ +From e96e9410bde06962c211fa6f21c3d91263a90f86 Mon Sep 17 00:00:00 2001 +From: Frank Tang +Date: Fri, 29 Apr 2022 22:50:33 +0000 +Subject: [PATCH] ICU-22005 Fix int32 overflow in FormattedStringBuilder + +See #2070 +--- + .../i18n/formatted_string_builder.cpp | 55 +++++++++++++------ + .../formatted_string_builder_test.cpp | 41 ++++++++++++++ + 2 files changed, 79 insertions(+), 17 deletions(-) + +diff --git a/i18n/formatted_string_builder.cpp b/i18n/formatted_string_builder.cpp +index 734078644b8..628fbea8711 100644 +--- a/i18n/formatted_string_builder.cpp ++++ b/i18n/formatted_string_builder.cpp +@@ -6,6 +6,7 @@ + #if !UCONFIG_NO_FORMATTING + + #include "formatted_string_builder.h" ++#include "putilimp.h" + #include "unicode/ustring.h" + #include "unicode/utf16.h" + #include "unicode/unum.h" // for UNumberFormatFields literals +@@ -197,6 +198,9 @@ FormattedStringBuilder::splice(int32_t startThis, int32_t endThis, const Unicod + int32_t thisLength = endThis - startThis; + int32_t otherLength = endOther - startOther; + int32_t count = otherLength - thisLength; ++ if (U_FAILURE(status)) { ++ return count; ++ } + int32_t position; + if (count > 0) { + // Overall, chars need to be added. +@@ -221,6 +225,9 @@ int32_t FormattedStringBuilder::append(const FormattedStringBuilder &other, UErr + + int32_t + FormattedStringBuilder::insert(int32_t index, const FormattedStringBuilder &other, UErrorCode &status) { ++ if (U_FAILURE(status)) { ++ return 0; ++ } + if (this == &other) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; +@@ -255,12 +262,18 @@ int32_t FormattedStringBuilder::prepareForInsert(int32_t index, int32_t count, U + U_ASSERT(index >= 0); + U_ASSERT(index <= fLength); + U_ASSERT(count >= 0); ++ U_ASSERT(fZero >= 0); ++ U_ASSERT(fLength >= 0); ++ U_ASSERT(getCapacity() - fZero >= fLength); ++ if (U_FAILURE(status)) { ++ return count; ++ } + if (index == 0 && fZero - count >= 0) { + // Append to start + fZero -= count; + fLength += count; + return fZero; +- } else if (index == fLength && fZero + fLength + count < getCapacity()) { ++ } else if (index == fLength && count <= getCapacity() - fZero - fLength) { + // Append to end + fLength += count; + return fZero + fLength - count; +@@ -275,18 +288,26 @@ int32_t FormattedStringBuilder::prepareForInsertHelper(int32_t index, int32_t co + int32_t oldZero = fZero; + char16_t *oldChars = getCharPtr(); + Field *oldFields = getFieldPtr(); +- if (fLength + count > oldCapacity) { +- if ((fLength + count) > INT32_MAX / 2) { +- // If we continue, then newCapacity will overflow int32_t in the next line. ++ int32_t newLength; ++ if (uprv_add32_overflow(fLength, count, &newLength)) { ++ status = U_INPUT_TOO_LONG_ERROR; ++ return -1; ++ } ++ int32_t newZero; ++ if (newLength > oldCapacity) { ++ if (newLength > INT32_MAX / 2) { ++ // We do not support more than 1G char16_t in this code because ++ // dealing with >2G *bytes* can cause subtle bugs. + status = U_INPUT_TOO_LONG_ERROR; + return -1; + } +- int32_t newCapacity = (fLength + count) * 2; +- int32_t newZero = newCapacity / 2 - (fLength + count) / 2; ++ // Keep newCapacity also to at most 1G char16_t. ++ int32_t newCapacity = newLength * 2; ++ newZero = (newCapacity - newLength) / 2; + + // C++ note: malloc appears in two places: here and in the assignment operator. +- auto newChars = static_cast (uprv_malloc(sizeof(char16_t) * newCapacity)); +- auto newFields = static_cast(uprv_malloc(sizeof(Field) * newCapacity)); ++ auto newChars = static_cast (uprv_malloc(sizeof(char16_t) * static_cast(newCapacity))); ++ auto newFields = static_cast(uprv_malloc(sizeof(Field) * static_cast(newCapacity))); + if (newChars == nullptr || newFields == nullptr) { + uprv_free(newChars); + uprv_free(newFields); +@@ -315,10 +336,8 @@ int32_t FormattedStringBuilder::prepareForInsertHelper(int32_t index, int32_t co + fChars.heap.capacity = newCapacity; + fFields.heap.ptr = newFields; + fFields.heap.capacity = newCapacity; +- fZero = newZero; +- fLength += count; + } else { +- int32_t newZero = oldCapacity / 2 - (fLength + count) / 2; ++ newZero = (oldCapacity - newLength) / 2; + + // C++ note: memmove is required because src and dest may overlap. + // First copy the entire string to the location of the prefix, and then move the suffix +@@ -331,18 +350,20 @@ int32_t FormattedStringBuilder::prepareForInsertHelper(int32_t index, int32_t co + uprv_memmove2(oldFields + newZero + index + count, + oldFields + newZero + index, + sizeof(Field) * (fLength - index)); +- +- fZero = newZero; +- fLength += count; + } +- U_ASSERT((fZero + index) >= 0); ++ fZero = newZero; ++ fLength = newLength; + return fZero + index; + } + + int32_t FormattedStringBuilder::remove(int32_t index, int32_t count) { +- // TODO: Reset the heap here? (If the string after removal can fit on stack?) ++ U_ASSERT(0 <= index); ++ U_ASSERT(index <= fLength); ++ U_ASSERT(count <= (fLength - index)); ++ U_ASSERT(index <= getCapacity() - fZero); ++ + int32_t position = index + fZero; +- U_ASSERT(position >= 0); ++ // TODO: Reset the heap here? (If the string after removal can fit on stack?) + uprv_memmove2(getCharPtr() + position, + getCharPtr() + position + count, + sizeof(char16_t) * (fLength - index - count)); +diff --git a/test/intltest/formatted_string_builder_test.cpp b/test/intltest/formatted_string_builder_test.cpp +index 45721a320ac..57294e24856 100644 +--- a/test/intltest/formatted_string_builder_test.cpp ++++ b/test/intltest/formatted_string_builder_test.cpp +@@ -22,6 +22,7 @@ class FormattedStringBuilderTest : public IntlTest { + void testFields(); + void testUnlimitedCapacity(); + void testCodePoints(); ++ void testInsertOverflow(); + + void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override; + +@@ -50,6 +51,7 @@ void FormattedStringBuilderTest::runIndexedTest(int32_t index, UBool exec, const + TESTCASE_AUTO(testFields); + TESTCASE_AUTO(testUnlimitedCapacity); + TESTCASE_AUTO(testCodePoints); ++ TESTCASE_AUTO(testInsertOverflow); + TESTCASE_AUTO_END; + } + +@@ -308,6 +310,45 @@ void FormattedStringBuilderTest::testCodePoints() { + assertEquals("Code point count is 2", 2, nsb.codePointCount()); + } + ++void FormattedStringBuilderTest::testInsertOverflow() { ++ if (quick) return; ++ // Setup the test fixture in sb, sb2, ustr. ++ UErrorCode status = U_ZERO_ERROR; ++ FormattedStringBuilder sb; ++ int32_t data_length = INT32_MAX / 2; ++ UnicodeString ustr(data_length, u'a', data_length); ++ sb.append(ustr, kUndefinedField, status); ++ assertSuccess("Setup the first FormattedStringBuilder", status); ++ ++ FormattedStringBuilder sb2; ++ sb2.append(ustr, kUndefinedField, status); ++ sb2.insert(0, ustr, 0, data_length / 2, kUndefinedField, status); ++ sb2.writeTerminator(status); ++ assertSuccess("Setup the second FormattedStringBuilder", status); ++ ++ ustr = sb2.toUnicodeString(); ++ // Complete setting up the test fixture in sb, sb2 and ustr. ++ ++ // Test splice() of the second UnicodeString ++ sb.splice(0, 1, ustr, 1, ustr.length(), ++ kUndefinedField, status); ++ assertEquals( ++ "splice() long text should not crash but return U_INPUT_TOO_LONG_ERROR", ++ U_INPUT_TOO_LONG_ERROR, status); ++ ++ // Test sb.insert() of the first FormattedStringBuilder with the second one. ++ sb.insert(0, sb2, status); ++ assertEquals( ++ "insert() long FormattedStringBuilder should not crash but return " ++ "U_INPUT_TOO_LONG_ERROR", U_INPUT_TOO_LONG_ERROR, status); ++ ++ // Test sb.insert() of the first FormattedStringBuilder with UnicodeString. ++ sb.insert(0, ustr, 0, ustr.length(), kUndefinedField, status); ++ assertEquals( ++ "insert() long UnicodeString should not crash but return " ++ "U_INPUT_TOO_LONG_ERROR", U_INPUT_TOO_LONG_ERROR, status); ++} ++ + void FormattedStringBuilderTest::assertEqualsImpl(const UnicodeString &a, const FormattedStringBuilder &b) { + // TODO: Why won't this compile without the IntlTest:: qualifier? + IntlTest::assertEquals("Lengths should be the same", a.length(), b.length()); diff --git a/dev-libs/icu/icu-71.1-r1.ebuild b/dev-libs/icu/icu-71.1-r1.ebuild new file mode 100644 index 000000000000..584c243c2e41 --- /dev/null +++ b/dev-libs/icu/icu-71.1-r1.ebuild @@ -0,0 +1,154 @@ +# Copyright 1999-2022 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +# Please bump with dev-libs/icu-layoutex + +PYTHON_COMPAT=( python3_{8..10} ) +VERIFY_SIG_OPENPGP_KEY_PATH="${BROOT}"/usr/share/openpgp-keys/icu.asc +inherit autotools flag-o-matic multilib-minimal python-any-r1 toolchain-funcs verify-sig + +DESCRIPTION="International Components for Unicode" +HOMEPAGE="https://icu.unicode.org/" +SRC_URI="https://github.com/unicode-org/icu/releases/download/release-${PV//./-}/icu4c-${PV//./_}-src.tgz" +SRC_URI+=" verify-sig? ( https://github.com/unicode-org/icu/releases/download/release-${PV//./-}/icu4c-${PV//./_}-src.tgz.asc )" +S="${WORKDIR}/${PN}/source" + +LICENSE="BSD" +SLOT="0/${PV}" +KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~loong ~m68k ~mips ~ppc ~ppc64 ~riscv ~s390 ~sparc ~x86 ~amd64-linux ~x86-linux ~ppc-macos ~x64-macos ~sparc-solaris ~sparc64-solaris ~x64-solaris ~x86-solaris ~x86-winnt" +IUSE="debug doc examples static-libs test" +RESTRICT="!test? ( test )" + +BDEPEND="${PYTHON_DEPS} + sys-devel/autoconf-archive + virtual/pkgconfig + doc? ( app-doc/doxygen[dot] ) + verify-sig? ( sec-keys/openpgp-keys-icu ) +" + +MULTILIB_CHOST_TOOLS=( + /usr/bin/icu-config +) + +PATCHES=( + "${FILESDIR}/${PN}-65.1-remove-bashisms.patch" + "${FILESDIR}/${PN}-64.2-darwin.patch" + "${FILESDIR}/${PN}-68.1-nonunicode.patch" + "${FILESDIR}/${P}-CVE-2022-1638.patch" # bug 843731 +) + +src_prepare() { + default + + # Disable renaming as it assumes stable ABI and that consumers + # won't use unofficial APIs. We need this despite the configure argument. + sed -i \ + -e "s/#define U_DISABLE_RENAMING 0/#define U_DISABLE_RENAMING 1/" \ + common/unicode/uconfig.h || die + + # Fix linking of icudata + sed -i \ + -e "s:LDFLAGSICUDT=-nodefaultlibs -nostdlib:LDFLAGSICUDT=:" \ + config/mh-linux || die + + # Append doxygen configuration to configure + sed -i \ + -e 's:icudefs.mk:icudefs.mk Doxyfile:' \ + configure.ac || die + + eautoreconf +} + +src_configure() { + # ICU tries to append -std=c++11 without this, so as of 71.1, + # despite GCC 9+ using c++14 (or gnu++14) and GCC 11+ using gnu++17, + # we still need this. + append-cxxflags -std=c++14 + + if tc-is-cross-compiler; then + mkdir "${WORKDIR}"/host || die + pushd "${WORKDIR}"/host >/dev/null || die + + CFLAGS="" CXXFLAGS="" ASFLAGS="" LDFLAGS="" \ + CC="$(tc-getBUILD_CC)" CXX="$(tc-getBUILD_CXX)" AR="$(tc-getBUILD_AR)" \ + RANLIB="$(tc-getBUILD_RANLIB)" LD="$(tc-getBUILD_LD)" \ + "${S}"/configure --disable-renaming --disable-debug \ + --disable-samples --enable-static || die + emake + + popd >/dev/null || die + fi + + multilib-minimal_src_configure +} + +multilib_src_configure() { + local myeconfargs=( + --disable-renaming + --disable-samples + --disable-layoutex + $(use_enable debug) + $(use_enable static-libs static) + $(use_enable test tests) + $(multilib_native_use_enable examples samples) + ) + + tc-is-cross-compiler && myeconfargs+=( + --with-cross-build="${WORKDIR}"/host + ) + + # Work around cross-endian testing failures with LTO #757681 + if tc-is-cross-compiler && is-flagq '-flto*' ; then + myeconfargs+=( --disable-strict ) + fi + + # ICU tries to use clang by default + tc-export CC CXX + + # Make sure we configure with the same shell as we run icu-config + # with, or ECHO_N, ECHO_T and ECHO_C will be wrongly defined + export CONFIG_SHELL="${EPREFIX}/bin/sh" + # Probably have no /bin/sh in prefix-chain + [[ -x ${CONFIG_SHELL} ]] || CONFIG_SHELL="${BASH}" + + ECONF_SOURCE="${S}" econf "${myeconfargs[@]}" +} + +multilib_src_compile() { + default + + if multilib_is_native_abi && use doc; then + doxygen -u Doxyfile || die + doxygen Doxyfile || die + fi +} + +multilib_src_test() { + # INTLTEST_OPTS: intltest options + # -e: Exhaustive testing + # -l: Reporting of memory leaks + # -v: Increased verbosity + # IOTEST_OPTS: iotest options + # -e: Exhaustive testing + # -v: Increased verbosity + # CINTLTST_OPTS: cintltst options + # -e: Exhaustive testing + # -v: Increased verbosity + emake -j1 VERBOSE="1" check +} + +multilib_src_install() { + default + + if multilib_is_native_abi && use doc; then + docinto html + dodoc -r doc/html/* + fi +} + +multilib_src_install_all() { + local HTML_DOCS=( ../readme.html ) + einstalldocs +}