From d2892f3a2d7fa53791dc3ab9dbc69aa7fdc1c211 Mon Sep 17 00:00:00 2001 From: Mark H Weaver Date: Sun, 2 Aug 2015 02:07:52 -0400 Subject: gnu: icu4c: Add fix for CVE-2015-4760. * gnu/packages/patches/icu4c-CVE-2015-4760.patch: New file. * gnu-system.am (dist_patch_DATA): Add it. * gnu/packages/icu4c.scm (icu4c)[source]: Add patch. --- gnu-system.am | 1 + gnu/packages/icu4c.scm | 3 +- gnu/packages/patches/icu4c-CVE-2015-4760.patch | 189 +++++++++++++++++++++++++ 3 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 gnu/packages/patches/icu4c-CVE-2015-4760.patch diff --git a/gnu-system.am b/gnu-system.am index 87924febd1..4b1486eeee 100644 --- a/gnu-system.am +++ b/gnu-system.am @@ -486,6 +486,7 @@ dist_patch_DATA = \ gnu/packages/patches/icecat-enable-acceleration-and-webgl.patch \ gnu/packages/patches/icecat-freetype-2.6.patch \ gnu/packages/patches/icecat-libvpx-1.4.patch \ + gnu/packages/patches/icu4c-CVE-2015-4760.patch \ gnu/packages/patches/irrlicht-mesa-10.patch \ gnu/packages/patches/jbig2dec-ignore-testtest.patch \ gnu/packages/patches/julia-0.3.10-fix-empty-array.patch \ diff --git a/gnu/packages/icu4c.scm b/gnu/packages/icu4c.scm index a753a22b20..46e5d12049 100644 --- a/gnu/packages/icu4c.scm +++ b/gnu/packages/icu4c.scm @@ -37,7 +37,8 @@ (string-map (lambda (x) (if (char=? x #\.) #\_ x)) version) "-src.tgz")) (sha256 - (base32 "0ys5f5spizg45qlaa31j2lhgry0jka2gfha527n4ndfxxz5j4sz1")))) + (base32 "0ys5f5spizg45qlaa31j2lhgry0jka2gfha527n4ndfxxz5j4sz1")) + (patches (list (search-patch "icu4c-CVE-2015-4760.patch"))))) (build-system gnu-build-system) (inputs `(("perl" ,perl))) diff --git a/gnu/packages/patches/icu4c-CVE-2015-4760.patch b/gnu/packages/patches/icu4c-CVE-2015-4760.patch new file mode 100644 index 0000000000..77da283b7b --- /dev/null +++ b/gnu/packages/patches/icu4c-CVE-2015-4760.patch @@ -0,0 +1,189 @@ +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) +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; -- cgit v1.2.3