Bug 1349310 - Update graphite2 to release 1.3.10. r=milan, a=dveditz FENNEC_54_0b6_BUILD1 FENNEC_54_0b6_RELEASE FIREFOX_54_0b6_BUILD1 FIREFOX_54_0b6_RELEASE
authorJonathan Kew <jkew@mozilla.com>
Mon, 08 May 2017 12:08:24 +0100
changeset 393882 798ee0e6f73e
parent 393881 30a656462d6b
child 393883 487ea7114fd1
push id7289
push userryanvm@gmail.com
push dateMon, 08 May 2017 21:00:07 +0000
treeherdermozilla-beta@798ee0e6f73e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmilan, dveditz
bugs1349310
milestone54.0
Bug 1349310 - Update graphite2 to release 1.3.10. r=milan, a=dveditz
gfx/graphite2/README.mozilla
gfx/graphite2/include/graphite2/Font.h
gfx/graphite2/src/CMakeLists.txt
gfx/graphite2/src/Collider.cpp
gfx/graphite2/src/Decompressor.cpp
gfx/graphite2/src/FeatureMap.cpp
gfx/graphite2/src/GlyphCache.cpp
gfx/graphite2/src/Pass.cpp
gfx/graphite2/src/Silf.cpp
gfx/graphite2/src/inc/Collider.h
gfx/graphite2/src/inc/UtfCodec.h
gfx/graphite2/src/inc/locale2lcid.h
--- a/gfx/graphite2/README.mozilla
+++ b/gfx/graphite2/README.mozilla
@@ -1,6 +1,3 @@
-This directory contains the Graphite2 library release 1.3.9 from
-https://github.com/silnrsi/graphite/releases/download/1.3.9/graphite2-minimal-1.3.9.tgz
-See gfx/graphite2/moz-gr-update.sh for update procedure.
-
-Cherry-picked post-1.3.9 commit 1ce331d5548b98ed8b818532b2556d6f2c7a3b83 to fix
-https://bugzilla.mozilla.org/show_bug.cgi?id=1345461.
+This directory contains the Graphite2 library release 1.3.10 from
+https://github.com/silnrsi/graphite/releases/download/1.3.10/graphite2-minimal-1.3.10.tgz
+See ./gfx/graphite2/moz-gr-update.sh for update procedure.
--- a/gfx/graphite2/include/graphite2/Font.h
+++ b/gfx/graphite2/include/graphite2/Font.h
@@ -25,17 +25,17 @@
     either version 2 of the License or (at your option) any later version.
 */
 #pragma once
 
 #include "graphite2/Types.h"
 
 #define GR2_VERSION_MAJOR   1
 #define GR2_VERSION_MINOR   3
