icu: fix CVE-2017-15422 5839/head
authorHirokazu MORIKAWA <morikw2@gmail.com>
Tue, 27 Mar 2018 08:05:45 +0000 (17:05 +0900)
committerHirokazu MORIKAWA <morikw2@gmail.com>
Tue, 27 Mar 2018 08:05:45 +0000 (17:05 +0900)
[lede-17.01]

Maintainer: me

Compile tested: ar71xx, mips_24kc_gcc-5.4.0_musl-1.1.16, lede-17.01 r3863-fad29d2
Run tested: NONE

Description:
CVE-2017-15422 : integer overflow in icu
https://security-tracker.debian.org/tracker/CVE-2017-15422

Signed-off-by: Hirokazu MORIKAWA <morikw2@gmail.com>
libs/icu/Makefile
libs/icu/patches/CVE-2017-15422.patch [new file with mode: 0644]

index 1635230bb52ff875e94c5e10487f8d545e4e1f3f..2fb0a85593e4ca8995373f969ed80c463d19f700 100644 (file)
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
 
 PKG_NAME:=icu4c
 PKG_VERSION:=58.2
-PKG_RELEASE:=3
+PKG_RELEASE:=4
 
 PKG_SOURCE:=$(PKG_NAME)-58_2-src.tgz
 PKG_SOURCE_URL:=http://download.icu-project.org/files/$(PKG_NAME)/$(PKG_VERSION)
diff --git a/libs/icu/patches/CVE-2017-15422.patch b/libs/icu/patches/CVE-2017-15422.patch
new file mode 100644 (file)
index 0000000..50e6f25
--- /dev/null
@@ -0,0 +1,106 @@
+Index: source/i18n/gregoimp.cpp
+===================================================================
+--- source/i18n/gregoimp.cpp   (revision 40653)
++++ source/i18n/gregoimp.cpp   (revision 40654)
+@@ -24,4 +24,9 @@
+ int32_t ClockMath::floorDivide(int32_t numerator, int32_t denominator) {
++    return (numerator >= 0) ?
++        numerator / denominator : ((numerator + 1) / denominator) - 1;
++}
++
++int64_t ClockMath::floorDivide(int64_t numerator, int64_t denominator) {
+     return (numerator >= 0) ?
+         numerator / denominator : ((numerator + 1) / denominator) - 1;
+Index: source/i18n/gregoimp.h
+===================================================================
+--- source/i18n/gregoimp.h     (revision 40653)
++++ source/i18n/gregoimp.h     (revision 40654)
+@@ -40,4 +40,15 @@
+      */
+     static int32_t floorDivide(int32_t numerator, int32_t denominator);
++
++    /**
++     * Divide two integers, returning the floor of the quotient.
++     * Unlike the built-in division, this is mathematically
++     * well-behaved.  E.g., <code>-1/4</code> => 0 but
++     * <code>floorDivide(-1,4)</code> => -1.
++     * @param numerator the numerator
++     * @param denominator a divisor which must be != 0
++     * @return the floor of the quotient
++     */
++    static int64_t floorDivide(int64_t numerator, int64_t denominator);
+     /**
+Index: source/i18n/persncal.cpp
+===================================================================
+--- source/i18n/persncal.cpp   (revision 40653)
++++ source/i18n/persncal.cpp   (revision 40654)
+@@ -214,5 +214,5 @@
+     int32_t daysSinceEpoch = julianDay - PERSIAN_EPOCH;
+-    year = 1 + ClockMath::floorDivide(33 * daysSinceEpoch + 3, 12053);
++    year = 1 + (int32_t)ClockMath::floorDivide(33 * (int64_t)daysSinceEpoch + 3, (int64_t)12053);
+     int32_t farvardin1 = 365 * (year - 1) + ClockMath::floorDivide(8 * year + 21, 33);
+Index: source/test/intltest/calregts.cpp
+===================================================================
+--- source/test/intltest/calregts.cpp  (revision 40653)
++++ source/test/intltest/calregts.cpp  (revision 40654)
+@@ -13,4 +13,5 @@
+ #include "calregts.h"
++#include "unicode/calendar.h"
+ #include "unicode/gregocal.h"
+ #include "unicode/simpletz.h"
+@@ -91,4 +92,5 @@
+         CASE(49,Test9019);
+         CASE(50,TestT9452);
++        CASE(51,TestPersianCalOverflow);
+     default: name = ""; break;
+     }
+@@ -2946,4 +2948,34 @@
+     }
+ }
++
++/**
++ * @bug ticket 13454
++ */
++void CalendarRegressionTest::TestPersianCalOverflow(void) {
++    const char* localeID = "bs_Cyrl@calendar=persian";
++    UErrorCode status = U_ZERO_ERROR;
++    Calendar* cal = Calendar::createInstance(Locale(localeID), status);
++    if(U_FAILURE(status)) {
++        dataerrln("FAIL: Calendar::createInstance for localeID %s: %s", localeID, u_errorName(status));
++    } else {
++        int32_t maxMonth = cal->getMaximum(UCAL_MONTH);
++        int32_t maxDayOfMonth = cal->getMaximum(UCAL_DATE);
++        int32_t jd, month, dayOfMonth;
++        for (jd = 67023580; jd <= 67023584; jd++) { // year 178171, int32_t overflow if jd >= 67023582
++            status = U_ZERO_ERROR;
++            cal->clear();
++            cal->set(UCAL_JULIAN_DAY, jd);
++            month = cal->get(UCAL_MONTH, status);
++            dayOfMonth = cal->get(UCAL_DATE, status);
++            if ( U_FAILURE(status) ) {
++                errln("FAIL: Calendar->get MONTH/DATE for localeID %s, julianDay %d, status %s\n", localeID, jd, u_errorName(status)); 
++            } else if (month > maxMonth || dayOfMonth > maxDayOfMonth) {
++                errln("FAIL: localeID %s, julianDay %d; maxMonth %d, got month %d; maxDayOfMonth %d, got dayOfMonth %d\n",
++                        localeID, jd, maxMonth, month, maxDayOfMonth, dayOfMonth); 
++            }
++        }
++        delete cal;
++    }
++}
+ #endif /* #if !UCONFIG_NO_FORMATTING */
+Index: source/test/intltest/calregts.h
+===================================================================
+--- source/test/intltest/calregts.h    (revision 40653)
++++ source/test/intltest/calregts.h    (revision 40654)
+@@ -78,4 +78,5 @@
+     void Test9019(void);
+     void TestT9452(void);
++    void TestPersianCalOverflow(void);
+     void printdate(GregorianCalendar *cal, const char *string);