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é <anarcat@orangeseeds.org> --- 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 Index: source/layout/IndicRearrangementProcessor.cpp =================================================================== --- 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]; Index: source/layout/IndicRearrangementProcessor.h =================================================================== --- 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> &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> indicRearrangementSubtableHeader; LEReferenceToArrayOf<IndicRearrangementStateEntry> entryTable; Index: source/layout/IndicRearrangementProcessor2.cpp =================================================================== --- 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]; Index: source/layout/IndicRearrangementProcessor2.h =================================================================== --- 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<MorphSubtableHeader2> &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<IndicRearrangementStateEntry2> entryTable; LEReferenceTo<IndicRearrangementSubtableHeader2> indicRearrangementSubtableHeader; Index: source/layout/MorphTables.cpp =================================================================== --- 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: Index: source/layout/MorphTables2.cpp =================================================================== --- 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: Index: source/layout/SegmentArrayProcessor.cpp =================================================================== --- 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); Index: source/layout/SegmentArrayProcessor2.cpp =================================================================== --- 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); Index: source/layout/SegmentSingleProcessor2.cpp =================================================================== --- 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); Index: source/layout/SimpleArrayProcessor2.cpp =================================================================== --- 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) { Index: source/layout/SingleTableProcessor.cpp =================================================================== --- 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);