-#define GR2_VERSION_BUGFIX  9
+#define GR2_VERSION_BUGFIX  10
 
 #ifdef __cplusplus
 extern "C"
 {
 #endif
 
 typedef struct gr_face          gr_face;
 typedef struct gr_font          gr_font;
--- a/gfx/graphite2/src/CMakeLists.txt
+++ b/gfx/graphite2/src/CMakeLists.txt
@@ -106,16 +106,19 @@ set_target_properties(graphite2 PROPERTI
                                             LT_VERSION_REVISION ${GRAPHITE_API_REVISION}
                                             LT_VERSION_AGE ${GRAPHITE_API_AGE})
 
 if  (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
     set_target_properties(graphite2 PROPERTIES 
         COMPILE_FLAGS   "-Wall -Wextra -Wno-unknown-pragmas -Wendif-labels -Wshadow -Wctor-dtor-privacy -Wnon-virtual-dtor -fno-rtti -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden -fno-stack-protector"
         LINK_FLAGS      "-nodefaultlibs ${GRAPHITE_LINK_FLAGS}" 
         LINKER_LANGUAGE C)
+    if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86|i.86")
+        add_definitions(-mfpmath=sse -msse2)
+    endif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86|i.86")
     if (CMAKE_COMPILER_IS_GNUCXX)
         add_definitions(-Wdouble-promotion)
     endif (CMAKE_COMPILER_IS_GNUCXX)
     message(STATUS "Compiler ID is: ${CMAKE_CXX_COMPILER_ID}")
     if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
         add_definitions(-Wimplicit-fallthrough)
     endif (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
     if (${CMAKE_CXX_COMPILER} MATCHES  ".*mingw.*")
@@ -130,17 +133,17 @@ if  (${CMAKE_SYSTEM_NAME} STREQUAL "Linu
         nolib_test(stdc++ $<TARGET_SONAME_FILE:graphite2>)
     endif (${CMAKE_CXX_COMPILER} MATCHES  ".*mingw.*")
     set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "")
     CREATE_LIBTOOL_FILE(graphite2 "/lib${LIB_SUFFIX}")
 endif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
 
 if  (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
     set_target_properties(graphite2 PROPERTIES 
-        COMPILE_FLAGS   "-Wall -Wextra -Wno-unknown-pragmas -Wimplicit-fallthrough -Wendif-labels -Wshadow -Wno-ctor-dtor-privacy -Wno-non-virtual-dtor -fno-rtti -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden -fno-stack-protector"
+        COMPILE_FLAGS   "-Wall -Wextra -Wno-unknown-pragmas -Wimplicit-fallthrough -Wendif-labels -Wshadow -Wno-ctor-dtor-privacy -Wno-non-virtual-dtor -fno-rtti -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden -fno-stack-protector -mfpmath=sse -msse2"
         LINK_FLAGS      "-nodefaultlibs" 
         LINKER_LANGUAGE C)
     target_link_libraries(graphite2 c)
     include(Graphite)
     nolib_test(stdc++ $<TARGET_SONAME_FILE:graphite2>)
     set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "")
     CREATE_LIBTOOL_FILE(graphite2 "/lib${LIB_SUFFIX}")
 endif (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
--- a/gfx/graphite2/src/Collider.cpp
+++ b/gfx/graphite2/src/Collider.cpp
@@ -257,17 +257,17 @@ inline void ShiftCollider::removeBox(con
             break;
     }
     return;
 }
 
 // Adjust the movement limits for the target to avoid having it collide
 // with the given neighbor slot. Also determine if there is in fact a collision
 // between the target and the given slot.
-bool ShiftCollider::mergeSlot(Segment *seg, Slot *slot, const Position &currShift,
+bool ShiftCollider::mergeSlot(Segment *seg, Slot *slot, const SlotCollision *cslot, const Position &currShift,
 		bool isAfter,  // slot is logically after _target
 		bool sameCluster, bool &hasCol, bool isExclusion,
         GR_MAYBE_UNUSED json * const dbgout )
 {
     bool isCol = false;
     const float sx = slot->origin().x - _origin.x + currShift.x;
     const float sy = slot->origin().y - _origin.y + currShift.y;
     const float sd = sx - sy;
@@ -277,17 +277,17 @@ bool ShiftCollider::mergeSlot(Segment *s
     float cmin, cmax;   // target limits
     float torg;
     const GlyphCache &gc = seg->getFace()->glyphs();
     const unsigned short gid = slot->gid();
     if (!gc.check(gid))
         return false;
     const BBox &bb = gc.getBoundingBBox(gid);
 
-    SlotCollision * cslot = seg->collisionInfo(slot);
+    // SlotCollision * cslot = seg->collisionInfo(slot);
     int orderFlags = 0;
     bool sameClass = _seqProxClass == 0 && cslot->seqClass() == _seqClass;
     if (sameCluster && _seqClass 
         && (sameClass || (_seqProxClass != 0 && cslot->seqClass() == _seqProxClass)))
 		// Force the target glyph to be in the specified direction from the slot we're testing.
         orderFlags = _seqOrder;
 
     // short circuit if only interested in direct collision and we are out of range
@@ -556,17 +556,18 @@ bool ShiftCollider::mergeSlot(Segment *s
     bool res = true;
     if (cslot->exclGlyph() > 0 && gc.check(cslot->exclGlyph()) && !isExclusion)
     {
         // Set up the bogus slot representing the exclusion glyph.
         Slot *exclSlot = seg->newSlot();
         exclSlot->setGlyph(seg, cslot->exclGlyph());
         Position exclOrigin(slot->origin() + cslot->exclOffset());
         exclSlot->origin(exclOrigin);
-        res &= mergeSlot(seg, exclSlot, currShift, isAfter, sameCluster, isCol, true, dbgout );
+        SlotCollision exclInfo(seg, exclSlot);
+        res &= mergeSlot(seg, exclSlot, &exclInfo, currShift, isAfter, sameCluster, isCol, true, dbgout );
         seg->freeSlot(exclSlot);
     }
     hasCol |= isCol;
     return res;
     
 }   // end of ShiftCollider::mergeSlot
 
 
--- a/gfx/graphite2/src/Decompressor.cpp
+++ b/gfx/graphite2/src/Decompressor.cpp
@@ -46,17 +46,17 @@ u32 read_literal(u8 const * &s, u8 const
 bool read_sequence(u8 const * &src, u8 const * const end, u8 const * &literal, u32 & literal_len, u32 & match_len, u32 & match_dist)
 {
     u8 const token = *src++;
     
     literal_len = read_literal(src, end, token >> 4);
     literal = src;
     src += literal_len;
     
-    if (src > end - 2)
+    if (src > end - 2 || src < literal)
         return false;
     
     match_dist  = *src++;
     match_dist |= *src++ << 8;
     match_len = read_literal(src, end, token & 0xf);
     
     return src <= end-5;
 }
@@ -80,34 +80,36 @@ int lz4::decompress(void const *in, size
         match_dist = 0;
     
     while (read_sequence(src, src_end, literal, literal_len, match_len, match_dist))
     {
         if (literal_len != 0)
         {
             // Copy in literal. At this point the last full sequence must be at
             // least MINMATCH + 5 from the end of the output buffer.
-            if (dst + align(literal_len) > dst_end - (MINMATCH+5))
+            if (align(literal_len) > unsigned(dst_end - dst - (MINMATCH+5)) || dst_end - dst < MINMATCH + 5)
                 return -1;
             dst = overrun_copy(dst, literal, literal_len);
         }
         
         // Copy, possibly repeating, match from earlier in the
         //  decoded output.
         u8 const * const pcpy = dst - match_dist;
         if (pcpy < static_cast<u8*>(out)
-                  || dst + match_len + MINMATCH > dst_end - 5)
+                  || pcpy >= dst
+                  || match_len > unsigned(dst_end - dst - (MINMATCH+5))
+                  || dst_end - dst < MINMATCH + 5)
             return -1;
         if (dst > pcpy+sizeof(unsigned long) 
             && dst + align(match_len + MINMATCH) <= dst_end)
             dst = overrun_copy(dst, pcpy, match_len + MINMATCH);
         else 
             dst = safe_copy(dst, pcpy, match_len + MINMATCH);
     }
     
-    if (literal + literal_len > src_end
-              || dst + literal_len > dst_end)
+    if (literal_len > src_end - literal
+              || literal_len > dst_end - dst)
         return -1;
     dst = fast_copy(dst, literal, literal_len);
     
     return dst - (u8*)out;
 }
 
--- a/gfx/graphite2/src/FeatureMap.cpp
+++ b/gfx/graphite2/src/FeatureMap.cpp
@@ -270,17 +270,18 @@ bool FeatureRef::applyValToFeature(uint3
 { 
     if (val>maxVal() || !m_pFace)
       return false;
     if (pDest.m_pMap==NULL)
       pDest.m_pMap = &m_pFace->theSill().theFeatureMap();
     else
       if (pDest.m_pMap!=&m_pFace->theSill().theFeatureMap())
         return false;       //incompatible
-    pDest.reserve(m_index + 1);
+    if (m_index >= pDest.size())
+        pDest.resize(m_index+1);
     pDest[m_index] &= ~m_mask;
     pDest[m_index] |= (uint32(val) << m_bits);
     return true;
 }
 
 uint32 FeatureRef::getFeatureVal(const Features& feats) const
 { 
   if (m_index < feats.size() && &m_pFace->theSill().theFeatureMap()==feats.m_pMap) 
--- a/gfx/graphite2/src/GlyphCache.cpp
+++ b/gfx/graphite2/src/GlyphCache.cpp
@@ -375,22 +375,26 @@ const GlyphFace * GlyphCache::Loader::re
     {
         const byte * gloc = m_pGloc;
         size_t      glocs = 0, gloce = 0;
 
         be::skip<uint32>(gloc);
         be::skip<uint16>(gloc,2);
         if (_long_fmt)
         {
+            if (8 + glyphid * sizeof(uint32) > m_pGloc.size())
+                return 0;
             be::skip<uint32>(gloc, glyphid);
             glocs = be::read<uint32>(gloc);
             gloce = be::peek<uint32>(gloc);
         }
         else
         {
+            if (8 + glyphid * sizeof(uint16) > m_pGloc.size())
+                return 0;
             be::skip<uint16>(gloc, glyphid);
             glocs = be::read<uint16>(gloc);
             gloce = be::peek<uint16>(gloc);
         }
 
         if (glocs >= m_pGlat.size() - 1 || gloce > m_pGlat.size())
             return 0;
 
--- a/gfx/graphite2/src/Pass.cpp
+++ b/gfx/graphite2/src/Pass.cpp
@@ -166,17 +166,17 @@ bool Pass::readPass(const byte * const p
     if (m_colThreshold == 0) m_colThreshold = 10;       // A default
     const size_t pass_constraint_len = be::read<uint16>(p);
 
     const uint16 * const o_constraint = reinterpret_cast<const uint16 *>(p);
     be::skip<uint16>(p, m_numRules + 1);
     const uint16 * const o_actions = reinterpret_cast<const uint16 *>(p);
     be::skip<uint16>(p, m_numRules + 1);
     const byte * const states = p;
-    if (e.test(p + 2u*m_numTransition*m_numColumns >= pass_end, E_BADPASSLENGTH)) return face.error(e);
+    if (e.test(2u*m_numTransition*m_numColumns >= (unsigned)(pass_end - p), E_BADPASSLENGTH)) return face.error(e);
     be::skip<int16>(p, m_numTransition*m_numColumns);
     be::skip<uint8>(p);
     if (e.test(p != pcCode, E_BADPASSCCODEPTR)) return face.error(e);
     be::skip<byte>(p, pass_constraint_len);
     if (e.test(p != rcCode, E_BADRULECCODEPTR)
         || e.test(size_t(rcCode - pcCode) != pass_constraint_len, E_BADCCODELEN)) return face.error(e);
     be::skip<byte>(p, be::peek<uint16>(o_constraint + m_numRules));
     if (e.test(p != aCode, E_BADACTIONCODEPTR)) return face.error(e);
@@ -187,17 +187,17 @@ bool Pass::readPass(const byte * const p
 
     // Load the pass constraint if there is one.
     if (pass_constraint_len)
     {
         face.error_context(face.error_context() + 1);
         m_cPConstraint = vm::Machine::Code(true, pcCode, pcCode + pass_constraint_len, 
                                   precontext[0], be::peek<uint16>(sort_keys), *m_silf, face, PASS_TYPE_UNKNOWN);
         if (e.test(!m_cPConstraint, E_OUTOFMEM)
-                || e.test(!m_cPConstraint, m_cPConstraint.status() + E_CODEFAILURE))
+                || e.test(m_cPConstraint.status() != Code::loaded, m_cPConstraint.status() + E_CODEFAILURE))
             return face.error(e);
         face.error_context(face.error_context() - 1);
     }
     if (m_numRules)
     {
         if (!readRanges(ranges, numRanges, e)) return face.error(e);
         if (!readRules(rule_map, numEntries,  precontext, sort_keys,
                    o_constraint, rcCode, o_actions, aCode, face, pt, e)) return false;
@@ -969,17 +969,17 @@ bool Pass::resolveCollisions(Segment *se
                       && !(cNbor->ignore())    				// don't process if ignoring
                       && (nbor == base || sameCluster       // process if in the same cluster as slotFix
                             || !inKernCluster(seg, nbor)    // or this cluster is not to be kerned
                             || (rtl ^ ignoreForKern))       // or it comes before(ltr) or after(rtl)
                       && (!isRev    // if processing forwards then good to merge otherwise only:
                             || !(cNbor->flags() & SlotCollision::COLL_FIX)     // merge in immovable stuff
                             || ((cNbor->flags() & SlotCollision::COLL_KERN) && !sameCluster)     // ignore other kernable clusters
                             || (cNbor->flags() & SlotCollision::COLL_ISCOL))   // test against other collided glyphs
-                      && !coll.mergeSlot(seg, nbor, cNbor->shift(), !ignoreForKern, sameCluster, collides, false, dbgout))
+                      && !coll.mergeSlot(seg, nbor, cNbor, cNbor->shift(), !ignoreForKern, sameCluster, collides, false, dbgout))
             return false;
         else if (nbor == slotFix)
             // Switching sides of this glyph - if we were ignoring kernable stuff before, don't anymore.
             ignoreForKern = !ignoreForKern;
             
         if (nbor != start && (cNbor->flags() & (isRev ? SlotCollision::COLL_START : SlotCollision::COLL_END)))
             break;
     }
--- a/gfx/graphite2/src/Silf.cpp
+++ b/gfx/graphite2/src/Silf.cpp
@@ -150,75 +150,75 @@ bool Silf::readGraphite(const byte * con
     m_aCollision = be::read<uint8>(p);
     be::skip<byte>(p,3);
     be::skip<uint16>(p, be::read<uint8>(p));    // don't need critical features yet
     be::skip<byte>(p);                          // reserved
     if (e.test(p >= silf_end, E_BADCRITFEATURES))   { releaseBuffers(); return face.error(e); }
     be::skip<uint32>(p, be::read<uint8>(p));    // don't use scriptTag array.
     if (e.test(p + sizeof(uint16) + sizeof(uint32) >= silf_end, E_BADSCRIPTTAGS)) { releaseBuffers(); return face.error(e); }
     m_gEndLine  = be::read<uint16>(p);          // lbGID
-    const byte * o_passes = p,
-               * const passes_start = silf_start + be::read<uint32>(p);
+    const byte * o_passes = p;
+    uint32 passes_start = be::read<uint32>(p);
 
     const size_t num_attrs = face.glyphs().numAttrs();
     if (e.test(m_aPseudo   >= num_attrs, E_BADAPSEUDO)
         || e.test(m_aBreak >= num_attrs, E_BADABREAK)
         || e.test(m_aBidi  >= num_attrs, E_BADABIDI)
         || e.test(m_aMirror>= num_attrs, E_BADAMIRROR)
         || e.test(m_aCollision && m_aCollision >= num_attrs - 5, E_BADACOLLISION)
-        || e.test(m_numPasses > 128, E_BADNUMPASSES) || e.test(passes_start >= silf_end, E_BADPASSESSTART)
+        || e.test(m_numPasses > 128, E_BADNUMPASSES) || e.test(passes_start >= lSilf, E_BADPASSESSTART)
         || e.test(m_pPass < m_sPass, E_BADPASSBOUND) || e.test(m_pPass > m_numPasses, E_BADPPASS) || e.test(m_sPass > m_numPasses, E_BADSPASS)
         || e.test(m_jPass < m_pPass, E_BADJPASSBOUND) || e.test(m_jPass > m_numPasses, E_BADJPASS)
         || e.test((m_bPass != 0xFF && (m_bPass < m_jPass || m_bPass > m_numPasses)), E_BADBPASS)
         || e.test(m_aLig > 127, E_BADALIG))
     {
         releaseBuffers();
         return face.error(e);
     }
     be::skip<uint32>(p, m_numPasses);
-    if (e.test(p + sizeof(uint16) >= passes_start, E_BADPASSESSTART)) { releaseBuffers(); return face.error(e); }
+    if (e.test(unsigned(p - silf_start) + sizeof(uint16) >= passes_start, E_BADPASSESSTART)) { releaseBuffers(); return face.error(e); }
     m_numPseudo = be::read<uint16>(p);
     be::skip<uint16>(p, 3); // searchPseudo, pseudoSelector, pseudoShift
     m_pseudos = new Pseudo[m_numPseudo];
-    if (e.test(p + m_numPseudo*(sizeof(uint32) + sizeof(uint16)) >= passes_start, E_BADNUMPSEUDO)
+    if (e.test(unsigned(p - silf_start) + m_numPseudo*(sizeof(uint32) + sizeof(uint16)) >= passes_start, E_BADNUMPSEUDO)
         || e.test(!m_pseudos, E_OUTOFMEM))
     {
         releaseBuffers(); return face.error(e);
     }
     for (int i = 0; i < m_numPseudo; i++)
     {
         m_pseudos[i].uid = be::read<uint32>(p);
         m_pseudos[i].gid = be::read<uint16>(p);
     }
 
-    const size_t clen = readClassMap(p, passes_start - p, version, e);
+    const size_t clen = readClassMap(p, passes_start + silf_start - p, version, e);
     m_passes = new Pass[m_numPasses];
-    if (e || e.test(p + clen > passes_start, E_BADPASSESSTART)
+    if (e || e.test(clen > unsigned(passes_start + silf_start - p), E_BADPASSESSTART)
           || e.test(!m_passes, E_OUTOFMEM))
     { releaseBuffers(); return face.error(e); }
 
     for (size_t i = 0; i < m_numPasses; ++i)
     {
-        const byte * const pass_start = silf_start + be::read<uint32>(o_passes),
-                   * const pass_end = silf_start + be::peek<uint32>(o_passes);
+        uint32 pass_start = be::read<uint32>(o_passes);
+        uint32 pass_end = be::peek<uint32>(o_passes);
         face.error_context((face.error_context() & 0xFF00) + EC_ASILF + (i << 16));
         if (e.test(pass_start > pass_end, E_BADPASSSTART) 
                 || e.test(pass_start < passes_start, E_BADPASSSTART)
-                || e.test(pass_end > silf_end, E_BADPASSEND)) {
+                || e.test(pass_end > lSilf, E_BADPASSEND)) {
             releaseBuffers(); return face.error(e);
         }
 
         enum passtype pt = PASS_TYPE_UNKNOWN;
         if (i >= m_jPass) pt = PASS_TYPE_JUSTIFICATION;
         else if (i >= m_pPass) pt = PASS_TYPE_POSITIONING;
         else if (i >= m_sPass) pt = PASS_TYPE_SUBSTITUTE;
         else pt = PASS_TYPE_LINEBREAK;
 
         m_passes[i].init(this);
-        if (!m_passes[i].readPass(pass_start, pass_end - pass_start, pass_start - silf_start, face, pt,
+        if (!m_passes[i].readPass(silf_start + pass_start, pass_end - pass_start, pass_start, face, pt,
             version, e))
         {
             releaseBuffers();
             return false;
         }
     }
 
     // fill in gr_faceinfo
@@ -288,17 +288,18 @@ size_t Silf::readClassMap(const byte *p,
 
     // Check the lookup class invariants for each non-linear class
     for (const uint32 *o = m_classOffsets + m_nLinear, * const o_end = m_classOffsets + m_nClass; o != o_end; ++o)
     {
         const uint16 * lookup = m_classData + *o;
         if (e.test(*o + 4 > max_off, E_HIGHCLASSOFFSET)                        // LookupClass doesn't stretch over max_off
          || e.test(lookup[0] == 0                                                   // A LookupClass with no looks is a suspicious thing ...
                     || lookup[0] * 2 + *o + 4 > max_off                             // numIDs lookup pairs fits within (start of LookupClass' lookups array, max_off]
-                    || lookup[3] + lookup[1] != lookup[0], E_BADCLASSLOOKUPINFO))   // rangeShift:   numIDs  - searchRange
+                    || lookup[3] + lookup[1] != lookup[0], E_BADCLASSLOOKUPINFO)    // rangeShift:   numIDs  - searchRange
+         || e.test(((o[1] - *o) & 1) != 0, ERROROFFSET))                         // glyphs are in pairs so difference must be even.
             return ERROROFFSET;
     }
 
     return max_off;
 }
 
 uint16 Silf::findPseudo(uint32 uid) const
 {
--- a/gfx/graphite2/src/inc/Collider.h
+++ b/gfx/graphite2/src/inc/Collider.h
@@ -128,17 +128,17 @@ public:
     typedef vfpairs::iterator ivfpairs;
 
     ShiftCollider(json *dbgout);
     ~ShiftCollider() throw() { };
 
     bool initSlot(Segment *seg, Slot *aSlot, const Rect &constraint,
                 float margin, float marginMin, const Position &currShift,
                 const Position &currOffset, int dir, GR_MAYBE_UNUSED json * const dbgout);
-    bool mergeSlot(Segment *seg, Slot *slot, const Position &currShift, bool isAfter, 
+    bool mergeSlot(Segment *seg, Slot *slot, const SlotCollision *cinfo, const Position &currShift, bool isAfter, 
                 bool sameCluster, bool &hasCol, bool isExclusion, GR_MAYBE_UNUSED json * const dbgout);
     Position resolve(Segment *seg, bool &isCol, GR_MAYBE_UNUSED json * const dbgout);
     void addBox_slope(bool isx, const Rect &box, const BBox &bb, const SlantBox &sb, const Position &org, float weight, float m, bool minright, int mode);
     void removeBox(const Rect &box, const BBox &bb, const SlantBox &sb, const Position &org, int mode);
     const Position &origin() const { return _origin; }
 
 #if !defined GRAPHITE2_NTRACING
 	void outputJsonDbg(json * const dbgout, Segment *seg, int axis);
--- a/gfx/graphite2/src/inc/UtfCodec.h
+++ b/gfx/graphite2/src/inc/UtfCodec.h
@@ -119,17 +119,17 @@ public:
 
 
 template <>
 struct _utf_codec<8>
 {
 private:
     static const int8 sz_lut[16];
     static const byte mask_lut[5];
-
+    static const uchar_t    limit = 0x110000;
 
 public:
     typedef uint8   codeunit_t;
 
     inline
     static void put(codeunit_t * cp, const uchar_t usv, int8 & l) throw()
     {
         if (usv < 0x80)     {l = 1; cp[0] = usv; return; }
@@ -152,17 +152,17 @@ public:
             case 3:     u <<= 6; u |= *++cp & 0x3F; if (*cp >> 6 != 2) break; ++l; toolong |= (u < 0x20); GR_FALLTHROUGH;
                 // no break
             case 2:     u <<= 6; u |= *++cp & 0x3F; if (*cp >> 6 != 2) break; ++l; toolong |= (u < 0x80); GR_FALLTHROUGH;
                 // no break
             case 1:     break;
             case 0:     l = -1; return 0xFFFD;
         }
 
-        if (l != seq_sz || toolong)
+        if (l != seq_sz || toolong  || u >= limit)
         {
             l = -l;
             return 0xFFFD;
         }
         return u;
     }
 
     inline
--- a/gfx/graphite2/src/inc/locale2lcid.h
+++ b/gfx/graphite2/src/inc/locale2lcid.h
@@ -31,18 +31,18 @@ of the License or (at your option) any l
 #include "inc/Main.h"
 
 
 namespace graphite2 {
 
 struct IsoLangEntry
 {
     unsigned short mnLang;
-    const char maLangStr[4];
-    const char maCountry[3];
+    char maLangStr[4];
+    char maCountry[3];
 };
 
 // Windows Language ID, Locale ISO-639 language, country code as used in
 // naming table of OpenType fonts
 const IsoLangEntry LANG_ENTRIES[] = {
     { 0x0401, "ar","SA" }, // Arabic Saudi Arabia
     { 0x0402, "bg","BG" }, // Bulgarian Bulgaria
     { 0x0403, "ca","ES" }, // Catalan Catalan