Bug 1443095 - Update graphite2 library to release 1.3.11. r=jrmuizel
☠☠ backed out by 66ab96fc4782 ☠ ☠
authorJonathan Kew <jkew@mozilla.com>
Mon, 05 Mar 2018 15:33:01 +0000
changeset 461603 f24d341229db8e89186ddee74f7d7ce2a280f2e4
parent 461602 e8ece564ba17e52e227dc8ce00d51db91251874f
child 461604 ea674a01296795588d20377b9e3844523ad6dcb4
push id1683
push usersfraser@mozilla.com
push dateThu, 26 Apr 2018 16:43:40 +0000
treeherdermozilla-release@5af6cb21869d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1443095
milestone60.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1443095 - Update graphite2 library to release 1.3.11. r=jrmuizel
gfx/graphite2/README.md
gfx/graphite2/README.mozilla
gfx/graphite2/include/graphite2/Font.h
gfx/graphite2/src/CMakeLists.txt
gfx/graphite2/src/Code.cpp
gfx/graphite2/src/Collider.cpp
gfx/graphite2/src/Decompressor.cpp
gfx/graphite2/src/FeatureMap.cpp
gfx/graphite2/src/FileFace.cpp
gfx/graphite2/src/Pass.cpp
gfx/graphite2/src/SegCacheEntry.cpp
gfx/graphite2/src/Segment.cpp
gfx/graphite2/src/Silf.cpp
gfx/graphite2/src/TtfUtil.cpp
gfx/graphite2/src/gr_face.cpp
gfx/graphite2/src/gr_features.cpp
gfx/graphite2/src/gr_font.cpp
gfx/graphite2/src/gr_logging.cpp
gfx/graphite2/src/gr_segment.cpp
gfx/graphite2/src/inc/Code.h
gfx/graphite2/src/inc/Collider.h
gfx/graphite2/src/inc/Compression.h
gfx/graphite2/src/inc/FeatureMap.h
gfx/graphite2/src/inc/Font.h
gfx/graphite2/src/inc/List.h
gfx/graphite2/src/inc/Machine.h
gfx/graphite2/src/inc/Main.h
gfx/graphite2/src/inc/Segment.h
gfx/graphite2/src/inc/Sparse.h
gfx/graphite2/src/inc/opcode_table.h
gfx/graphite2/src/inc/opcodes.h
--- a/gfx/graphite2/README.md
+++ b/gfx/graphite2/README.md
@@ -1,10 +1,17 @@
 # Graphite engine
 
