summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--gnu-system.am1
-rw-r--r--gnu/packages/icu4c.scm3
-rw-r--r--gnu/packages/patches/icu4c-CVE-2015-4760.patch189
3 files changed, 192 insertions, 1 deletions
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) <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;