diff -Nru icu-52.1/debian/changelog icu-52.1/debian/changelog --- icu-52.1/debian/changelog 2015-09-11 13:28:05.000000000 +0000 +++ icu-52.1/debian/changelog 2017-03-10 16:41:35.000000000 +0000 @@ -1,3 +1,21 @@ +icu (52.1-3ubuntu0.5) trusty-security; urgency=medium + + * SECURITY UPDATE: Multiple security issues. Synchronize security fixes + with Debian's 52.1-8+deb8u4 release. Thanks to Laszlo Boszormenyi for + the work this update is based on. + - debian/patches/CVE-2014-9911.patch + - debian/patches/CVE-2015-4844.patch + - debian/patches/CVE-2016-0494.patch + - debian/patches/CVE-2016-6293.patch + - debian/patches/CVE-2016-7415.patch + - CVE-2014-9911 + - CVE-2015-4844 + - CVE-2016-0494 + - CVE-2016-6293 + - CVE-2016-7415 + + -- Marc Deslauriers Fri, 10 Mar 2017 11:41:10 -0500 + icu (52.1-3ubuntu0.4) trusty-security; urgency=medium * SECURITY UPDATE: denial of service via mishandling of converter names diff -Nru icu-52.1/debian/patches/CVE-2014-9911.patch icu-52.1/debian/patches/CVE-2014-9911.patch --- icu-52.1/debian/patches/CVE-2014-9911.patch 1970-01-01 00:00:00.000000000 +0000 +++ icu-52.1/debian/patches/CVE-2014-9911.patch 2017-03-10 16:40:29.000000000 +0000 @@ -0,0 +1,44 @@ +Index: source/common/uresbund.cpp +=================================================================== +--- a/source/common/uresbund.cpp (revision 35698) ++++ b/source/common/uresbund.cpp (revision 35699) +@@ -1,5 +1,5 @@ + /* + ****************************************************************************** +-* Copyright (C) 1997-2013, International Business Machines Corporation and ++* Copyright (C) 1997-2014, International Business Machines Corporation and + * others. All Rights Reserved. + ****************************************************************************** +@@ -37,4 +37,5 @@ + #include "uassert.h" + ++using namespace icu; + + /* +@@ -1733,6 +1734,6 @@ + if(res == RES_BOGUS) { + UResourceDataEntry *dataEntry = resB->fData; +- char path[256]; +- char* myPath = path; ++ CharString path; ++ char *myPath = NULL; + const char* resPath = resB->fResPath; + int32_t len = resB->fResPathLen; +@@ -1742,9 +1743,14 @@ + + if(dataEntry->fBogus == U_ZERO_ERROR) { ++ path.clear(); + if (len > 0) { +- uprv_memcpy(path, resPath, len); ++ path.append(resPath, len, *status); + } +- uprv_strcpy(path+len, inKey); +- myPath = path; ++ path.append(inKey, *status); ++ if (U_FAILURE(*status)) { ++ ures_close(helper); ++ return fillIn; ++ } ++ myPath = path.data(); + key = inKey; + do { diff -Nru icu-52.1/debian/patches/CVE-2015-4844.patch icu-52.1/debian/patches/CVE-2015-4844.patch --- icu-52.1/debian/patches/CVE-2015-4844.patch 1970-01-01 00:00:00.000000000 +0000 +++ icu-52.1/debian/patches/CVE-2015-4844.patch 2017-03-10 16:40:39.000000000 +0000 @@ -0,0 +1,570 @@ +Description: backport of CVE-2015-4844 patch from JDK + CVE-2015-4844 was fixed through dbb4e2bdfa9e in JDK, but never + backported to ICU. This patch is a port that removes a chunk that + doesn't apply. That chunk (documented in ticket #12020 upstream) is + not necessary because the inner loop does the check and in 4.4.1, + there are no other statements at the end of the loop. + . + Note that this patch introduces CVE-2016-0494 which requires a + different patch. + +Author: Antoine Beaupré + +--- +The information above should follow the Patch Tagging Guidelines, please +checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here +are templates for supplementary fields that you might want to add: + +Origin: upstream, http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/rev/dbb4e2bdfa9e#l2.15 +Bug: https://ssl.icu-project.org/trac/ticket/12020 +Forwarded: no +Reviewed-By: no +Last-Update: 2016-01-30 + +--- icu-4.4.1.orig/source/layout/IndicRearrangementProcessor.cpp ++++ icu-4.4.1/source/layout/IndicRearrangementProcessor.cpp +@@ -51,14 +51,14 @@ ByteOffset IndicRearrangementProcessor:: + } + + if (flags & irfMarkFirst) { +- firstGlyph = currGlyph; ++ firstGlyph = (le_uint32)currGlyph; + } + + if (flags & irfMarkLast) { +- lastGlyph = currGlyph; ++ lastGlyph = (le_uint32)currGlyph; + } + +- doRearrangementAction(glyphStorage, (IndicRearrangementVerb) (flags & irfVerbMask)); ++ doRearrangementAction(glyphStorage, (IndicRearrangementVerb) (flags & irfVerbMask), success); + + if (!(flags & irfDontAdvance)) { + // XXX: Should handle reverse too... +@@ -72,18 +72,29 @@ void IndicRearrangementProcessor::endSta + { + } + +-void IndicRearrangementProcessor::doRearrangementAction(LEGlyphStorage &glyphStorage, IndicRearrangementVerb verb) const ++void IndicRearrangementProcessor::doRearrangementAction(LEGlyphStorage &glyphStorage, IndicRearrangementVerb verb, LEErrorCode &success) const + { + LEGlyphID a, b, c, d; + le_int32 ia, ib, ic, id, ix, x; +- LEErrorCode success = LE_NO_ERROR; ++ ++ if (LE_FAILURE(success)) return; ++ ++ if (verb == irvNoAction) { ++ return; ++ } ++ if (firstGlyph > lastGlyph) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ return; ++ } + + switch(verb) + { +- case irvNoAction: +- break; +- + case irvxA: ++ if (firstGlyph == lastGlyph) break; ++ if (firstGlyph + 1 < firstGlyph) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + a = glyphStorage[firstGlyph]; + ia = glyphStorage.getCharIndex(firstGlyph, success); + x = firstGlyph + 1; +@@ -100,6 +111,11 @@ void IndicRearrangementProcessor::doRear + break; + + case irvDx: ++ if (firstGlyph == lastGlyph) break; ++ if (lastGlyph - 1 > lastGlyph) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + d = glyphStorage[lastGlyph]; + id = glyphStorage.getCharIndex(lastGlyph, success); + x = lastGlyph - 1; +@@ -128,6 +144,11 @@ void IndicRearrangementProcessor::doRear + break; + + case irvxAB: ++ if ((firstGlyph + 2 < firstGlyph) || ++ (lastGlyph - firstGlyph < 1)) { // difference == 1 is a no-op, < 1 is an error. ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + a = glyphStorage[firstGlyph]; + b = glyphStorage[firstGlyph + 1]; + ia = glyphStorage.getCharIndex(firstGlyph, success); +@@ -149,6 +170,11 @@ void IndicRearrangementProcessor::doRear + break; + + case irvxBA: ++ if ((firstGlyph + 2 < firstGlyph) || ++ (lastGlyph - firstGlyph < 1)) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + a = glyphStorage[firstGlyph]; + b = glyphStorage[firstGlyph + 1]; + ia = glyphStorage.getCharIndex(firstGlyph, success); +@@ -170,6 +196,11 @@ void IndicRearrangementProcessor::doRear + break; + + case irvCDx: ++ if ((lastGlyph - 2 > lastGlyph) || ++ (lastGlyph - firstGlyph < 1)) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + c = glyphStorage[lastGlyph - 1]; + d = glyphStorage[lastGlyph]; + ic = glyphStorage.getCharIndex(lastGlyph - 1, success); +@@ -191,6 +222,11 @@ void IndicRearrangementProcessor::doRear + break; + + case irvDCx: ++ if ((lastGlyph - 2 > lastGlyph) || ++ (lastGlyph - firstGlyph < 1)) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + c = glyphStorage[lastGlyph - 1]; + d = glyphStorage[lastGlyph]; + ic = glyphStorage.getCharIndex(lastGlyph - 1, success); +@@ -212,6 +248,11 @@ void IndicRearrangementProcessor::doRear + break; + + case irvCDxA: ++ if ((lastGlyph - 2 > lastGlyph) || ++ (lastGlyph - firstGlyph < 2)) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + a = glyphStorage[firstGlyph]; + c = glyphStorage[lastGlyph - 1]; + d = glyphStorage[lastGlyph]; +@@ -237,6 +278,11 @@ void IndicRearrangementProcessor::doRear + break; + + case irvDCxA: ++ if ((lastGlyph - 2 > lastGlyph) || ++ (lastGlyph - firstGlyph < 2)) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + a = glyphStorage[firstGlyph]; + c = glyphStorage[lastGlyph - 1]; + d = glyphStorage[lastGlyph]; +@@ -262,6 +308,11 @@ void IndicRearrangementProcessor::doRear + break; + + case irvDxAB: ++ if ((firstGlyph + 2 < firstGlyph) || ++ (lastGlyph - firstGlyph < 2)) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + a = glyphStorage[firstGlyph]; + b = glyphStorage[firstGlyph + 1]; + d = glyphStorage[lastGlyph]; +@@ -287,6 +338,11 @@ void IndicRearrangementProcessor::doRear + break; + + case irvDxBA: ++ if ((firstGlyph + 2 < firstGlyph) || ++ (lastGlyph - firstGlyph < 2)) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + a = glyphStorage[firstGlyph]; + b = glyphStorage[firstGlyph + 1]; + d = glyphStorage[lastGlyph]; +@@ -312,6 +368,10 @@ void IndicRearrangementProcessor::doRear + break; + + case irvCDxAB: ++ if (lastGlyph - firstGlyph < 3) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + a = glyphStorage[firstGlyph]; + b = glyphStorage[firstGlyph + 1]; + +@@ -334,6 +394,10 @@ void IndicRearrangementProcessor::doRear + break; + + case irvCDxBA: ++ if (lastGlyph - firstGlyph < 3) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + a = glyphStorage[firstGlyph]; + b = glyphStorage[firstGlyph + 1]; + +@@ -356,6 +420,10 @@ void IndicRearrangementProcessor::doRear + break; + + case irvDCxAB: ++ if (lastGlyph - firstGlyph < 3) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + a = glyphStorage[firstGlyph]; + b = glyphStorage[firstGlyph + 1]; + +@@ -378,6 +446,10 @@ void IndicRearrangementProcessor::doRear + break; + + case irvDCxBA: ++ if (lastGlyph - firstGlyph < 3) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + a = glyphStorage[firstGlyph]; + b = glyphStorage[firstGlyph + 1]; + +--- icu-4.4.1.orig/source/layout/IndicRearrangementProcessor.h ++++ icu-4.4.1/source/layout/IndicRearrangementProcessor.h +@@ -31,7 +31,7 @@ public: + + virtual void endStateTable(); + +- void doRearrangementAction(LEGlyphStorage &glyphStorage, IndicRearrangementVerb verb) const; ++ void doRearrangementAction(LEGlyphStorage &glyphStorage, IndicRearrangementVerb verb, LEErrorCode &success) const; + + IndicRearrangementProcessor(const LEReferenceTo &morphSubtableHeader, LEErrorCode &success); + virtual ~IndicRearrangementProcessor(); +@@ -51,8 +51,8 @@ public: + static UClassID getStaticClassID(); + + protected: +- le_int32 firstGlyph; +- le_int32 lastGlyph; ++ le_uint32 firstGlyph; ++ le_uint32 lastGlyph; + + LEReferenceTo indicRearrangementSubtableHeader; + LEReferenceToArrayOf entryTable; +--- icu-4.4.1.orig/source/layout/IndicRearrangementProcessor2.cpp ++++ icu-4.4.1/source/layout/IndicRearrangementProcessor2.cpp +@@ -49,14 +49,14 @@ le_uint16 IndicRearrangementProcessor2:: + } + + if (flags & irfMarkFirst) { +- firstGlyph = currGlyph; ++ firstGlyph = (le_uint32)currGlyph; + } + + if (flags & irfMarkLast) { +- lastGlyph = currGlyph; ++ lastGlyph = (le_uint32)currGlyph; + } + +- doRearrangementAction(glyphStorage, (IndicRearrangementVerb) (flags & irfVerbMask)); ++ doRearrangementAction(glyphStorage, (IndicRearrangementVerb) (flags & irfVerbMask), success); + + if (!(flags & irfDontAdvance)) { + currGlyph += dir; +@@ -69,18 +69,29 @@ void IndicRearrangementProcessor2::endSt + { + } + +-void IndicRearrangementProcessor2::doRearrangementAction(LEGlyphStorage &glyphStorage, IndicRearrangementVerb verb) const ++void IndicRearrangementProcessor2::doRearrangementAction(LEGlyphStorage &glyphStorage, IndicRearrangementVerb verb, LEErrorCode &success) const + { + LEGlyphID a, b, c, d; + le_int32 ia, ib, ic, id, ix, x; +- LEErrorCode success = LE_NO_ERROR; ++ ++ if (LE_FAILURE(success)) return; ++ ++ if (verb == irvNoAction) { ++ return; ++ } ++ if (firstGlyph > lastGlyph) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ return; ++ } + + switch(verb) + { +- case irvNoAction: +- break; +- + case irvxA: ++ if (firstGlyph == lastGlyph) break; ++ if (firstGlyph + 1 < firstGlyph) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + a = glyphStorage[firstGlyph]; + ia = glyphStorage.getCharIndex(firstGlyph, success); + x = firstGlyph + 1; +@@ -97,6 +108,11 @@ void IndicRearrangementProcessor2::doRea + break; + + case irvDx: ++ if (firstGlyph == lastGlyph) break; ++ if (lastGlyph - 1 > lastGlyph) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + d = glyphStorage[lastGlyph]; + id = glyphStorage.getCharIndex(lastGlyph, success); + x = lastGlyph - 1; +@@ -125,6 +141,11 @@ void IndicRearrangementProcessor2::doRea + break; + + case irvxAB: ++ if ((firstGlyph + 2 < firstGlyph) || ++ (lastGlyph - firstGlyph < 1)) { // difference == 1 is a no-op, < 1 is an error. ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + a = glyphStorage[firstGlyph]; + b = glyphStorage[firstGlyph + 1]; + ia = glyphStorage.getCharIndex(firstGlyph, success); +@@ -146,6 +167,11 @@ void IndicRearrangementProcessor2::doRea + break; + + case irvxBA: ++ if ((firstGlyph + 2 < firstGlyph) || ++ (lastGlyph - firstGlyph < 1)) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + a = glyphStorage[firstGlyph]; + b = glyphStorage[firstGlyph + 1]; + ia = glyphStorage.getCharIndex(firstGlyph, success); +@@ -167,6 +193,11 @@ void IndicRearrangementProcessor2::doRea + break; + + case irvCDx: ++ if ((lastGlyph - 2 > lastGlyph) || ++ (lastGlyph - firstGlyph < 1)) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + c = glyphStorage[lastGlyph - 1]; + d = glyphStorage[lastGlyph]; + ic = glyphStorage.getCharIndex(lastGlyph - 1, success); +@@ -188,6 +219,11 @@ void IndicRearrangementProcessor2::doRea + break; + + case irvDCx: ++ if ((lastGlyph - 2 > lastGlyph) || ++ (lastGlyph - firstGlyph < 1)) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + c = glyphStorage[lastGlyph - 1]; + d = glyphStorage[lastGlyph]; + ic = glyphStorage.getCharIndex(lastGlyph - 1, success); +@@ -209,6 +245,11 @@ void IndicRearrangementProcessor2::doRea + break; + + case irvCDxA: ++ if ((lastGlyph - 2 > lastGlyph) || ++ (lastGlyph - firstGlyph < 2)) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + a = glyphStorage[firstGlyph]; + c = glyphStorage[lastGlyph - 1]; + d = glyphStorage[lastGlyph]; +@@ -234,6 +275,11 @@ void IndicRearrangementProcessor2::doRea + break; + + case irvDCxA: ++ if ((lastGlyph - 2 > lastGlyph) || ++ (lastGlyph - firstGlyph < 2)) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + a = glyphStorage[firstGlyph]; + c = glyphStorage[lastGlyph - 1]; + d = glyphStorage[lastGlyph]; +@@ -259,6 +305,11 @@ void IndicRearrangementProcessor2::doRea + break; + + case irvDxAB: ++ if ((firstGlyph + 2 < firstGlyph) || ++ (lastGlyph - firstGlyph < 2)) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + a = glyphStorage[firstGlyph]; + b = glyphStorage[firstGlyph + 1]; + d = glyphStorage[lastGlyph]; +@@ -284,6 +335,11 @@ void IndicRearrangementProcessor2::doRea + break; + + case irvDxBA: ++ if ((firstGlyph + 2 < firstGlyph) || ++ (lastGlyph - firstGlyph < 2)) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + a = glyphStorage[firstGlyph]; + b = glyphStorage[firstGlyph + 1]; + d = glyphStorage[lastGlyph]; +@@ -309,6 +365,10 @@ void IndicRearrangementProcessor2::doRea + break; + + case irvCDxAB: ++ if (lastGlyph - firstGlyph < 3) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + a = glyphStorage[firstGlyph]; + b = glyphStorage[firstGlyph + 1]; + +@@ -331,6 +391,10 @@ void IndicRearrangementProcessor2::doRea + break; + + case irvCDxBA: ++ if (lastGlyph - firstGlyph < 3) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + a = glyphStorage[firstGlyph]; + b = glyphStorage[firstGlyph + 1]; + +@@ -353,6 +417,10 @@ void IndicRearrangementProcessor2::doRea + break; + + case irvDCxAB: ++ if (lastGlyph - firstGlyph < 3) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + a = glyphStorage[firstGlyph]; + b = glyphStorage[firstGlyph + 1]; + +@@ -375,6 +443,10 @@ void IndicRearrangementProcessor2::doRea + break; + + case irvDCxBA: ++ if (lastGlyph - firstGlyph < 3) { ++ success = LE_INDEX_OUT_OF_BOUNDS_ERROR; ++ break; ++ } + a = glyphStorage[firstGlyph]; + b = glyphStorage[firstGlyph + 1]; + +--- icu-4.4.1.orig/source/layout/IndicRearrangementProcessor2.h ++++ icu-4.4.1/source/layout/IndicRearrangementProcessor2.h +@@ -31,7 +31,7 @@ public: + + virtual void endStateTable(); + +- void doRearrangementAction(LEGlyphStorage &glyphStorage, IndicRearrangementVerb verb) const; ++ void doRearrangementAction(LEGlyphStorage &glyphStorage, IndicRearrangementVerb verb, LEErrorCode &success) const; + + IndicRearrangementProcessor2(const LEReferenceTo &morphSubtableHeader, LEErrorCode &success); + virtual ~IndicRearrangementProcessor2(); +@@ -51,8 +51,8 @@ public: + static UClassID getStaticClassID(); + + protected: +- le_int32 firstGlyph; +- le_int32 lastGlyph; ++ le_uint32 firstGlyph; ++ le_uint32 lastGlyph; + + LEReferenceToArrayOf entryTable; + LEReferenceTo indicRearrangementSubtableHeader; +--- icu-4.4.1.orig/source/layout/MorphTables.cpp ++++ icu-4.4.1/source/layout/MorphTables.cpp +@@ -56,6 +56,8 @@ void MorphSubtableHeader::process(const + { + SubtableProcessor *processor = NULL; + ++ if (LE_FAILURE(success)) return; ++ + switch (SWAPW(coverage) & scfTypeMask) + { + case mstIndicRearrangement: +--- icu-4.4.1.orig/source/layout/MorphTables2.cpp ++++ icu-4.4.1/source/layout/MorphTables2.cpp +@@ -164,6 +164,7 @@ void MorphTableHeader2::process(const LE + if(subtable>0) { + le_uint32 length = SWAPL(subtableHeader->length); + subtableHeader.addOffset(length, success); // Don't addOffset for the last entry. ++ if (LE_FAILURE(success)) break; + } + le_uint32 coverage = SWAPL(subtableHeader->coverage); + FeatureFlags subtableFeatures = SWAPL(subtableHeader->subtableFeatures); +@@ -179,6 +180,8 @@ void MorphSubtableHeader2::process(const + { + SubtableProcessor2 *processor = NULL; + ++ if (LE_FAILURE(success)) return; ++ + switch (SWAPL(coverage) & scfTypeMask2) + { + case mstIndicRearrangement: +--- icu-4.4.1.orig/source/layout/SegmentArrayProcessor.cpp ++++ icu-4.4.1/source/layout/SegmentArrayProcessor.cpp +@@ -38,6 +38,8 @@ void SegmentArrayProcessor::process(LEGl + le_int32 glyphCount = glyphStorage.getGlyphCount(); + le_int32 glyph; + ++ if (LE_FAILURE(success)) return; ++ + for (glyph = 0; glyph < glyphCount; glyph += 1) { + LEGlyphID thisGlyph = glyphStorage[glyph]; + const LookupSegment *lookupSegment = segmentArrayLookupTable->lookupSegment(segmentArrayLookupTable, segments, thisGlyph, success); +--- icu-4.4.1.orig/source/layout/SegmentArrayProcessor2.cpp ++++ icu-4.4.1/source/layout/SegmentArrayProcessor2.cpp +@@ -38,6 +38,8 @@ void SegmentArrayProcessor2::process(LEG + le_int32 glyphCount = glyphStorage.getGlyphCount(); + le_int32 glyph; + ++ if (LE_FAILURE(success)) return; ++ + for (glyph = 0; glyph < glyphCount; glyph += 1) { + LEGlyphID thisGlyph = glyphStorage[glyph]; + const LookupSegment *lookupSegment = segmentArrayLookupTable->lookupSegment(segmentArrayLookupTable, segments, thisGlyph, success); +--- icu-4.4.1.orig/source/layout/SegmentSingleProcessor2.cpp ++++ icu-4.4.1/source/layout/SegmentSingleProcessor2.cpp +@@ -39,6 +39,8 @@ void SegmentSingleProcessor2::process(LE + le_int32 glyphCount = glyphStorage.getGlyphCount(); + le_int32 glyph; + ++ if (LE_FAILURE(success)) return; ++ + for (glyph = 0; glyph < glyphCount; glyph += 1) { + LEGlyphID thisGlyph = glyphStorage[glyph]; + const LookupSegment *lookupSegment = segmentSingleLookupTable->lookupSegment(segmentSingleLookupTable, segments, thisGlyph, success); +--- icu-4.4.1.orig/source/layout/SimpleArrayProcessor2.cpp ++++ icu-4.4.1/source/layout/SimpleArrayProcessor2.cpp +@@ -36,10 +36,11 @@ SimpleArrayProcessor2::~SimpleArrayProce + + void SimpleArrayProcessor2::process(LEGlyphStorage &glyphStorage, LEErrorCode &success) + { +- if (LE_FAILURE(success)) return; + le_int32 glyphCount = glyphStorage.getGlyphCount(); + le_int32 glyph; + ++ if (LE_FAILURE(success)) return; ++ + for (glyph = 0; glyph < glyphCount; glyph += 1) { + LEGlyphID thisGlyph = glyphStorage[glyph]; + if (LE_GET_GLYPH(thisGlyph) < 0xFFFF) { +--- icu-4.4.1.orig/source/layout/SingleTableProcessor.cpp ++++ icu-4.4.1/source/layout/SingleTableProcessor.cpp +@@ -38,6 +38,8 @@ void SingleTableProcessor::process(LEGly + le_int32 glyph; + le_int32 glyphCount = glyphStorage.getGlyphCount(); + ++ if (LE_FAILURE(success)) return; ++ + for (glyph = 0; glyph < glyphCount; glyph += 1) { + const LookupSingle *lookupSingle = singleTableLookupTable->lookupSingle(singleTableLookupTable, entries, glyphStorage[glyph], success); + diff -Nru icu-52.1/debian/patches/CVE-2016-0494.patch icu-52.1/debian/patches/CVE-2016-0494.patch --- icu-52.1/debian/patches/CVE-2016-0494.patch 1970-01-01 00:00:00.000000000 +0000 +++ icu-52.1/debian/patches/CVE-2016-0494.patch 2017-03-10 16:40:51.000000000 +0000 @@ -0,0 +1,100 @@ +Description: Arrange font actions +Origin: upstream, http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/rev/ce5c56e0676f +Bug: (no upstream bug yet) + +--- icu-4.8.1.1.orig/source/layout/IndicRearrangementProcessor.cpp ++++ icu-4.8.1.1/source/layout/IndicRearrangementProcessor.cpp +@@ -51,11 +51,11 @@ + } + + if (flags & irfMarkFirst) { +- firstGlyph = (le_uint32)currGlyph; ++ firstGlyph = currGlyph; + } + + if (flags & irfMarkLast) { +- lastGlyph = (le_uint32)currGlyph; ++ lastGlyph = currGlyph; + } + + doRearrangementAction(glyphStorage, (IndicRearrangementVerb) (flags & irfVerbMask), success); +@@ -93,7 +93,7 @@ + if (firstGlyph == lastGlyph) break; + if (firstGlyph + 1 < firstGlyph) { + success = LE_INDEX_OUT_OF_BOUNDS_ERROR; +- break; ++ break; + } + a = glyphStorage[firstGlyph]; + ia = glyphStorage.getCharIndex(firstGlyph, success); +--- icu-4.8.1.1.orig/source/layout/IndicRearrangementProcessor.h ++++ icu-4.8.1.1/source/layout/IndicRearrangementProcessor.h +@@ -51,8 +51,8 @@ + static UClassID getStaticClassID(); + + protected: +- le_uint32 firstGlyph; +- le_uint32 lastGlyph; ++ le_int32 firstGlyph; ++ le_int32 lastGlyph; + + LEReferenceTo indicRearrangementSubtableHeader; + LEReferenceToArrayOf entryTable; +--- icu-4.8.1.1.orig/source/layout/IndicRearrangementProcessor2.cpp ++++ icu-4.8.1.1/source/layout/IndicRearrangementProcessor2.cpp +@@ -49,11 +49,11 @@ + } + + if (flags & irfMarkFirst) { +- firstGlyph = (le_uint32)currGlyph; ++ firstGlyph = currGlyph; + } + + if (flags & irfMarkLast) { +- lastGlyph = (le_uint32)currGlyph; ++ lastGlyph = currGlyph; + } + + doRearrangementAction(glyphStorage, (IndicRearrangementVerb) (flags & irfVerbMask), success); +@@ -90,7 +90,7 @@ + if (firstGlyph == lastGlyph) break; + if (firstGlyph + 1 < firstGlyph) { + success = LE_INDEX_OUT_OF_BOUNDS_ERROR; +- break; ++ break; + } + a = glyphStorage[firstGlyph]; + ia = glyphStorage.getCharIndex(firstGlyph, success); +--- icu-4.8.1.1.orig/source/layout/IndicRearrangementProcessor2.h ++++ icu-4.8.1.1/source/layout/IndicRearrangementProcessor2.h +@@ -51,8 +51,8 @@ + static UClassID getStaticClassID(); + + protected: +- le_uint32 firstGlyph; +- le_uint32 lastGlyph; ++ le_int32 firstGlyph; ++ le_int32 lastGlyph; + + LEReferenceToArrayOf entryTable; + LEReferenceTo indicRearrangementSubtableHeader; +--- icu-4.8.1.1.orig/source/runConfigureICU ++++ icu-4.8.1.1/source/runConfigureICU +@@ -370,7 +370,7 @@ + then + case $CC in + gcc|*/gcc|*-gcc-*|*/*-gcc-*) +- RELEASE_CFLAGS=-O3 ++ RELEASE_CFLAGS=-O3 -fno-strict-overflow + ;; + esac + fi +@@ -382,7 +382,7 @@ + then + case $CXX in + g++|*/g++|*-g++-*|*/*-g++-*) +- RELEASE_CXXFLAGS=-O3 ++ RELEASE_CXXFLAGS=-O3 -fno-strict-overflow + ;; + esac + fi diff -Nru icu-52.1/debian/patches/CVE-2016-6293.patch icu-52.1/debian/patches/CVE-2016-6293.patch --- icu-52.1/debian/patches/CVE-2016-6293.patch 1970-01-01 00:00:00.000000000 +0000 +++ icu-52.1/debian/patches/CVE-2016-6293.patch 2017-03-10 16:40:59.000000000 +0000 @@ -0,0 +1,272 @@ +--- /source/common/unicode/localpointer.h ++++ /source/common/unicode/localpointer.h +@@ -238,6 +238,24 @@ public: + */ + explicit LocalArray(T *p=NULL) : LocalPointerBase(p) {} + /** ++ * Constructor takes ownership and reports an error if NULL. ++ * ++ * This constructor is intended to be used with other-class constructors ++ * that may report a failure UErrorCode, ++ * so that callers need to check only for U_FAILURE(errorCode) ++ * and not also separately for isNull(). ++ * ++ * @param p simple pointer to an array of T objects that is adopted ++ * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR ++ * if p==NULL and no other failure code had been set ++ * @stable ICU 56 ++ */ ++ LocalArray(T *p, UErrorCode &errorCode) : LocalPointerBase(p) { ++ if(p==NULL && U_SUCCESS(errorCode)) { ++ errorCode=U_MEMORY_ALLOCATION_ERROR; ++ } ++ } ++ /** + * Destructor deletes the array it owns. + * @stable ICU 4.4 + */ +Index: /source/common/uloc.cpp +=================================================================== +--- /source/common/uloc.cpp (revision 39108) ++++ /source/common/uloc.cpp (revision 39109) +@@ -46,6 +46,8 @@ + + #include /* for sprintf */ + ++#define UPRV_LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) ++ + /* ### Declarations **************************************************/ + + /* Locale stuff from locid.cpp */ +@@ -2240,5 +2242,5 @@ + float q; + int32_t dummy; /* to avoid uninitialized memory copy from qsort */ +- char *locale; ++ char locale[ULOC_FULLNAME_CAPACITY+1]; + } _acceptLangItem; + +@@ -2282,7 +2284,5 @@ + UErrorCode *status) + { +- _acceptLangItem *j; +- _acceptLangItem smallBuffer[30]; +- char **strs; ++ MaybeStackArray<_acceptLangItem, 4> items; // Struct for collecting items. + char tmp[ULOC_FULLNAME_CAPACITY +1]; + int32_t n = 0; +@@ -2293,11 +2293,7 @@ uloc_acceptLanguageFromHTTP(char *result + int32_t res; + int32_t i; + int32_t l = (int32_t)uprv_strlen(httpAcceptLanguage); +- int32_t jSize; +- char *tempstr; /* Use for null pointer check */ + +- j = smallBuffer; +- jSize = sizeof(smallBuffer)/sizeof(smallBuffer[0]); + if(U_FAILURE(*status)) { + return -1; + } +@@ -2325,27 +2321,29 @@ uloc_acceptLanguageFromHTTP(char *result + while(isspace(*t)) { + t++; + } +- j[n].q = (float)_uloc_strtod(t,NULL); ++ items[n].q = (float)_uloc_strtod(t,NULL); + } else { + /* no semicolon - it's 1.0 */ +- j[n].q = 1.0f; ++ items[n].q = 1.0f; + paramEnd = itemEnd; + } +- j[n].dummy=0; ++ items[n].dummy=0; + /* eat spaces prior to semi */ + for(t=(paramEnd-1);(paramEnd>s)&&isspace(*t);t--) + ; +- /* Check for null pointer from uprv_strndup */ +- tempstr = uprv_strndup(s,(int32_t)((t+1)-s)); +- if (tempstr == NULL) { +- *status = U_MEMORY_ALLOCATION_ERROR; +- return -1; ++ int32_t slen = ((t+1)-s); ++ if(slen > ULOC_FULLNAME_CAPACITY) { ++ *status = U_BUFFER_OVERFLOW_ERROR; ++ return -1; // too big + } +- j[n].locale = tempstr; +- uloc_canonicalize(j[n].locale,tmp,sizeof(tmp)/sizeof(tmp[0]),status); +- if(strcmp(j[n].locale,tmp)) { +- uprv_free(j[n].locale); +- j[n].locale=uprv_strdup(tmp); ++ uprv_strncpy(items[n].locale, s, slen); ++ items[n].locale[slen]=0; // terminate ++ int32_t clen = uloc_canonicalize(items[n].locale, tmp, UPRV_LENGTHOF(tmp)-1, status); ++ if(U_FAILURE(*status)) return -1; ++ if((clen!=slen) || (uprv_strncmp(items[n].locale, tmp, slen))) { ++ // canonicalization had an effect- copy back ++ uprv_strncpy(items[n].locale, tmp, clen); ++ items[n].locale[clen] = 0; // terminate + } + #if defined(ULOC_DEBUG) + /*fprintf(stderr,"%d: s <%s> q <%g>\n", n, j[n].locale, j[n].q);*/ +@@ -2356,42 +2354,18 @@ + s++; + } +- if(n>=jSize) { +- if(j==smallBuffer) { /* overflowed the small buffer. */ +- j = static_cast<_acceptLangItem *>(uprv_malloc(sizeof(j[0])*(jSize*2))); +- if(j!=NULL) { +- uprv_memcpy(j,smallBuffer,sizeof(j[0])*jSize); +- } ++ if(n>=items.getCapacity()) { // If we need more items ++ if(NULL == items.resize(items.getCapacity()*2, items.getCapacity())) { ++ *status = U_MEMORY_ALLOCATION_ERROR; ++ return -1; ++ } + #if defined(ULOC_DEBUG) +- fprintf(stderr,"malloced at size %d\n", jSize); ++ fprintf(stderr,"malloced at size %d\n", items.getCapacity()); + #endif +- } else { +- j = static_cast<_acceptLangItem *>(uprv_realloc(j, sizeof(j[0])*jSize*2)); +-#if defined(ULOC_DEBUG) +- fprintf(stderr,"re-alloced at size %d\n", jSize); +-#endif +- } +- jSize *= 2; +- if(j==NULL) { +- *status = U_MEMORY_ALLOCATION_ERROR; +- return -1; +- } +- } +- } +- uprv_sortArray(j, n, sizeof(j[0]), uloc_acceptLanguageCompare, NULL, TRUE, status); ++ } ++ } ++ uprv_sortArray(items.getAlias(), n, sizeof(items[0]), uloc_acceptLanguageCompare, NULL, TRUE, status); ++ LocalArray strs(new const char*[n], *status); + if(U_FAILURE(*status)) { +- if(j != smallBuffer) { +-#if defined(ULOC_DEBUG) +- fprintf(stderr,"freeing j %p\n", j); +-#endif +- uprv_free(j); +- } +- return -1; +- } +- strs = static_cast(uprv_malloc((size_t)(sizeof(strs[0])*n))); +- /* Check for null pointer */ +- if (strs == NULL) { +- uprv_free(j); /* Free to avoid memory leak */ +- *status = U_MEMORY_ALLOCATION_ERROR; +- return -1; ++ return -1; + } + for(i=0;i q <%g>\n", i, j[i].locale, j[i].q);*/ + #endif +- strs[i]=j[i].locale; ++ strs[i]=items[i].locale; + } + res = uloc_acceptLanguage(result, resultAvailable, outResult, +- (const char**)strs, n, availableLocales, status); +- for(i=0;i0)&&uprv_strcmp(tmp, tests[i].expect)) { +- log_err_status(status, "FAIL: #%d: expected %s but got %s\n", i, tests[i].expect, tmp); +- log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n", +- i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect, acceptResult(tests[i].res)); ++ } ++ if((outResult>0)&&uprv_strcmp(tmp, tests[i].expect)) { ++ log_err_status(status, "FAIL: #%d: expected %s but got %s\n", i, tests[i].expect, tmp); ++ log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n", ++ i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect, acceptResult(tests[i].res)); ++ } + } + } diff -Nru icu-52.1/debian/patches/CVE-2016-7415.patch icu-52.1/debian/patches/CVE-2016-7415.patch --- icu-52.1/debian/patches/CVE-2016-7415.patch 1970-01-01 00:00:00.000000000 +0000 +++ icu-52.1/debian/patches/CVE-2016-7415.patch 2017-03-10 16:41:05.000000000 +0000 @@ -0,0 +1,178 @@ +Index: source/common/locid.cpp +=================================================================== +--- a/source/common/locid.cpp (revision 39353) ++++ b/source/common/locid.cpp (revision 39356) +@@ -41,6 +41,7 @@ + #include "uhash.h" + #include "ucln_cmn.h" + #include "ustr_imp.h" ++#include "charstr.h" + + #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) + +@@ -57,4 +58,10 @@ + static UHashtable *gDefaultLocalesHashT = NULL; + static Locale *gDefaultLocale = NULL; ++ ++/** ++ * \def ULOC_STRING_LIMIT ++ * strings beyond this value crash in CharString ++ */ ++#define ULOC_STRING_LIMIT 357913941 + + U_NAMESPACE_END +@@ -253,5 +260,5 @@ + else + { +- MaybeStackArray togo; ++ UErrorCode status = U_ZERO_ERROR; + int32_t size = 0; + int32_t lsize = 0; +@@ -259,5 +266,4 @@ + int32_t vsize = 0; + int32_t ksize = 0; +- char *p; + + // Calculate the size of the resulting string. +@@ -267,6 +273,12 @@ + { + lsize = (int32_t)uprv_strlen(newLanguage); ++ if ( lsize < 0 || lsize > ULOC_STRING_LIMIT ) { // int32 wrap ++ setToBogus(); ++ return; ++ } + size = lsize; + } ++ ++ CharString togo(newLanguage, lsize, status); // start with newLanguage + + // _Country +@@ -274,4 +286,8 @@ + { + csize = (int32_t)uprv_strlen(newCountry); ++ if ( csize < 0 || csize > ULOC_STRING_LIMIT ) { // int32 wrap ++ setToBogus(); ++ return; ++ } + size += csize; + } +@@ -288,4 +304,8 @@ + // remove trailing _'s + vsize = (int32_t)uprv_strlen(newVariant); ++ if ( vsize < 0 || vsize > ULOC_STRING_LIMIT ) { // int32 wrap ++ setToBogus(); ++ return; ++ } + while( (vsize>1) && (newVariant[vsize-1] == SEP_CHAR) ) + { +@@ -312,48 +332,34 @@ + { + ksize = (int32_t)uprv_strlen(newKeywords); ++ if ( ksize < 0 || ksize > ULOC_STRING_LIMIT ) { ++ setToBogus(); ++ return; ++ } + size += ksize + 1; + } + +- ++ if (size < 0) { ++ setToBogus(); ++ return; ++ } + // NOW we have the full locale string.. +- +- /*if the whole string is longer than our internal limit, we need +- to go to the heap for temporary buffers*/ +- if (size >= togo.getCapacity()) +- { +- // If togo_heap could not be created, initialize with default settings. +- if (togo.resize(size+1) == NULL) { +- init(NULL, FALSE); +- } +- } +- +- togo[0] = 0; +- + // Now, copy it back. +- p = togo.getAlias(); +- if ( lsize != 0 ) +- { +- uprv_strcpy(p, newLanguage); +- p += lsize; +- } ++ ++ // newLanguage is already copied + + if ( ( vsize != 0 ) || (csize != 0) ) // at least: __v + { // ^ +- *p++ = SEP_CHAR; ++ togo.append(SEP_CHAR, status); + } + + if ( csize != 0 ) + { +- uprv_strcpy(p, newCountry); +- p += csize; ++ togo.append(newCountry, status); + } + + if ( vsize != 0) + { +- *p++ = SEP_CHAR; // at least: __v +- +- uprv_strncpy(p, newVariant, vsize); // Must use strncpy because +- p += vsize; // of trimming (above). +- *p = 0; // terminate ++ togo.append(SEP_CHAR, status) ++ .append(newVariant, vsize, status); + } + +@@ -361,19 +367,23 @@ + { + if (uprv_strchr(newKeywords, '=')) { +- *p++ = '@'; /* keyword parsing */ ++ togo.append('@', status); /* keyword parsing */ + } + else { +- *p++ = '_'; /* Variant parsing with a script */ ++ togo.append('_', status); /* Variant parsing with a script */ + if ( vsize == 0) { +- *p++ = '_'; /* No country found */ ++ togo.append('_', status); /* No country found */ + } + } +- uprv_strcpy(p, newKeywords); +- p += ksize; +- } +- ++ togo.append(newKeywords, status); ++ } ++ ++ if (U_FAILURE(status)) { ++ // Something went wrong with appending, etc. ++ setToBogus(); ++ return; ++ } + // Parse it, because for example 'language' might really be a complete + // string. +- init(togo.getAlias(), FALSE); ++ init(togo.data(), FALSE); + } + } +Index: source/test/intltest/numfmtst.cpp +=================================================================== +--- a/source/test/intltest/numfmtst.cpp (revision 39353) ++++ b/source/test/intltest/numfmtst.cpp (revision 39356) +@@ -1951,9 +1951,10 @@ + const char *localeName = badLocales[i]; + Locale locBad(localeName); ++ TEST_ASSERT_TRUE(!locBad.isBogus()); + UErrorCode status = U_ZERO_ERROR; + UnicodeString intlCurrencySymbol((UChar)0xa4); + + intlCurrencySymbol.append((UChar)0xa4); +- ++ + logln("Current locale is %s", Locale::getDefault().getName()); + Locale::setDefault(locBad, status); diff -Nru icu-52.1/debian/patches/series icu-52.1/debian/patches/series --- icu-52.1/debian/patches/series 2015-09-11 13:28:00.000000000 +0000 +++ icu-52.1/debian/patches/series 2017-03-10 16:41:05.000000000 +0000 @@ -15,3 +15,8 @@ CVE-2015-1270.patch CVE-2015-2632.patch CVE-2015-4760.patch +CVE-2014-9911.patch +CVE-2015-4844.patch +CVE-2016-0494.patch +CVE-2016-6293.patch +CVE-2016-7415.patch