+## Project CI status 
+Linux -- Intel 64bit:[![Build Status](http://build.palaso.org/app/rest/builds/buildType:bt124/statusIcon)](http://build.palaso.org/viewType.html?buildTypeId=bt124&guest=1)
+Intel 32bit:[![Build Status](http://build.palaso.org/app/rest/builds/buildType:bt123/statusIcon)](http://build.palaso.org/viewType.html?buildTypeId=bt123&guest=1)
+ARM 32bit:[![Build Status](http://build.palaso.org/app/rest/builds/buildType:Graphite_Linux32bitArm/statusIcon)](http://build.palaso.org/viewType.html?buildTypeId=Graphite_Linux32bitArm&guest=1)
+
+Windows -- Intel 64bit:[![Build Status](http://build.palaso.org/app/rest/builds/buildType:Graphite_Windows64bitProduction/statusIcon)](http://build.palaso.org/viewType.html?buildTypeId=Graphite_Windows64bitProduction&guest=1)
+
 ## What is Graphite?
 
 Graphite is a system that can be used to create “smart fonts” capable of displaying writing systems with various complex behaviors. A smart font contains not only letter shapes but also additional instructions indicating how to combine and position the letters in complex ways.
 
 Graphite was primarily developed to provide the flexibility needed for minority languages which often need to be written according to slightly different rules than well-known languages that use the same script.
 
 Examples of complex script behaviors Graphite can handle include:
 
--- a/gfx/graphite2/README.mozilla
+++ b/gfx/graphite2/README.mozilla
@@ -1,3 +1,3 @@
-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
+This directory contains the Graphite2 library release 1.3.11 from
+https://github.com/silnrsi/graphite/releases/download/1.3.11/graphite2-minimal-1.3.11.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  10
+#define GR2_VERSION_BUGFIX  11
 
 #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
@@ -51,26 +51,30 @@ if (GRAPHITE2_NTRACING)
     add_definitions(-DGRAPHITE2_NTRACING)
     set(TRACING)
 endif (GRAPHITE2_NTRACING)
 
 if (GRAPHITE2_TELEMETRY)
     add_definitions(-DGRAPHITE2_TELEMETRY)
 endif (GRAPHITE2_TELEMETRY)
 
+if (NOT BUILD_SHARED_LIBS)
+    add_definitions(-DGRAPHITE2_STATIC)
+endif (NOT BUILD_SHARED_LIBS)
+
 set(GRAPHITE_HEADERS 
     ../include/graphite2/Font.h
     ../include/graphite2/Segment.h
     ../include/graphite2/Types.h
     ../include/graphite2/Log.h
     )
 
 file(GLOB PRIVATE_HEADERS inc/*.h) 
 
-add_library(graphite2 SHARED
+add_library(graphite2
     ${GRAPHITE2_VM_TYPE}_machine.cpp
     gr_char_info.cpp
     gr_features.cpp
     gr_face.cpp
     gr_font.cpp
     gr_logging.cpp
     gr_segment.cpp
     gr_slot.cpp
@@ -102,19 +106,19 @@ add_library(graphite2 SHARED
 set_target_properties(graphite2 PROPERTIES  PUBLIC_HEADER "${GRAPHITE_HEADERS}"
                                             SOVERSION ${GRAPHITE_SO_VERSION}
                                             VERSION ${GRAPHITE_VERSION}
                                             LT_VERSION_CURRENT ${GRAPHITE_API_CURRENT}
                                             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}" 
+    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"
+        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}")
@@ -125,26 +129,28 @@ if  (${CMAKE_SYSTEM_NAME} STREQUAL "Linu
         target_link_libraries(graphite2 kernel32 msvcr90 mingw32 gcc user32)
     else (${CMAKE_CXX_COMPILER} MATCHES  ".*mingw.*")
         if (GRAPHITE2_ASAN)
             target_link_libraries(graphite2 c gcc_s)
         else (GRAPHITE2_ASAN)
             target_link_libraries(graphite2 c gcc)
         endif (GRAPHITE2_ASAN)
         include(Graphite)
-        nolib_test(stdc++ $<TARGET_SONAME_FILE:graphite2>)
+        if (BUILD_SHARED_LIBS)
+            nolib_test(stdc++ $<TARGET_SONAME_FILE:graphite2>)
+        endif (BUILD_SHARED_LIBS)
     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 -mfpmath=sse -msse2"
-        LINK_FLAGS      "-nodefaultlibs" 
+    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 -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/Code.cpp
+++ b/gfx/graphite2/src/Code.cpp
@@ -214,17 +214,21 @@ Machine::Code::Code(bool is_constraint, 
     // memory.
     assert((bytecode_end - bytecode_begin) >= ptrdiff_t(_instr_count));
     assert((bytecode_end - bytecode_begin) >= ptrdiff_t(_data_size));
     memmove(_code + (_instr_count+1), _data, _data_size*sizeof(byte));
     size_t const total_sz = ((_instr_count+1) + (_data_size + sizeof(instr)-1)/sizeof(instr))*sizeof(instr);
     if (_out)
         *_out += total_sz;
     else
-        _code = static_cast<instr *>(realloc(_code, total_sz));
+    {
+      instr * const old_code = _code;
+      _code = static_cast<instr *>(realloc(_code, total_sz));
+      if (!_code) free(old_code);
+    }
    _data = reinterpret_cast<byte *>(_code + (_instr_count+1));
 
     if (!_code)
     {
         failure(alloc_failed);
         return;
     }
 
@@ -311,18 +315,19 @@ opcode Machine::Code::decoder::fetch_opc
             if (_stack_depth <= 0)
                 failure(underfull_stack);
             break;
         case COND :
             _stack_depth -= 2;
             if (_stack_depth <= 0)
                 failure(underfull_stack);
             break;
+        case NEXT_N :           // runtime checked
+            break;
         case NEXT :
-        case NEXT_N :           // runtime checked
         case COPY_NEXT :
             ++_out_index;
             if (_out_index < -1 || _out_index > _out_length || _slotref > _max.rule_length)
                 failure(out_of_range_data);
             break;
         case PUT_GLYPH_8BIT_OBS :
             valid_upto(_max.classes, bc[0]);
             test_context();
--- a/gfx/graphite2/src/Collider.cpp
+++ b/gfx/graphite2/src/Collider.cpp
@@ -301,17 +301,17 @@ bool ShiftCollider::mergeSlot(Segment *s
         const float ts = tx + ty;
         const SlantBox &sb = gc.getBoundingSlantBox(gid);
         const unsigned short tgid = _target->gid();
         const BBox &tbb = gc.getBoundingBBox(tgid);
         const SlantBox &tsb = gc.getBoundingSlantBox(tgid);
         float seq_above_wt = cslot->seqAboveWt();
         float seq_below_wt = cslot->seqBelowWt();
         float seq_valign_wt = cslot->seqValignWt();
-        float lmargin = _margin;
+        float lmargin;
         // if isAfter, invert orderFlags for diagonal orders.
         if (isAfter)
         {
             // invert appropriate bits
             orderFlags ^= (sameClass ? 0x3F : 0x3);
             // consider 2 bits at a time, non overlapping. If both bits set, clear them
             orderFlags = orderFlags ^ ((((orderFlags >> 1) & orderFlags) & 0x15) * 3);
         }
@@ -553,16 +553,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();
+        if (!exclSlot)
+            return res;
         exclSlot->setGlyph(seg, cslot->exclGlyph());
         Position exclOrigin(slot->origin() + cslot->exclOffset());
         exclSlot->origin(exclOrigin);
         SlotCollision exclInfo(seg, exclSlot);
         res &= mergeSlot(seg, exclSlot, &exclInfo, currShift, isAfter, sameCluster, isCol, true, dbgout );
         seg->freeSlot(exclSlot);
     }
     hasCol |= isCol;
@@ -800,16 +802,18 @@ static float get_edge(Segment *seg, cons
                 }
             }
         }
     }
     else
     {
         const BBox &bb = gc.getBoundingBBox(gid);
         const SlantBox &sb = gc.getBoundingSlantBox(gid);
+        if (sy + bb.yi - margin > y + width / 2 || sy + bb.ya + margin < y - width / 2)
+            return res;
         float td = sx - sy + y;
         float ts = sx + sy - y;
         if (isRight)
             res = localmax(td + sb.da - width / 2, td + sb.da + width / 2, ts + sb.sa - width / 2, ts + sb.sa + width / 2, sx + bb.xa) + margin;
         else
             res = localmin(td + sb.di - width / 2, td + sb.di + width / 2, ts + sb.si - width / 2, ts + sb.si + width / 2, sx + bb.xi) - margin;
     }
     return res;
@@ -919,17 +923,17 @@ bool KernCollider::initSlot(Segment *seg
                     _edges[i] = t;
                     if (t > _xbound)
                         _xbound = t;
                 }
             }
         }
     }
     done:
-    _mingap = (float)1e38;
+    _mingap = (float)1e37;      // less than 1e38 s.t. 1e38-_mingap is really big
     _target = aSlot;
     _margin = margin;
     _currShift = currShift;
     return true;
 }   // end of KernCollider::initSlot
 
 
 // Determine how much the target slot needs to kern away from the given slot.
@@ -940,53 +944,64 @@ bool KernCollider::mergeSlot(Segment *se
 {
     int rtl = (dir & 1) * 2 - 1;
     if (!seg->getFace()->glyphs().check(slot->gid()))
         return false;
     const Rect &bb = seg->theGlyphBBoxTemporary(slot->gid());
     const float sx = slot->origin().x + currShift.x;
     float x = (sx + (rtl > 0 ? bb.tr.x : bb.bl.x)) * rtl;
     // this isn't going to reduce _mingap so skip
-    if (x < rtl * (_xbound - _mingap - currSpace))
+    if (_hit && x < rtl * (_xbound - _mingap - currSpace))
         return false;
 
     const float sy = slot->origin().y + currShift.y;
     int smin = max(1, int((bb.bl.y + (1 - _miny + sy)) / _sliceWidth + 1)) - 1;
     int smax = min((int)_edges.size() - 2, int((bb.tr.y + (1 - _miny + sy)) / _sliceWidth + 1)) + 1;
     if (smin > smax)
         return false;
     bool collides = false;
+    bool nooverlap = true;
 
     for (int i = smin; i <= smax; ++i)
     {
-        float t;
         float here = _edges[i] * rtl;
-        float y = (float)(_miny - 1 + (i + .5f) * _sliceWidth);  // vertical center of slice
-        if (    (x > here - _mingap - currSpace) )
+        if (here > (float)9e37)
+            continue;
+        if (!_hit || x > here - _mingap - currSpace)
         {
+            float y = (float)(_miny - 1 + (i + .5f) * _sliceWidth);  // vertical center of slice
             // 2 * currSpace to account for the space that is already separating them and the space we want to add
             float m = get_edge(seg, slot, currShift, y, _sliceWidth, 0., rtl > 0) * rtl + 2 * currSpace;
-            t = here - m;
+            if (m < (float)-8e37)       // only true if the glyph has a gap in it
+                continue;
+            nooverlap = false;
+            float t = here - m;
             // _mingap is positive to shrink
-            if (t < _mingap)
+            if (t < _mingap || (!_hit && !collides))
             {
                 _mingap = t;
                 collides = true;
             }
 #if !defined GRAPHITE2_NTRACING
             // Debugging - remember the closest neighboring edge for this slice.
             if (m > rtl * _nearEdges[i])
             {
                 _slotNear[i] = slot;
                 _nearEdges[i] = m * rtl;
             }
 #endif
         }
+        else
+            nooverlap = false;
     }
-    return collides;   // note that true is not a necessarily reliable value
+    if (nooverlap)
+        _mingap = max(_mingap, _xbound + currSpace + _margin - x);
+    if (collides && !nooverlap)
+        _hit = true;
+    return collides | nooverlap;   // note that true is not a necessarily reliable value
     
 }   // end of KernCollider::mergeSlot
 
 
 // Return the amount to kern by.
 Position KernCollider::resolve(GR_MAYBE_UNUSED Segment *seg, GR_MAYBE_UNUSED Slot *slot,
         int dir, GR_MAYBE_UNUSED json * const dbgout)
 {
--- a/gfx/graphite2/src/Decompressor.cpp
+++ b/gfx/graphite2/src/Decompressor.cpp
@@ -38,78 +38,89 @@ u32 read_literal(u8 const * &s, u8 const
     if (l == 15 && s != e)
     {
         u8 b = 0;
         do { l += b = *s++; } while(b==0xff && s != e);
     }
     return l;
 }
 
-bool read_sequence(u8 const * &src, u8 const * const end, u8 const * &literal, u32 & literal_len, u32 & match_len, u32 & match_dist)
+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 || src < literal)
+
+    // Normal exit for end of stream, wrap arround check and parital match check.
+    if (src > end - sizeof(u16) || src < literal)
         return false;
     
     match_dist  = *src++;
     match_dist |= *src++ << 8;
-    match_len = read_literal(src, end, token & 0xf);
-    
-    return src <= end-5;
+    match_len = read_literal(src, end, token & 0xf) + MINMATCH;
+
+    // Malformed stream check.
+    return src <= end-MINCODA;
 }
 
 }
 
 int lz4::decompress(void const *in, size_t in_size, void *out, size_t out_size)
 {
-    if (out_size <= in_size || in_size < sizeof(unsigned long)+1)
+    if (out_size <= in_size || in_size < MINSRCSIZE)
         return -1;
     
     u8 const *       src     = static_cast<u8 const *>(in),
              *       literal = 0,
              * const src_end = src + in_size;
 
     u8 *       dst     = static_cast<u8*>(out),
        * const dst_end = dst + out_size;
-    
+
+    // Check the in and out size hasn't wrapped around.
+    if (src >= src_end || dst >= dst_end)
+        return -1;
+
     u32 literal_len = 0,
         match_len = 0,
         match_dist = 0;
-    
-    while (read_sequence(src, src_end, literal, literal_len, match_len, match_dist))
+
+    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 (align(literal_len) > unsigned(dst_end - dst - (MINMATCH+5)) || dst_end - dst < MINMATCH + 5)
+            // Copy in literal. At this point the a minimal literal + minminal
+            // match plus the coda (1 + 2 + 5) must be 8 bytes or more allowing
+            // us to remain within the src buffer for an overrun_copy on
+            // machines upto 64 bits.
+            if (align(literal_len) > out_size)
                 return -1;
             dst = overrun_copy(dst, literal, literal_len);
+            out_size -= 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)
-                  || pcpy >= dst
-                  || match_len > unsigned(dst_end - dst - (MINMATCH+5))
-                  || dst_end - dst < MINMATCH + 5)
+              || match_len > unsigned(out_size - LASTLITERALS)
+              // Wrap around checks:
+              || out_size < LASTLITERALS || pcpy >= dst)
             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 (dst > pcpy+sizeof(unsigned long)
+            && align(match_len) <= out_size)
+            dst = overrun_copy(dst, pcpy, match_len);
+        else
+            dst = safe_copy(dst, pcpy, match_len);
+        out_size -= match_len;
     }
-    
-    if (literal_len > src_end - literal
-              || literal_len > dst_end - dst)
+
+    if (literal > src_end - literal_len || literal_len > out_size)
         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
@@ -68,17 +68,17 @@ namespace
         return max_val;
     }
 }
 
 FeatureRef::FeatureRef(const Face & face,
     unsigned short & bits_offset, uint32 max_val,
     uint32 name, uint16 uiName, uint16 flags,
     FeatureSetting *settings, uint16 num_set) throw()
-: m_pFace(&face),
+: m_face(face),
   m_nameValues(settings),
   m_mask(mask_over_val(max_val)),
   m_max(max_val),
   m_id(name),
   m_nameid(uiName),
   m_flags(flags),
   m_numSet(num_set)
 {
@@ -115,17 +115,17 @@ bool FeatureMap::readFeats(const Face & 
     if (m_numFeats == 0)    return true;
     if (version < 0x00010000 ||
         p + m_numFeats*FEATURE_SIZE > feat_end)
     {   //defensive
         m_numFeats = 0;
         return false;
     }
 
-    m_feats = new FeatureRef [m_numFeats];
+    m_feats = grzeroalloc<FeatureRef>(m_numFeats);
     uint16 * const  defVals = gralloc<uint16>(m_numFeats);
     if (!defVals || !m_feats) return false;
     unsigned short bits = 0;     //to cause overflow on first Feature
 
     for (int i = 0, ie = m_numFeats; i != ie; i++)
     {
         const uint32    label   = version < 0x00020000 ? be::read<uint16>(p) : be::read<uint32>(p);
         const uint16    num_settings = be::read<uint16>(p);
@@ -171,19 +171,19 @@ bool FeatureMap::readFeats(const Face & 
     if (!m_pNamedFeats)
     {
         free(defVals);
         return false;
     }
     for (int i = 0; i < m_numFeats; ++i)
     {
         m_feats[i].applyValToFeature(defVals[i], m_defaultFeatures);
-        m_pNamedFeats[i] = m_feats+i;
+        m_pNamedFeats[i] = m_feats[i];
     }
-    
+
     free(defVals);
 
     qsort(m_pNamedFeats, m_numFeats, sizeof(NameAndFeatureRef), &cmpNameAndFeatures);
 
     return true;
 }
 
 bool SillMap::readFace(const Face & face)
@@ -262,32 +262,30 @@ const FeatureRef *FeatureMap::findFeatur
     
     for (it = m_pNamedFeats; it < m_pNamedFeats + m_numFeats; ++it)
         if (it->m_name == name)
             return it->m_pFRef;
     return NULL;
 }
 
 bool FeatureRef::applyValToFeature(uint32 val, Features & pDest) const
-{ 
-    if (val>maxVal() || !m_pFace)
+{
+    if (val>maxVal())
       return false;
     if (pDest.m_pMap==NULL)
-      pDest.m_pMap = &m_pFace->theSill().theFeatureMap();
+      pDest.m_pMap = &m_face.theSill().theFeatureMap();
     else
-      if (pDest.m_pMap!=&m_pFace->theSill().theFeatureMap())
+      if (pDest.m_pMap!=&m_face.theSill().theFeatureMap())
         return false;       //incompatible
     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) 
-    return (feats[m_index] & m_mask) >> m_bits; 
+{
+  if (m_index < feats.size() && &m_face.theSill().theFeatureMap()==feats.m_pMap)
+    return (feats[m_index] & m_mask) >> m_bits;
   else
     return 0;
 }
-
-
--- a/gfx/graphite2/src/FileFace.cpp
+++ b/gfx/graphite2/src/FileFace.cpp
@@ -87,17 +87,17 @@ const void *FileFace::get_table_fn(const
     if (!TtfUtil::GetTableInfo(name, file_face._header_tbl, file_face._table_dir, tbl_offset, tbl_len))
         return 0;
 
     if (tbl_offset > file_face._file_len || tbl_len > file_face._file_len - tbl_offset
             || fseek(file_face._file, tbl_offset, SEEK_SET) != 0)
         return 0;
 
     tbl = malloc(tbl_len);
-    if (fread(tbl, 1, tbl_len, file_face._file) != tbl_len)
+    if (!tbl || fread(tbl, 1, tbl_len, file_face._file) != tbl_len)
     {
         free(tbl);
         return 0;
     }
 
     if (len) *len = tbl_len;
     return tbl;
 }
--- a/gfx/graphite2/src/Pass.cpp
+++ b/gfx/graphite2/src/Pass.cpp
@@ -166,17 +166,19 @@ 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(2u*m_numTransition*m_numColumns >= (unsigned)(pass_end - p), E_BADPASSLENGTH)) return face.error(e);
+    if (e.test(2u*m_numTransition*m_numColumns >= (unsigned)(pass_end - p), E_BADPASSLENGTH)
+            || e.test(p >= pass_end, 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);
@@ -265,20 +267,21 @@ bool Pass::readRules(const byte * rule_m
 
         if (e.test(!r->action || !r->constraint, E_OUTOFMEM)
                 || e.test(r->action->status() != Code::loaded, r->action->status() + E_CODEFAILURE)
                 || e.test(r->constraint->status() != Code::loaded, r->constraint->status() + E_CODEFAILURE)
                 || e.test(!r->constraint->immutable(), E_MUTABLECCODE))
             return face.error(e);
     }
 
-    byte * moved_progs = static_cast<byte *>(realloc(m_progs, prog_pool_free - m_progs));
+    byte * const moved_progs = prog_pool_free > m_progs ? static_cast<byte *>(realloc(m_progs, prog_pool_free - m_progs)) : 0;
     if (e.test(!moved_progs, E_OUTOFMEM))
     {
-        if (prog_pool_free - m_progs == 0) m_progs = 0;
+        free(m_progs);
+        m_progs = 0;
         return face.error(e);
     }
 
     if (moved_progs != m_progs)
     {
         for (Code * c = m_codes, * const ce = c + m_numRules*2; c != ce; ++c)
         {
             c->externalProgramMoved(moved_progs - m_progs);
@@ -709,28 +712,28 @@ void Pass::adjustSlot(int delta, Slot * 
             slot_out = smap.segment.first();
             --delta;
         }
     }
     if (delta < 0)
     {
         while (++delta <= 0 && slot_out)
         {
+            slot_out = slot_out->prev();
             if (smap.highpassed() && smap.highwater() == slot_out)
                 smap.highpassed(false);
-            slot_out = slot_out->prev();
         }
     }
     else if (delta > 0)
     {
         while (--delta >= 0 && slot_out)
         {
-            slot_out = slot_out->next();
             if (slot_out == smap.highwater() && slot_out)
                 smap.highpassed(true);
+            slot_out = slot_out->next();
         }
     }
 }
 
 bool Pass::collisionShift(Segment *seg, int dir, json * const dbgout) const
 {
     ShiftCollider shiftcoll(dbgout);
     // bool isfirst = true;
@@ -963,18 +966,18 @@ bool Pass::resolveCollisions(Segment *se
     // Look for collisions with the neighboring glyphs.
     for (nbor = start; nbor; nbor = isRev ? nbor->prev() : nbor->next())
     {
         SlotCollision *cNbor = seg->collisionInfo(nbor);
         bool sameCluster = nbor->isChildOf(base);
         if (nbor != slotFix         						// don't process if this is the slot of interest
                       && !(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)
+                            || !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, 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.
@@ -1032,26 +1035,30 @@ float Pass::resolveKern(Segment *seg, Sl
     float currSpace = 0.;
     bool collides = false;
     unsigned int space_count = 0;
     Slot *base = slotFix;
     while (base->attachedTo())
         base = base->attachedTo();
     SlotCollision *cFix = seg->collisionInfo(base);
     const GlyphCache &gc = seg->getFace()->glyphs();
+    const Rect &bbb = seg->theGlyphBBoxTemporary(slotFix->gid());
+    const float by = slotFix->origin().y + cFix->shift().y;
 
     if (base != slotFix)
     {
         cFix->setFlags(cFix->flags() | SlotCollision::COLL_KERN | SlotCollision::COLL_FIX);
         return 0;
     }
     bool seenEnd = (cFix->flags() & SlotCollision::COLL_END) != 0;
     bool isInit = false;
     KernCollider coll(dbgout);
 
+    ymax = max(by + bbb.tr.y, ymax);
+    ymin = min(by + bbb.bl.y, ymin);
     for (nbor = slotFix->next(); nbor; nbor = nbor->next())
     {
         if (nbor->isChildOf(base))
             continue;
         if (!gc.check(nbor->gid()))
             return 0.;
         const Rect &bb = seg->theGlyphBBoxTemporary(nbor->gid());
         SlotCollision *cNbor = seg->collisionInfo(nbor);
@@ -1061,19 +1068,16 @@ float Pass::resolveKern(Segment *seg, Sl
                 break;
             // Add space for a space glyph.
             currSpace += nbor->advance();
             ++space_count;
         }
         else
         {
             space_count = 0; 
-            float y = nbor->origin().y + cNbor->shift().y;
-            ymax = max(y + bb.tr.y, ymax);
-            ymin = min(y + bb.bl.y, ymin);
             if (nbor != slotFix && !cNbor->ignore())
             {
                 seenEnd = true;
                 if (!isInit)
                 {
                     if (!coll.initSlot(seg, slotFix, cFix->limit(), cFix->margin(),
                                     cFix->shift(), cFix->offset(), dir, ymin, ymax, dbgout))
                         return 0.;
--- a/gfx/graphite2/src/SegCacheEntry.cpp
+++ b/gfx/graphite2/src/SegCacheEntry.cpp
@@ -37,17 +37,17 @@ of the License or (at your option) any l
 using namespace graphite2;
 
 SegCacheEntry::SegCacheEntry(const uint16* cmapGlyphs, size_t length, Segment * seg, size_t charOffset, long long cacheTime)
     : m_glyphLength(0), m_unicode(gralloc<uint16>(length)), m_glyph(NULL),
     m_attr(NULL), m_justs(NULL),
     m_accessCount(0), m_lastAccess(cacheTime)
 {
     if (m_unicode)
-        for (uint16 i = 0; i < length; i++)
+        for (size_t i = 0; i < length; i++)
             m_unicode[i] = cmapGlyphs[i];
 
     const size_t    glyphCount = seg->slotCount(),
                     sizeof_sjust = SlotJustify::size_of(seg->silf()->numJustLevels());
     if (!glyphCount) return;
     size_t num_justs = 0,
            justs_pos = 0;
     if (seg->hasJustification())
--- a/gfx/graphite2/src/Segment.cpp
+++ b/gfx/graphite2/src/Segment.cpp
@@ -54,17 +54,19 @@ Segment::Segment(unsigned int numchars, 
   m_bufSize(numchars + 10),
   m_numGlyphs(numchars),
   m_numCharinfo(numchars),
   m_passBits(m_silf->aPassBits() ? -1 : 0),
   m_defaultOriginal(0),
   m_dir(textDir),
   m_flags(((m_silf->flags() & 0x20) != 0) << 1)
 {
-    freeSlot(newSlot());
+    Slot *s = newSlot();
+    if (s)
+        freeSlot(s);
     m_bufSize = log_binary(numchars)+1;
 }
 
 Segment::~Segment()
 {
     for (SlotRope::iterator i = m_slots.begin(); i != m_slots.end(); ++i)
         free(*i);
     for (AttributeRope::iterator i = m_userAttrs.begin(); i != m_userAttrs.end(); ++i)
--- a/gfx/graphite2/src/Silf.cpp
+++ b/gfx/graphite2/src/Silf.cpp
@@ -271,16 +271,17 @@ size_t Silf::readClassMap(const byte *p,
         max_off = readClassOffsets<uint16>(p, data_len, e);
 
     if (max_off == ERROROFFSET) return ERROROFFSET;
 
     if (e.test((int)max_off < m_nLinear + (m_nClass - m_nLinear) * 6, E_CLASSESTOOBIG))
         return ERROROFFSET;
 
     // Check the linear offsets are sane, these must be monotonically increasing.
+    assert(m_nClass >= m_nLinear);
     for (const uint32 *o = m_classOffsets, * const o_end = o + m_nLinear; o != o_end; ++o)
         if (e.test(o[0] > o[1], E_BADCLASSOFFSET))
             return ERROROFFSET;
 
     // Fortunately the class data is all uint16s so we can decode these now
     m_classData = gralloc<uint16>(max_off);
     if (e.test(!m_classData, E_OUTOFMEM)) return ERROROFFSET;
     for (uint16 *d = m_classData, * const d_end = d + max_off; d != d_end; ++d)
--- a/gfx/graphite2/src/TtfUtil.cpp
+++ b/gfx/graphite2/src/TtfUtil.cpp
@@ -336,16 +336,21 @@ bool CheckTable(const Tag TableId, const
     {
         const Sfnt::FontNames * pName 
             = reinterpret_cast<const Sfnt::FontNames *>(pTable);
         if (lTableSize < sizeof(Sfnt::FontNames))
             return false;
         return be::swap(pName->format) == 0;
     }
 
+    case Tag::glyf:
+    {
+        return (lTableSize >= sizeof(Sfnt::Glyph));
+    }
+
     default:
         break;
     }
 
     return true;
 }
 
 /*----------------------------------------------------------------------------------------------
@@ -459,17 +464,17 @@ void HeadTableCreateTime(const void * pH
 
     Note: this method is not currently used by the Graphite engine.
 ----------------------------------------------------------------------------------------------*/
 void HeadTableModifyTime(const void * pHead,
     unsigned int * pnDateBC, unsigned int *pnDateAD)
 {
     const Sfnt::FontHeader * pTable = 
             reinterpret_cast<const Sfnt::FontHeader *>(pHead);
-    
+   ; 
     *pnDateBC = be::swap(pTable->modified[0]);
     *pnDateAD = be::swap(pTable->modified[1]);
 }
 
 /*----------------------------------------------------------------------------------------------
     Return true if the font is italic.
 ----------------------------------------------------------------------------------------------*/
 bool IsItalic(const void * pHead)
@@ -1242,17 +1247,17 @@ size_t LocaLookup(gid16 nGlyphId,
 
 /*----------------------------------------------------------------------------------------------
     Return a pointer into the glyf table based on the given offset (from LocaLookup).
     Return NULL on error.
 ----------------------------------------------------------------------------------------------*/
 void * GlyfLookup(const void * pGlyf, size_t nGlyfOffset, size_t nTableLen)
 {
     const uint8 * pByte = reinterpret_cast<const uint8 *>(pGlyf);
-        if (nGlyfOffset + pByte < pByte || nGlyfOffset + sizeof(Sfnt::Glyph) >= nTableLen)
+        if (nGlyfOffset + pByte < pByte || nGlyfOffset >= nTableLen - sizeof(Sfnt::Glyph))
             return NULL;
     return const_cast<uint8 *>(pByte + nGlyfOffset);
 }
 
 /*----------------------------------------------------------------------------------------------
     Get the bounding box coordinates for a simple glyf entry (non-composite).
     Return true if successful, false otherwise.
 ----------------------------------------------------------------------------------------------*/
--- a/gfx/graphite2/src/gr_face.cpp
+++ b/gfx/graphite2/src/gr_face.cpp
@@ -190,17 +190,17 @@ gr_uint32 gr_face_lang_by_index(const gr
 {
     assert(pFace);
     return pFace->theSill().getLangName(i);
 }
 
 
 void gr_face_destroy(gr_face *face)
 {
-    delete face;
+    delete static_cast<Face*>(face);
 }
 
 
 gr_uint16 gr_face_name_lang_for_locale(gr_face *face, const char * locale)
 {
     if (face)
     {
         return face->languageForLocale(locale);
--- a/gfx/graphite2/src/gr_features.cpp
+++ b/gfx/graphite2/src/gr_features.cpp
@@ -75,45 +75,45 @@ gr_int16 gr_fref_value(const gr_feature_
         return 0;
     }
     return pfeatureref->getSettingValue(settingno);
 }
 
 
 void* gr_fref_label(const gr_feature_ref* pfeatureref, gr_uint16 *langId, gr_encform utf, gr_uint32 *length)
 {
-    if(!pfeatureref || !pfeatureref->getFace())
+    if(!pfeatureref)
     {
         langId = 0;
         length = 0;
         return NULL;
     }
     uint16 label = pfeatureref->getNameId();
-    NameTable * names = pfeatureref->getFace()->nameTable();
+    NameTable * names = pfeatureref->getFace().nameTable();
     if (!names)
     {
         langId = 0;
         length = 0;
         return NULL;
     }
     return names->getName(*langId, label, utf, *length);
 }
 
 
 void* gr_fref_value_label(const gr_feature_ref*pfeatureref, gr_uint16 setting,
     gr_uint16 *langId, gr_encform utf, gr_uint32 *length)
 {
-    if(!pfeatureref || (setting >= pfeatureref->getNumSettings()) || !pfeatureref->getFace())
+    if(!pfeatureref || (setting >= pfeatureref->getNumSettings()))
     {
         langId = 0;
         length = 0;
         return NULL;
     }
     uint16 label = pfeatureref->getSettingName(setting);
-    NameTable * names = pfeatureref->getFace()->nameTable();
+    NameTable * names = pfeatureref->getFace().nameTable();
     if (!names)
     {
         langId = 0;
         length = 0;
         return NULL;
     }
     return names->getName(*langId, label, utf, *length);
 }
@@ -126,13 +126,13 @@ void gr_label_destroy(void * label)
 
 gr_feature_val* gr_featureval_clone(const gr_feature_val* pfeatures/*may be NULL*/)
 {                      //When finished with the Features, call features_destroy    
     return static_cast<gr_feature_val*>(pfeatures ? new Features(*pfeatures) : new Features);
 }
   
 void gr_featureval_destroy(gr_feature_val *p)
 {
-    delete p;
+    delete static_cast<Features*>(p);
 }
 
 
 } // extern "C"
--- a/gfx/graphite2/src/gr_font.cpp
+++ b/gfx/graphite2/src/gr_font.cpp
@@ -42,31 +42,37 @@ void gr_engine_version(int *nMajor, int 
 gr_font* gr_make_font(float ppm/*pixels per em*/, const gr_face *face)
 {
     return gr_make_font_with_advance_fn(ppm, 0, 0, face);
 }
 
 
 gr_font* gr_make_font_with_ops(float ppm/*pixels per em*/, const void* appFontHandle/*non-NULL*/, const gr_font_ops * font_ops, const gr_face * face/*needed for scaling*/)
 {                 //the appFontHandle must stay alive all the time when the gr_font is alive. When finished with the gr_font, call destroy_gr_font    
-    if (face == 0)  return 0;
+    if (face == 0 || ppm <= 0)  return 0;
 
     Font * const res = new Font(ppm, *face, appFontHandle, font_ops);
-    return static_cast<gr_font*>(res);
+    if (*res)
+        return static_cast<gr_font*>(res);
+    else
+    {
+        delete res;
+        return 0;
+    }
 }
 
 gr_font* gr_make_font_with_advance_fn(float ppm/*pixels per em*/, const void* appFontHandle/*non-NULL*/, gr_advance_fn getAdvance, const gr_face * face/*needed for scaling*/)
 {
     const gr_font_ops ops = {sizeof(gr_font_ops), getAdvance, NULL};
     return gr_make_font_with_ops(ppm, appFontHandle, &ops, face);
 }
 
 void gr_font_destroy(gr_font *font)
 {
-    delete font;
+    delete static_cast<Font*>(font);
 }
 
 
 } // extern "C"
 
 
 
 
--- a/gfx/graphite2/src/gr_logging.cpp
+++ b/gfx/graphite2/src/gr_logging.cpp
@@ -36,17 +36,17 @@ of the License or (at your option) any l
 
 #if defined _WIN32
 #include "windows.h"
 #endif
 
 using namespace graphite2;
 
 #if !defined GRAPHITE2_NTRACING
-json *global_log = NULL;
+json *global_log = 0;
 #endif
 
 extern "C" {
 
 bool gr_start_logging(GR_MAYBE_UNUSED gr_face * face, const char *log_path)
 {
     if (!log_path)  return false;
 
@@ -115,16 +115,17 @@ void gr_stop_logging(GR_MAYBE_UNUSED gr_
         FILE * log = face->logger()->stream();
         face->setLogger(0);
         fclose(log);
     }
     else if (!face && global_log)
     {
         FILE * log = global_log->stream();
         delete global_log;
+        global_log = 0;
         fclose(log);
     }
 #endif
 }
 
 void graphite_stop_logging()
 {
 //    if (dbgout) delete dbgout;
@@ -209,17 +210,17 @@ json & graphite2::operator << (json & j,
         j << "parent" << json::flat << json::object
             << "id"             << objectid(dslot(&seg, s.attachedTo()))
             << "level"          << s.getAttr(0, gr_slatAttLevel, 0)
             << "offset"         << s.attachOffset()
             << json::close;
     j << "user" << json::flat << json::array;
     for (int n = 0; n!= seg.numAttrs(); ++n)
         j   << s.userAttrs()[n];
-        j   << json::close;
+    j       << json::close;
     if (s.firstChild())
     {
         j   << "children" << json::flat << json::array;
         for (const Slot *c = s.firstChild(); c; c = c->nextSibling())
             j   << objectid(dslot(&seg, c));
         j       << json::close;
     }
     if (cslot)
--- a/gfx/graphite2/src/gr_segment.cpp
+++ b/gfx/graphite2/src/gr_segment.cpp
@@ -98,25 +98,25 @@ size_t gr_count_unicode_characters(gr_en
 
 
 gr_segment* gr_make_seg(const gr_font *font, const gr_face *face, gr_uint32 script, const gr_feature_val* pFeats, gr_encform enc, const void* pStart, size_t nChars, int dir)
 {
     const gr_feature_val * tmp_feats = 0;
     if (pFeats == 0)
         pFeats = tmp_feats = static_cast<const gr_feature_val*>(face->theSill().cloneFeatures(0));
     gr_segment * seg = makeAndInitialize(font, face, script, pFeats, enc, pStart, nChars, dir);
-    delete tmp_feats;
+    delete static_cast<const FeatureVal*>(tmp_feats);
 
     return seg;
 }
 
 
 void gr_seg_destroy(gr_segment* p)
 {
-    delete p;
+    delete static_cast<Segment*>(p);
 }
 
 
 float gr_seg_advance_X(const gr_segment* pSeg/*not NULL*/)
 {
     assert(pSeg);
     return pSeg->advance().x;
 }
--- a/gfx/graphite2/src/inc/Code.h
+++ b/gfx/graphite2/src/inc/Code.h
@@ -157,15 +157,15 @@ inline Machine::Code & Machine::Code::op
     rhs._own = false;
     return *this;
 }
 
 inline void Machine::Code::externalProgramMoved(ptrdiff_t dist) throw()
 {
     if (_code && !_own)
     {
-        _code += dist / sizeof(instr);
+        _code += dist / signed(sizeof(instr));
         _data += dist;
     }
 }
 
 } // namespace vm
 } // namespace graphite2
--- a/gfx/graphite2/src/inc/Collider.h
+++ b/gfx/graphite2/src/inc/Collider.h
@@ -205,16 +205,17 @@ private:
     Position _offsetPrev;   // kern from a previous pass
     Position _currShift;    // NOT USED??
     float _miny;	        // y-coordinates offset by global slot position
     float _maxy;
     Vector<float> _edges;   // edges of horizontal slices
     float _sliceWidth;      // width of each slice
     float _mingap;
     float _xbound;        // max or min edge
+    bool  _hit;
 
 #if !defined GRAPHITE2_NTRACING    
     // Debugging
     Segment * _seg;
     Vector<float> _nearEdges; // closest potential collision in each slice
     Vector<Slot*> _slotNear;
 #endif
 };	// end of class KernCollider
@@ -228,17 +229,18 @@ float sqr(float x) {
 inline
 KernCollider::KernCollider(GR_MAYBE_UNUSED json *dbg)
 : _target(0),
   _margin(0.0f),
   _miny(-1e38f),
   _maxy(1e38f),
   _sliceWidth(0.0f),
   _mingap(0.0f),
-  _xbound(0.0)
+  _xbound(0.0),
+  _hit(false)
 {
 #if !defined GRAPHITE2_NTRACING
     _seg = 0;
 #endif
 };
 
 };  // end of namespace graphite2
 
--- a/gfx/graphite2/src/inc/Compression.h
+++ b/gfx/graphite2/src/inc/Compression.h
@@ -42,17 +42,20 @@ typedef unsigned __int64 u64;
 #else
 #include <stdint.h>
 typedef uint8_t u8;
 typedef uint16_t u16;
 typedef uint32_t u32;
 typedef uint64_t u64;
 #endif
 
-ptrdiff_t const     MINMATCH  = 4;
+ptrdiff_t const     MINMATCH = 4,
+                    LASTLITERALS = 5,
+                    MINCODA  = LASTLITERALS+1,
+                    MINSRCSIZE = 13;
 
 template<int S>
 inline 
 void unaligned_copy(void * d, void const * s) {
   ::memcpy(d, s, S);
 }
 
 inline
--- a/gfx/graphite2/src/inc/FeatureMap.h
+++ b/gfx/graphite2/src/inc/FeatureMap.h
@@ -51,17 +51,16 @@ private:
 };
 
 class FeatureRef
 {
     typedef uint32      chunk_t;
     static const uint8  SIZEOF_CHUNK = sizeof(chunk_t)*8;
 
 public:
-    FeatureRef();
     FeatureRef(const Face & face, unsigned short & bits_offset, uint32 max_val,
                uint32 name, uint16 uiName, uint16 flags,
                FeatureSetting *settings, uint16 num_set) throw();
     ~FeatureRef() throw();
 
     bool applyValToFeature(uint32 val, Features& pDest) const; //defined in GrFaceImp.h
     void maskFeature(Features & pDest) const {
     if (m_index < pDest.size())                 //defensive
@@ -71,69 +70,60 @@ public:
     uint32 getFeatureVal(const Features& feats) const; //defined in GrFaceImp.h
 
     uint32 getId() const { return m_id; }
     uint16 getNameId() const { return m_nameid; }
     uint16 getNumSettings() const { return m_numSet; }
     uint16 getSettingName(uint16 index) const { return m_nameValues[index].label(); }
     int16  getSettingValue(uint16 index) const { return m_nameValues[index].value(); }
     uint32 maxVal() const { return m_max; }
-    const Face* getFace() const { return m_pFace;}
+    const Face & getFace() const { return m_face;}
     const FeatureMap* getFeatureMap() const;// { return m_pFace;}
 
     CLASS_NEW_DELETE;
 private:
     FeatureRef(const FeatureRef & rhs);
 
-    const Face     * m_pFace;   //not NULL
+    const Face     & m_face;
     FeatureSetting * m_nameValues; // array of name table ids for feature values
     chunk_t m_mask,             // bit mask to get the value from the vector
             m_max;              // max value the value can take
     uint32  m_id;               // feature identifier/name
     uint16  m_nameid,            // Name table id for feature name
             m_flags,             // feature flags (unused at the moment but read from the font)
             m_numSet;            // number of values (number of entries in m_nameValues)
     byte    m_bits,             // how many bits to shift the value into place
             m_index;            // index into the array to find the ulong to mask
 
 private:        //unimplemented
     FeatureRef& operator=(const FeatureRef&);
 };
 
 
-inline
-FeatureRef::FeatureRef()
-: m_pFace(0), m_nameValues(0),
-  m_mask(0), m_max(0), m_id(0),
-  m_nameid(0), m_flags(0), m_numSet(0),
-  m_bits(0), m_index(0)
-{
-}
-
 
 class NameAndFeatureRef
 {
   public:
     NameAndFeatureRef(uint32 name = 0) : m_name(name) , m_pFRef(NULL){}
-    NameAndFeatureRef(const FeatureRef* p/*not NULL*/) : m_name(p->getId()), m_pFRef(p) {}
+    NameAndFeatureRef(FeatureRef const & p) : m_name(p.getId()), m_pFRef(&p) {}
 
     bool operator<(const NameAndFeatureRef& rhs) const //orders by m_name
         {   return m_name<rhs.m_name; }
 
     CLASS_NEW_DELETE
- 
+
     uint32 m_name;
     const FeatureRef* m_pFRef;
 };
 
 class FeatureMap
 {
 public:
     FeatureMap() : m_numFeats(0), m_feats(NULL), m_pNamedFeats(NULL) {}
-    ~FeatureMap() { delete [] m_feats; delete[] m_pNamedFeats; }
+    ~FeatureMap() { free(m_feats); delete[] m_pNamedFeats; }
 
     bool readFeats(const Face & face);
     const FeatureRef *findFeatureRef(uint32 name) const;
     FeatureRef *feature(uint16 index) const { return m_feats + index; }
     //GrFeatureRef *featureRef(byte index) { return index < m_numFeats ? m_feats + index : NULL; }
     const FeatureRef *featureRef(byte index) const { return index < m_numFeats ? m_feats + index : NULL; }
     FeatureVal* cloneFeatures(uint32 langname/*0 means default*/) const;      //call destroy_Features when done.
     uint16 numFeats() const { return m_numFeats; };
--- a/gfx/graphite2/src/inc/Font.h
+++ b/gfx/graphite2/src/inc/Font.h
@@ -39,16 +39,17 @@ class Font
 public:
     Font(float ppm, const Face & face, const void * appFontHandle=0, const gr_font_ops * ops=0);
     virtual ~Font();
 
     float advance(unsigned short glyphid) const;
     float scale() const;
     bool isHinted() const;
     const Face & face() const;
+    operator bool () const throw()  { return m_advances; }
 
     CLASS_NEW_DELETE;
 private:
     gr_font_ops         m_ops;
     const void  * const m_appFontHandle;
     float             * m_advances;  // One advance per glyph in pixels. Nan if not defined
     const Face        & m_face;
     float               m_scale;      // scales from design units to ppm
--- a/gfx/graphite2/src/inc/List.h
+++ b/gfx/graphite2/src/inc/List.h
@@ -29,16 +29,17 @@ of the License or (at your option) any l
 #pragma once
 
 #include <cstddef>
 #include <cassert>
 #include <cstring>
 #include <cstdlib>
 #include <new>
 
+#include "Main.h"
 
 namespace graphite2 {
 
 template <typename T> 
 inline
 ptrdiff_t distance(T* first, T* last) { return last-first; }
 
 
@@ -99,17 +100,19 @@ private:
     
 template <typename T>
 inline 
 void Vector<T>::reserve(size_t n)
 {
     if (n > capacity()) 
     {
         const ptrdiff_t sz = size();
-        m_first = static_cast<T*>(realloc(m_first, n*sizeof(T)));
+        size_t requested;
+        if (checked_mul(n,sizeof(T), requested))  std::abort();
+        m_first = static_cast<T*>(realloc(m_first, requested));
         if (!m_first)   std::abort();
         m_last  = m_first + sz;
         m_end   = m_first + n;
     }
 }
 
 template <typename T>
 inline
--- a/gfx/graphite2/src/inc/Machine.h
+++ b/gfx/graphite2/src/inc/Machine.h
@@ -10,33 +10,34 @@
 
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     Lesser General Public License for more details.
 
     You should also have received a copy of the GNU Lesser General Public
     License along with this library in the file named "LICENSE".
-    If not, write to the Free Software Foundation, 51 Franklin Street, 
-    Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 
+    If not, write to the Free Software Foundation, 51 Franklin Street,
+    Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
     internet at http://www.fsf.org/licenses/lgpl.html.
 
 Alternatively, the contents of this file may be used under the terms of the
 Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
 License, as published by the Free Software Foundation, either version 2
 of the License or (at your option) any later version.
 */
 // This general interpreter interface.
 // Author: Tim Eves
 
-// Build one of direct_machine.cpp or call_machine.cpp to implement this 
+// Build one of direct_machine.cpp or call_machine.cpp to implement this
 // interface.
 
 #pragma once
 #include <cstring>
+#include <limits>
 #include <graphite2/Types.h>
 #include "inc/Main.h"
 
 #if defined(__GNUC__)
 #if defined(__clang__) || (__GNUC__ * 100 + __GNUC_MINOR__ * 10) < 430
 #define     HOT
 #if defined(__x86_64)
 #define     REGPARM(n)      __attribute__((regparm(n)))
@@ -51,25 +52,32 @@ of the License or (at your option) any l
 #define     REGPARM(n)
 #endif
 #endif
 #else
 #define     HOT
 #define     REGPARM(n)
 #endif
 
+#if defined(__MINGW32__)
+// MinGW's <limits> at some point includes winnt.h which #define's a
+// DELETE macro, which conflicts with enum opcode below, so we undefine
+// it here.
+#undef DELETE
+#endif
+
 namespace graphite2 {
 
 // Forward declarations
 class Segment;
 class Slot;
 class SlotMap;
 
 
-namespace vm 
+namespace vm
 {
 
 
 typedef void * instr;
 typedef Slot * slotref;
 
 enum {VARARGS = 0xff, MAX_NAME_LEN=32};
 
@@ -107,22 +115,22 @@ enum opcode {
 
     POP_RET,                        RET_ZERO,           RET_TRUE,
     IATTR_SET,                      IATTR_ADD,          IATTR_SUB,
     PUSH_PROC_STATE,                PUSH_VERSION,
     PUT_SUBS,                       PUT_SUBS2,          PUT_SUBS3,
     PUT_GLYPH,                      PUSH_GLYPH_ATTR,    PUSH_ATT_TO_GLYPH_ATTR,
     BITOR,                          BITAND,             BITNOT,
     BITSET,                         SET_FEAT,
-    MAX_OPCODE,                     
+    MAX_OPCODE,
     // private opcodes for internal use only, comes after all other on disk opcodes
     TEMP_COPY = MAX_OPCODE
 };
 
-struct opcode_t 
+struct opcode_t
 {
     instr           impl[2];
     uint8           param_sz;
     char            name[MAX_NAME_LEN];
 };
 
 
 class Machine
@@ -181,20 +189,19 @@ inline SlotMap& Machine::slotMap() const
 
 inline Machine::status_t Machine::status() const throw()
 {
     return _status;
 }
 
 inline void Machine::check_final_stack(const stack_t * const sp)
 {
+    if (_status != finished) return;
+
     stack_t const * const base  = _stack + STACK_GUARD,
                   * const limit = base + STACK_MAX;
     if      (sp <  base)    _status = stack_underflow;       // This should be impossible now.
     else if (sp >= limit)   _status = stack_overflow;        // So should this.
     else if (sp != base)    _status = stack_not_empty;
 }
 
 } // namespace vm
 } // namespace graphite2
-
-
-
--- a/gfx/graphite2/src/inc/Main.h
+++ b/gfx/graphite2/src/inc/Main.h
@@ -10,18 +10,18 @@
 
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     Lesser General Public License for more details.
 
     You should also have received a copy of the GNU Lesser General Public
     License along with this library in the file named "LICENSE".
-    If not, write to the Free Software Foundation, 51 Franklin Street, 
-    Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 
+    If not, write to the Free Software Foundation, 51 Franklin Street,
+    Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
     internet at http://www.fsf.org/licenses/lgpl.html.
 
 Alternatively, the contents of this file may be used under the terms of the
 Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
 License, as published by the Free Software Foundation, either version 2
 of the License or (at your option) any later version.
 */
 #pragma once
@@ -72,25 +72,71 @@ public:
     category(size_t & t) : _prev(_category) { _category = &t; }
     ~category() { _category = _prev; }
 };
 
 #else
 struct telemetry  {};
 #endif
 
+// Checked multiplaction to catch overflow or underflow when allocating memory
+#if defined(__has_builtin)
+  #if __has_builtin(__builtin_mul_overflow)
+    #define HAVE_BUILTIN_OVERFLOW
+  #endif
+#elif defined(__GNUC__) && (__GNUC__ >= 5) && !defined(__INTEL_COMPILER)
+  #define HAVE_BUILTIN_OVERFLOW
+#endif
+#if defined(__has_include)
+  #if __has_include(<intsafe.h>)
+    #define HAVE_INTSAFE_H
+  #endif
+#elif defined(_WIN32)
+  #define HAVE_INTSAFE_H
+#endif
+
+// Need to import intsafe into the top level namespace
+#if defined(HAVE_INTSAFE_H)
+} // namespace graphite2
+
+#include <intsafe.h>
+
+namespace graphite2 {
+#endif
+
+#if defined(HAVE_BUILTIN_OVERFLOW)
+inline
+bool checked_mul(const size_t a, const size_t b, size_t & t) {
+    return __builtin_mul_overflow(a, b, &t);
+}
+#elif defined(HAVE_INTSAFE_H)
+inline
+bool checked_mul(const size_t a, const size_t b, size_t & t) {
+    return SizeTMult(a, b, &t) == INTSAFE_E_ARITHMETIC_OVERFLOW;
+}
+#else
+inline
+bool checked_mul(const size_t a, const size_t b, size_t & t) {
+  t = a*b;
+  return (((a | b) & (~size_t(0) << (sizeof(size_t) << 2))) && (t / a != b));
+}
+#endif
+
 // typesafe wrapper around malloc for simple types
 // use free(pointer) to deallocate
 
 template <typename T> T * gralloc(size_t n)
 {
+    size_t total;
+    if (checked_mul(n, sizeof(T), total))
+      return 0;
 #ifdef GRAPHITE2_TELEMETRY
-    telemetry::count_bytes(sizeof(T) * n);
+    telemetry::count_bytes(total);
 #endif
-    return static_cast<T*>(malloc(sizeof(T) * n));
+    return static_cast<T*>(malloc(total));
 }
 
 template <typename T> T * grzeroalloc(size_t n)
 {
 #ifdef GRAPHITE2_TELEMETRY
     telemetry::count_bytes(sizeof(T) * n);
 #endif
     return static_cast<T*>(calloc(n, sizeof(T)));
@@ -123,24 +169,26 @@ inline T max(const T a, const T b)
 #if defined(__GNUC__)  || defined(__clang__)
 #define GR_MAYBE_UNUSED __attribute__((unused))
 #else
 #define GR_MAYBE_UNUSED
 #endif
 
 #if defined(__clang__) && __cplusplus >= 201103L
    /* clang's fallthrough annotations are only available starting in C++11. */
-    #define GR_FALLTHROUGH [[clang::fallthrough]]
+    #define GR_FALLTHROUGH [[fallthrough]]
 #elif defined(_MSC_VER)
    /*
     * MSVC's __fallthrough annotations are checked by /analyze (Code Analysis):
     * https://msdn.microsoft.com/en-us/library/ms235402%28VS.80%29.aspx
     */
     #include <sal.h>
     #define GR_FALLTHROUGH __fallthrough
+#elif __GNUC__ >= 7
+    #define GR_FALLTHROUGH __attribute__ ((fallthrough))
 #else
     #define GR_FALLTHROUGH /* fallthrough */
 #endif
 
 #ifdef _MSC_VER
 #pragma warning(disable: 4800)
 #pragma warning(disable: 4355)
 #endif
--- a/gfx/graphite2/src/inc/Segment.h
+++ b/gfx/graphite2/src/inc/Segment.h
@@ -200,17 +200,17 @@ int8 Segment::getSlotBidiClass(Slot *s) 
     res = int8(glyphAttr(s->gid(), m_silf->aBidi()));
     s->setBidiClass(res);
     return res;
 }
 
 inline
 void Segment::finalise(const Font *font, bool reverse)
 {
-    if (!m_first) return;
+    if (!m_first || !m_last) return;
 
     m_advance = positionSlots(font, m_first, m_last, m_silf->dir(), true);
     //associateChars(0, m_numCharinfo);
     if (reverse && currdir() != (m_dir & 1))
         reverseSlots();
     linkClusters(m_first, m_last);
 }
 
--- a/gfx/graphite2/src/inc/Sparse.h
+++ b/gfx/graphite2/src/inc/Sparse.h
@@ -10,18 +10,18 @@
 
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     Lesser General Public License for more details.
 
     You should also have received a copy of the GNU Lesser General Public
     License along with this library in the file named "LICENSE".
-    If not, write to the Free Software Foundation, 51 Franklin Street, 
-    Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 
+    If not, write to the Free Software Foundation, 51 Franklin Street,
+    Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
     internet at http://www.fsf.org/licenses/lgpl.html.
 
 Alternatively, the contents of this file may be used under the terms of the
 Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
 License, as published by the Free Software Foundation, either version 2
 of the License or (at your option) any later version.
 */
 #pragma once
@@ -68,17 +68,17 @@ public:
 
     operator bool () const throw();
     mapped_type     operator [] (const key_type k) const throw();
 
     size_t capacity() const throw();
     size_t size()     const throw();
 
     size_t _sizeof() const throw();
-    
+
     CLASS_NEW_DELETE;
 
 private:
     union {
         chunk         * map;
         mapped_type   * values;
     }           m_array;
     key_type    m_nchunks;
@@ -117,20 +117,17 @@ sparse::sparse(I attr, const I last)
         return;
     }
 
     m_array.values = grzeroalloc<mapped_type>((m_nchunks*sizeof(chunk) + sizeof(mapped_type)-1)
                                                  / sizeof(mapped_type)
                                                  + n_values);
 
     if (m_array.values == 0)
-    {
-        free(m_array.values); m_array.map=0;
         return;
-    }
 
     // coverity[forward_null : FALSE] Since m_array is union and m_array.values is not NULL
     chunk * ci = m_array.map;
     ci->offset = (m_nchunks*sizeof(chunk) + sizeof(mapped_type)-1)/sizeof(mapped_type);
     mapped_type * vi = m_array.values + ci->offset;
     for (; attr != last; ++attr, ++vi)
     {
         const typename std::iterator_traits<I>::value_type v = *attr;
--- a/gfx/graphite2/src/inc/opcode_table.h
+++ b/gfx/graphite2/src/inc/opcode_table.h
@@ -68,17 +68,17 @@ static const opcode_t opcode_table[] =
     {{do2(equal)},                                  0, "EQUAL"},
     {{do2(not_eq_)},                                0, "NOT_EQ"},
     {{do2(less)},                                   0, "LESS"},
     {{do2(gtr)},                                    0, "GTR"},
     {{do2(less_eq)},                                0, "LESS_EQ"},
     {{do2(gtr_eq)},                                 0, "GTR_EQ"},   // 0x18
 
     {{do_(next), NILOP},                            0, "NEXT"},
-    {{do_(next_n), NILOP},                          1, "NEXT_N"},                   // number <= smap.end - map
+    {{NILOP, NILOP},                                1, "NEXT_N"},                   // number <= smap.end - map
     {{do_(next), NILOP},                            0, "COPY_NEXT"},
     {{do_(put_glyph_8bit_obs), NILOP},              1, "PUT_GLYPH_8BIT_OBS"},       // output_class
     {{do_(put_subs_8bit_obs), NILOP},               3, "PUT_SUBS_8BIT_OBS"},        // slot input_class output_class
     {{do_(put_copy), NILOP},                        1, "PUT_COPY"},                 // slot
     {{do_(insert), NILOP},                          0, "INSERT"},
     {{do_(delete_), NILOP},                         0, "DELETE"},   // 0x20
     {{do_(assoc), NILOP},                     VARARGS, "ASSOC"},
     {{NILOP ,do_(cntxt_item)},                      2, "CNTXT_ITEM"},               // slot offset
--- a/gfx/graphite2/src/inc/opcodes.h
+++ b/gfx/graphite2/src/inc/opcodes.h
@@ -21,17 +21,17 @@
 
 Alternatively, the contents of this file may be used under the terms of the
 Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
 License, as published by the Free Software Foundation, either version 2
 of the License or (at your option) any later version.
 */
 #pragma once
 // This file will be pulled into and integrated into a machine implmentation
-// DO NOT build directly and under no circumstances every #include headers in 
+// DO NOT build directly and under no circumstances ever #include headers in
 // here or you will break the direct_machine.
 //
 // Implementers' notes
 // ==================
 // You have access to a few primitives and the full C++ code:
 //    declare_params(n) Tells the interpreter how many bytes of parameter
 //                      space to claim for this instruction uses and 
 //                      initialises the param pointer.  You *must* before the 
@@ -60,17 +60,17 @@ of the License or (at your option) any l
 //        isf       = The first positioned slot
 //        isl       = The last positioned slot
 //        ip        = The current instruction pointer
 //        endPos    = Position of advance of last cluster
 //        dir       = writing system directionality of the font
      
 
 // #define NOT_IMPLEMENTED     assert(false)
-#define NOT_IMPLEMENTED
+// #define NOT_IMPLEMENTED
 
 #define binop(op)           const uint32 a = pop(); *sp = uint32(*sp) op a
 #define sbinop(op)          const int32 a = pop(); *sp = int32(*sp) op a
 #define use_params(n)       dp += n
 
 #define declare_params(n)   const byte * param = dp; \
                             use_params(n);
 
@@ -125,18 +125,20 @@ STARTOP(sub)
     binop(-);
 ENDOP
 
 STARTOP(mul)
     binop(*);
 ENDOP
 
 STARTOP(div_)
-    if (*sp == 0) DIE;
-    sbinop(/);
+    const int32 b = pop();
+    const int32 a = int32(*sp);
+    if (b == 0 || (a == std::numeric_limits<int32>::min() && b == -1)) DIE;
+    *sp = int32(*sp) / b;
 ENDOP
 
 STARTOP(min_)
     const int32 a = pop(), b = *sp;
     if (a < b) *sp = a;
 ENDOP
 
 STARTOP(max_)
@@ -203,22 +205,22 @@ STARTOP(next)
     {
         if (is == smap.highwater())
             smap.highpassed(true);
         is = is->next();
     }
     ++map;
 ENDOP
 
-STARTOP(next_n)
-    use_params(1);
-    NOT_IMPLEMENTED;
+//STARTOP(next_n)
+//    use_params(1);
+//    NOT_IMPLEMENTED;
     //declare_params(1);
     //const size_t num = uint8(*param);
-ENDOP
+//ENDOP
 
 //STARTOP(copy_next)
 //     if (is) is = is->next();
 //     ++map;
 // ENDOP
 
 STARTOP(put_glyph_8bit_obs)
     declare_params(1);
@@ -332,16 +334,17 @@ STARTOP(delete_)
     else
         seg.first(is->next());
     
     if (is->next())
         is->next()->prev(is->prev());
     else
         seg.last(is->prev());
     
+
     if (is == smap.highwater())
             smap.highwater(is->next());
     if (is->prev())
         is = is->prev();
     seg.extendLength(-1);
 ENDOP
 
 STARTOP(assoc)