Copied from Debian. Description: missing boundary checks in layout engine It was discovered that ICU Layout Engine was missing multiple boundary checks. These could lead to buffer overflows and memory corruption. A specially crafted file could cause an application using ICU to parse untrusted font files to crash and, possibly, execute arbitrary code. Author: Laszlo Boszormenyi (GCS) <gcs@debian.org> Origin: upstream, http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/rev/3f9845510b47 Reviewed-By: srl, bae, mschoene Forwarded: not-needed Last-Update: 2015-07-30 --- --- icu-52.1.orig/source/layout/ContextualGlyphInsertionProc2.cpp +++ icu-52.1/source/layout/ContextualGlyphInsertionProc2.cpp @@ -82,6 +82,10 @@ le_uint16 ContextualGlyphInsertionProces le_int16 markIndex = SWAPW(entry->markedInsertionListIndex); if (markIndex > 0) { + if (markGlyph < 0 || markGlyph >= glyphStorage.getGlyphCount()) { + success = LE_INDEX_OUT_OF_BOUNDS_ERROR; + return 0; + } le_int16 count = (flags & cgiMarkedInsertCountMask) >> 5; le_bool isKashidaLike = (flags & cgiMarkedIsKashidaLike); le_bool isBefore = (flags & cgiMarkInsertBefore); @@ -90,6 +94,10 @@ le_uint16 ContextualGlyphInsertionProces le_int16 currIndex = SWAPW(entry->currentInsertionListIndex); if (currIndex > 0) { + if (currGlyph < 0 || currGlyph >= glyphStorage.getGlyphCount()) { + success = LE_INDEX_OUT_OF_BOUNDS_ERROR; + return 0; + } le_int16 count = flags & cgiCurrentInsertCountMask; le_bool isKashidaLike = (flags & cgiCurrentIsKashidaLike); le_bool isBefore = (flags & cgiCurrentInsertBefore); --- icu-52.1.orig/source/layout/ContextualGlyphSubstProc.cpp +++ icu-52.1/source/layout/ContextualGlyphSubstProc.cpp @@ -51,6 +51,10 @@ ByteOffset ContextualGlyphSubstitutionPr WordOffset currOffset = SWAPW(entry->currOffset); if (markOffset != 0 && LE_SUCCESS(success)) { + if (markGlyph < 0 || markGlyph >= glyphStorage.getGlyphCount()) { + success = LE_INDEX_OUT_OF_BOUNDS_ERROR; + return 0; + } LEGlyphID mGlyph = glyphStorage[markGlyph]; TTGlyphID newGlyph = SWAPW(int16Table.getObject(markOffset + LE_GET_GLYPH(mGlyph), success)); // whew. @@ -58,6 +62,10 @@ ByteOffset ContextualGlyphSubstitutionPr } if (currOffset != 0) { + if (currGlyph < 0 || currGlyph >= glyphStorage.getGlyphCount()) { + success = LE_INDEX_OUT_OF_BOUNDS_ERROR; + return 0; + } LEGlyphID thisGlyph = glyphStorage[currGlyph]; TTGlyphID newGlyph = SWAPW(int16Table.getObject(currOffset + LE_GET_GLYPH(thisGlyph), success)); // whew. --- icu-52.1.orig/source/layout/ContextualGlyphSubstProc2.cpp +++ icu-52.1/source/layout/ContextualGlyphSubstProc2.cpp @@ -45,17 +45,25 @@ le_uint16 ContextualGlyphSubstitutionPro if(LE_FAILURE(success)) return 0; le_uint16 newState = SWAPW(entry->newStateIndex); le_uint16 flags = SWAPW(entry->flags); - le_int16 markIndex = SWAPW(entry->markIndex); - le_int16 currIndex = SWAPW(entry->currIndex); + le_uint16 markIndex = SWAPW(entry->markIndex); + le_uint16 currIndex = SWAPW(entry->currIndex); - if (markIndex != -1) { + if (markIndex != 0x0FFFF) { + if (markGlyph < 0 || markGlyph >= glyphStorage.getGlyphCount()) { + success = LE_INDEX_OUT_OF_BOUNDS_ERROR; + return 0; + } le_uint32 offset = SWAPL(perGlyphTable(markIndex, success)); LEGlyphID mGlyph = glyphStorage[markGlyph]; TTGlyphID newGlyph = lookup(offset, mGlyph, success); glyphStorage[markGlyph] = LE_SET_GLYPH(mGlyph, newGlyph); } - if (currIndex != -1) { + if (currIndex != 0x0FFFF) { + if (currGlyph < 0 || currGlyph >= glyphStorage.getGlyphCount()) { + success = LE_INDEX_OUT_OF_BOUNDS_ERROR; + return 0; + } le_uint32 offset = SWAPL(perGlyphTable(currIndex, success)); LEGlyphID thisGlyph = glyphStorage[currGlyph]; TTGlyphID newGlyph = lookup(offset, thisGlyph, success); --- icu-52.1.orig/source/layout/IndicRearrangementProcessor.cpp +++ icu-52.1/source/layout/IndicRearrangementProcessor.cpp @@ -45,6 +45,11 @@ ByteOffset IndicRearrangementProcessor:: ByteOffset newState = SWAPW(entry->newStateOffset); IndicRearrangementFlags flags = (IndicRearrangementFlags) SWAPW(entry->flags); + if (currGlyph < 0 || currGlyph >= glyphStorage.getGlyphCount()) { + success = LE_INDEX_OUT_OF_BOUNDS_ERROR; + return 0; + } + if (flags & irfMarkFirst) { firstGlyph = currGlyph; } --- icu-52.1.orig/source/layout/IndicRearrangementProcessor2.cpp +++ icu-52.1/source/layout/IndicRearrangementProcessor2.cpp @@ -43,6 +43,11 @@ le_uint16 IndicRearrangementProcessor2:: le_uint16 newState = SWAPW(entry->newStateIndex); // index to the new state IndicRearrangementFlags flags = (IndicRearrangementFlags) SWAPW(entry->flags); + if (currGlyph < 0 || currGlyph >= glyphStorage.getGlyphCount()) { + success = LE_INDEX_OUT_OF_BOUNDS_ERROR; + return 0; + } + if (flags & irfMarkFirst) { firstGlyph = currGlyph; } --- icu-52.1.orig/source/layout/LigatureSubstProc.cpp +++ icu-52.1/source/layout/LigatureSubstProc.cpp @@ -48,7 +48,7 @@ ByteOffset LigatureSubstitutionProcessor const LigatureSubstitutionStateEntry *entry = entryTable.getAlias(index, success); ByteOffset newState = SWAPW(entry->newStateOffset); - le_int16 flags = SWAPW(entry->flags); + le_uint16 flags = SWAPW(entry->flags); if (flags & lsfSetComponent) { if (++m >= nComponents) { --- icu-52.1.orig/source/layout/StateTableProcessor.cpp +++ icu-52.1/source/layout/StateTableProcessor.cpp @@ -60,6 +60,7 @@ void StateTableProcessor::process(LEGlyp if (currGlyph == glyphCount) { // XXX: How do we handle EOT vs. EOL? classCode = classCodeEOT; + break; } else { TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(glyphStorage[currGlyph]); --- icu-52.1.orig/source/layout/StateTableProcessor2.cpp +++ icu-52.1/source/layout/StateTableProcessor2.cpp @@ -78,6 +78,7 @@ void StateTableProcessor2::process(LEGly if (currGlyph == glyphCount || currGlyph == -1) { // XXX: How do we handle EOT vs. EOL? classCode = classCodeEOT; + break; } else { LEGlyphID gid = glyphStorage[currGlyph]; TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid); @@ -109,6 +110,7 @@ void StateTableProcessor2::process(LEGly if (currGlyph == glyphCount || currGlyph == -1) { // XXX: How do we handle EOT vs. EOL? classCode = classCodeEOT; + break; } else { LEGlyphID gid = glyphStorage[currGlyph]; TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid); @@ -146,6 +148,7 @@ void StateTableProcessor2::process(LEGly if (currGlyph == glyphCount || currGlyph == -1) { // XXX: How do we handle EOT vs. EOL? classCode = classCodeEOT; + break; } else if(currGlyph > glyphCount) { // note if > glyphCount, we've run off the end (bad font) currGlyph = glyphCount; @@ -186,6 +189,7 @@ void StateTableProcessor2::process(LEGly if (currGlyph == glyphCount || currGlyph == -1) { // XXX: How do we handle EOT vs. EOL? classCode = classCodeEOT; + break; } else { TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(glyphStorage[currGlyph]); if (glyphCode == 0xFFFF) { --- icu-52.1.orig/source/layout/StateTables.h +++ icu-52.1/source/layout/StateTables.h @@ -101,7 +101,7 @@ typedef le_uint8 EntryTableIndex; struct StateEntry { ByteOffset newStateOffset; - le_int16 flags; + le_uint16 flags; }; typedef le_uint16 EntryTableIndex2;