Merge inbound to mozilla-central. a=merge
authorCosmin Sabou <csabou@mozilla.com>
Sat, 10 Mar 2018 23:49:51 +0200
changeset 407513 e0eacfc97568bc270e61839c60ae787fb76c4f07
parent 407512 7b8e91ebc597e1c68009cb94a2c3891cde591ac4 (current diff)
parent 407506 0bc390d8397f210bf67d5ef89b8b07c5ba4d1107 (diff)
child 407514 53802a58a0a98ece8176e6afbc6d70a1eb39e0ac
child 407518 3b7db5bf4dfbf6aeeb8195ccb65aa5bf6e56009d
push id100702
push usercbrindusan@mozilla.com
push dateSat, 10 Mar 2018 21:54:51 +0000
treeherdermozilla-inbound@53802a58a0a9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone60.0a1
first release with
nightly linux32
e0eacfc97568 / 60.0a1 / 20180310220052 / files
nightly linux64
e0eacfc97568 / 60.0a1 / 20180310220052 / files
nightly mac
e0eacfc97568 / 60.0a1 / 20180310220052 / files
nightly win32
e0eacfc97568 / 60.0a1 / 20180310220052 / files
nightly win64
e0eacfc97568 / 60.0a1 / 20180310220052 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central. a=merge
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -425,16 +425,17 @@ These should match what Safari and other
 
 <!-- LOCALIZATION NOTE (moreMenu.label) This label is used in the new Photon
     app (hamburger) menu. When clicked, it opens a subview that contains
     secondary commands. -->
 <!ENTITY moreMenu.label "More">
 
 <!ENTITY openCmd.commandkey           "l">
 <!ENTITY urlbar.placeholder2          "Search or enter address">
+<!ENTITY urlbar.placeholder3          "Enter search terms and addresses here">
 <!ENTITY urlbar.accesskey             "d">
 <!-- LOCALIZATION NOTE (urlbar.extension.label): Used to indicate that a selected autocomplete entry is provided by an extension. -->
 <!ENTITY urlbar.extension.label       "Extension:">
 <!ENTITY urlbar.switchToTab.label     "Switch to tab:">
 
 <!-- LOCALIZATION NOTE (urlbar.searchSuggestionsNotification.hintPrefix): Shown just before the suggestions opt-out hint. -->
 <!ENTITY urlbar.searchSuggestionsNotification.hintPrefix "Tip:">
 <!-- LOCALIZATION NOTE (urlbar.searchSuggestionsNotification.hint): &#x1F50E; is the magnifier icon emoji, please don't change it. -->
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -428,16 +428,25 @@ reloadButton.tooltip=Reload current page
 # %S is the keyboard shortcut for stopping loading the page
 stopButton.tooltip=Stop loading this page (%S)
 # LOCALIZATION NOTE (urlbar-zoom-button.tooltip):
 # %S is the keyboard shortcut for resetting the zoom level to 100%
 urlbar-zoom-button.tooltip=Reset zoom level (%S)
 # LOCALIZATION NOTE (reader-mode-button.tooltip):
 # %S is the keyboard shortcut for entering/exiting reader view
 reader-mode-button.tooltip=Toggle reader view (%S)
+# LOCALIZATION NOTE (urlbar.placeholder):
+# %S is the name of the user's current search engine
+urlbar.placeholder=Search with %S or enter address
+# LOCALIZATION NOTE (urlbarSearchTip.onboarding):
+# %S is the name of the user's current search engine
+urlbarSearchTip.onboarding=Type less, find more: Search %S right from your address bar.
+# LOCALIZATION NOTE (urlbarSearchTip.engineIsCurrentPage):
+# %S is the name of the user's current search engine
+urlbarSearchTip.engineIsCurrentPage=Start your search here to see suggestions from %S and your browsing history.
 
 # LOCALIZATION NOTE(zoom-button.label): %S is the current page zoom level,
 # %% will be displayed as a single % character (% is commonly used to define
 # format specifiers, so it needs to be escaped).
 zoom-button.label = %S%%
 
 # Block autorefresh
 refreshBlocked.goButton=Allow
--- a/browser/locales/en-US/chrome/browser/search.properties
+++ b/browser/locales/en-US/chrome/browser/search.properties
@@ -43,8 +43,23 @@ searchForSomethingWith=Search for <span 
 # The wording of this string should be as close as possible to
 # searchForSomethingWith. This string will be used when the user
 # has not typed anything.
 searchWithHeader=Search with:
 
 # LOCALIZATION NOTE (searchSettings):
 # This is the label for the button that opens Search preferences.
 searchSettings=Change Search Settings
+
+# LOCALIZATION NOTE (searchReset.intro):
+# %S is the name of the user's current search engine.
+searchReset.intro=Did you want to search using %S?
+# LOCALIZATION NOTE (searchReset.message):
+# %1$S is brandShortName. %2$S is the name of the user's current search engine.
+searchReset.message=It appears that your default search engine has changed. Should %1$S make %2$S the default search engine?
+# LOCALIZATION NOTE (searchReset.doNotResetButton):
+# This string is used as a button label in a notification popup.
+searchReset.doNotResetButton=No Thanks
+# LOCALIZATION NOTE (searchReset.resetButton):
+# %S is the name of the user's current search engine. This string is used as a
+# button label in a notification popup, where space is limited.  If necessary,
+# translate simply as "Yes, Use %S" (e.g., "Yes, use Google")
+searchReset.resetButton=Yes, Use %S to Search
--- 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,7 @@
-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.
+
+Note (2018-03-10):
+Cherry-picked 6e24eb7edbd0872b46441d7397e8b87cccfede73 from upstream to fix memory leak
+as noted in bug https://bugzilla.mozilla.org/show_bug.cgi?id=1443095.
\ No newline at end of file
--- 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)
 {
@@ -130,17 +130,17 @@ bool FeatureMap::readFeats(const Face & 
         const uint32    label   = version < 0x00020000 ? be::read<uint16>(p) : be::read<uint32>(p);
         const uint16    num_settings = be::read<uint16>(p);
         if (version >= 0x00020000)
             be::skip<uint16>(p);
         const uint32    settings_offset = be::read<uint32>(p);
         const uint16    flags  = be::read<uint16>(p),
                         uiName = be::read<uint16>(p);
 
-        if (settings_offset > size_t(feat_end - feat_start) 
+        if (settings_offset > size_t(feat_end - feat_start)
             || settings_offset + num_settings * FEATURE_SETTING_SIZE > size_t(feat_end - feat_start))
         {
             free(defVals);
             return false;
         }
 
         FeatureSetting *uiSet;
         uint32 maxVal;
@@ -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)
@@ -254,40 +254,39 @@ Features* SillMap::cloneFeatures(uint32 
     return new Features (m_FeatureMap.m_defaultFeatures);
 }
 
 
 
 const FeatureRef *FeatureMap::findFeatureRef(uint32 name) const
 {
     NameAndFeatureRef *it;
-    
+
     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() || !m_face)
       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
+      && &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,89 +51,90 @@ private:
 };
 
 class FeatureRef
 {
     typedef uint32      chunk_t;
     static const uint8  SIZEOF_CHUNK = sizeof(chunk_t)*8;
 
 public:
-    FeatureRef();
+    FeatureRef() throw();
     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
-        pDest[m_index] |= m_mask; 
+        pDest[m_index] |= m_mask;
     }
 
     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 { assert(m_face); 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),
+FeatureRef::FeatureRef() throw()
+: m_face(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() { delete[] 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)
--- a/js/src/gc/RelocationOverlay.h
+++ b/js/src/gc/RelocationOverlay.h
@@ -29,29 +29,24 @@ struct Cell;
  * This structure overlays a Cell that has been moved and provides a way to find
  * its new location. It's used during generational and compacting GC.
  */
 class RelocationOverlay
 {
     /* See comment in js/public/HeapAPI.h. */
     static const uint32_t Relocated = js::gc::Relocated;
 
-#if MOZ_LITTLE_ENDIAN
     /*
      * Keep the low 32 bits untouched. Use them to distinguish strings from
      * objects in the nursery.
      */
     uint32_t preserve_;
 
     /* Set to Relocated when moved. */
     uint32_t magic_;
-#else
-    uint32_t magic_;
-    uint32_t preserve_;
-#endif
 
     /* The location |this| was moved to. */
     Cell* newLocation_;
 
     /* A list entry to track all relocated things. */
     RelocationOverlay* next_;
 
   public:
--- a/js/src/jit-test/tests/baseline/bug1416727.js
+++ b/js/src/jit-test/tests/baseline/bug1416727.js
@@ -1,8 +1,9 @@
+// |jit-test| allow-overrecursed
 g = newGlobal()
 g.parent = this
 g.eval("new Debugger(parent).onExceptionUnwind = function(){}");
 var depth = 0;
 function test() {
     if (++depth > 50)
         return;
     function f(n) {
@@ -11,11 +12,9 @@ function test() {
             return;
         }
         try {
             test();
         } finally {}
     }
     f(80);
 }
-try {
-    test();
-} catch(e) {}
+test();
--- a/js/src/jit/shared/LIR-shared.h
+++ b/js/src/jit/shared/LIR-shared.h
@@ -9856,28 +9856,37 @@ class LWasmStackArgI64 : public LInstruc
     MWasmStackArg* mir() const {
         return mirRaw()->toWasmStackArg();
     }
     const LInt64Allocation arg() {
         return getInt64Operand(0);
     }
 };
 
+inline bool
+IsWasmCall(LNode::Opcode op)
+{
+    return (op == LNode::LOp_WasmCall ||
+            op == LNode::LOp_WasmCallVoid ||
+            op == LNode::LOp_WasmCallI64);
+}
+
 template <size_t Defs>
 class LWasmCallBase : public LVariadicInstruction<Defs, 0>
 {
     using Base = LVariadicInstruction<Defs, 0>;
 
     bool needsBoundsCheck_;
 
   public:
     LWasmCallBase(LNode::Opcode opcode, uint32_t numOperands, bool needsBoundsCheck)
       : Base(opcode, numOperands),
         needsBoundsCheck_(needsBoundsCheck)
     {
+        MOZ_ASSERT(IsWasmCall(opcode));
         this->setIsCall();
     }
 
     MWasmCall* mir() const {
         return this->mir_->toWasmCall();
     }
 
     static bool isCallPreserved(AnyRegister reg) {
@@ -9925,24 +9934,19 @@ class LWasmCallI64 : public LWasmCallBas
       : LWasmCallBase(classOpcode, numOperands, needsBoundsCheck)
     {
     }
 };
 
 inline bool
 LNode::isCallPreserved(AnyRegister reg) const
 {
-    switch (op()) {
-      case LOp_WasmCall:
-      case LOp_WasmCallVoid:
-      case LOp_WasmCallI64:
+    if (IsWasmCall(op()))
         return LWasmCallBase<0>::isCallPreserved(reg);
-      default:
-        return false;
-    }
+    return false;
 }
 
 class LAssertRangeI : public LInstructionHelper<0, 1, 0>
 {
   public:
     LIR_HEADER(AssertRangeI)
 
     explicit LAssertRangeI(const LAllocation& input)
--- a/testing/geckodriver/CONTRIBUTING.md
+++ b/testing/geckodriver/CONTRIBUTING.md
@@ -17,19 +17,19 @@ parts it can be useful to know about:
   * [_webdriver_] is a Rust crate providing interfaces, traits
     and types, errors, type- and bounds checks, and JSON marshaling
     for correctly parsing and emitting the [WebDriver protocol].
 
 By participating in this project, you agree to abide by the Mozilla
 [Community Participation Guidelines].  Here are some guidelines
 for contributing high-quality and actionable bugs and code.
 
-[_geckodriver_]: ./README.md
-[_Marionette_]: ../marionette/README.md
-[_webdriver_]: ../webdriver/README.md
+[_geckodriver_]: https://firefox-source-docs.mozilla.org/testing/geckodriver/geckodriver/
+[_Marionette_]: https://firefox-source-docs.mozilla.org/testing/marionette/marionette/
+[_webdriver_]: https://crates.io/crates/webdriver
 [WebDriver protocol]: https://w3c.github.io/webdriver/webdriver-spec.html#protocol
 [XPCOM]: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Guide
 [Community Participation Guidelines]: https://www.mozilla.org/en-US/about/governance/policies/participation/
 
 
 Reporting bugs
 ==============
 
@@ -55,32 +55,30 @@ relating to a specific client should be 
 We welcome you to file issues in the [GitHub issue tracker] once you are
 confident it has not already been reported.  The [ISSUE_TEMPLATE.md]
 contains a helpful checklist for things we will want to know about
 the affected system, reproduction steps, and logs.
 
 geckodriver development follows a rolling release model as we don’t
 release patches for older versions.  It is therefore useful to use
 the tip-of-tree geckodriver binary, or failing this, the latest
-release when verifying the problem.  Similarly, as noted in the
-[README], geckodriver is only compatible with the current release
-channel versions of Firefox, and it consequently does not help
-to report bugs that affect outdated and unsupported Firefoxen.
-Please always try to verify the issue in the latest Firefox Nightly
-before you file your bug.
+release when verifying the problem.  geckodriver is only compatible
+with the current release channel versions of Firefox, and it
+consequently does not help to report bugs that affect outdated and
+unsupported Firefoxen.  Please always try to verify the issue in
+the latest Firefox Nightly before you file your bug.
 
 Once we are satisfied the issue raised is of sufficiently actionable
 character, we will continue with triaging it and file a bug where it
 is appropriate.  Bugs specific to geckodriver will be filed in the
 [`Testing :: geckodriver`] component in Bugzilla.
 
 [mailing list]: #communication
-[trace-level log]: doc/TraceLogs.md
+[trace-level log]: https://firefox-source-docs.mozilla.org/testing/geckodriver/geckodriver/TraceLogs.html
 [GitHub issue tracker]: https://github.com/mozilla/geckodriver/issues
-[README]: ./README.md
 [`Testing :: geckodriver`]: https://bugzilla.mozilla.org/buglist.cgi?component=geckodriver
 
 
 Writing code
 ============
 
 Because there are many moving parts involved remote controlling
 a web browser, it can be challenging to a new contributor to know
@@ -128,22 +126,22 @@ When you have, you are ready to start of
 
 To run the executable from the objdir:
 
 	% ./mach geckodriver -- --version
 	 0:00.27 /home/ato/src/gecko/obj-x86_64-pc-linux-gnu/dist/bin/geckodriver --version --binary /home/ato/src/gecko/obj-x86_64-pc-linux-gnu/dist/bin/firefox
 	geckodriver 0.19.0 (f3e939a81ee1169f9501ad96eb43bbf4bf4a1bde 2017-10-11)
 
 [Rust]: https://www.rust-lang.org/
-[webdriver crate]: ../webdriver/README.md
+[webdriver crate]: https://crates.io/crates/webdriver
 [commands]: https://docs.rs/webdriver/newest/webdriver/command/index.html
 [responses]: https://docs.rs/webdriver/newest/webdriver/response/index.html
 [errors]: https://docs.rs/webdriver/newest/webdriver/error/enum.ErrorStatus.html
 [Marionette protocol]: https://developer.mozilla.org/en-US/docs/Mozilla/QA/Marionette/Protocol
-[Marionette]: ../marionette/README.md
+[Marionette]: https://firefox-source-docs.mozilla.org/testing/marionette/marionette/index.html
 [Firefox CI]: https://treeherder.mozilla.org/
 [mozconfig]: https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Build_Instructions/Configuring_Build_Options
 
 
 Running the tests
 -----------------
 
 We verify and test geckodriver in a couple of different ways.
--- a/toolkit/themes/shared/extensions/extensions.inc.css
+++ b/toolkit/themes/shared/extensions/extensions.inc.css
@@ -110,17 +110,17 @@
 }
 
 .alert {
   -moz-box-align: center;
   padding: 10px;
   color: var(--in-content-text-color);
   border: 1px solid var(--in-content-box-border-color);
   border-radius: 2px;
-  background-color: #ebebeb;
+  background-color: var(--in-content-box-background-hover);
   text-align: center;
 }
 
 .alert .alert-title {
   font-weight: bold;
   font-size: 200%;
   margin-bottom: 15px;
 }
@@ -258,17 +258,17 @@ button.warning {
   padding-right: 10px;
   padding-left: 10px;
 }
 
 #header-utils-btn:not([disabled="true"]):active:hover,
 #header-utils-btn[open="true"] {
   padding-bottom: 0px;
   padding-top: 0px;
-  background-color: #dadada;
+  background-color: var(--in-content-box-background-active);
 }
 
 .header-button {
   -moz-appearance: none;
   border: 1px solid;
   border-radius: 2px;
 }
 
@@ -305,17 +305,17 @@ button.warning {
 
 .sorter .button-box {
   padding-top: 0;
   padding-bottom: 0;
 }
 
 .sorter[checkState="1"],
 .sorter[checkState="2"] {
-  background-color: #ebebeb;
+  background-color: var(--in-content-box-background-hover);
   box-shadow: 0 -4px 0 0 var(--in-content-border-highlight) inset;
 }
 
 .sorter .button-icon {
   margin-inline-start: 6px;
 }
 
 
@@ -366,17 +366,17 @@ button.warning {
   border: 1px dotted transparent;
 }
 
 .list:-moz-focusring > scrollbox > .scrollbox-innerbox {
   border-color: var(--in-content-border-focus);
 }
 
 .addon {
-  color: #444;
+  color: var(--in-content-text-color);
   border-bottom: 1px solid var(--in-content-box-border-color);
   padding: 5px;
   background-origin: border-box;
 }
 
 .addon:not(:only-child):last-child {
   border-bottom-width: 0;
 }
@@ -731,35 +731,35 @@ button.warning {
 }
 
 #detail-fulldesc {
   margin-top: 1em;
 }
 
 #detail-contributions {
   border-radius: 2px;
-  border: 1px solid #D2DBE8;
+  border: 1px solid var(--in-content-box-border-color);
   margin-bottom: 2em;
   padding: 1em;
-  background-color: #F3F7FB;
+  background-color: var(--in-content-box-background);
 }
 
 #detail-contrib-description {
   font-style: italic;
   margin-bottom: 1em;
-  color: #373D48;
+  color: var(--in-content-text-color);
 }
 
 #detail-contrib-suggested {
   color: grey;
   font-weight: bold;
 }
 
 #detail-contrib-btn {
-  color: #FFF;
+  color: var(--in-content-selected-text);
   text-shadow: none;
   border: 1px solid transparent;
   list-style-image: url("chrome://mozapps/skin/extensions/heart.png");
   background-color: var(--in-content-primary-button-background);
 }
 
 #detail-contrib-btn .button-icon {
   margin-inline-end: 5px;
@@ -967,51 +967,51 @@ button.warning {
   display: block !important;
 }
 
 button.button-link {
   -moz-appearance: none;
   background: transparent;
   border: none;
   box-shadow: none;
-  color: #0095dd;
+  color: var(--in-content-link-color);
   cursor: pointer;
   min-width: 0;
   min-height: 20px;
   margin: 0 6px;
 }
 
 button.button-link:hover {
   background-color: transparent;
-  color: #178ce5;
+  color: var(--in-content-link-color-hover);
   text-decoration: underline;
 }
 
 /* Needed to override normal button style from inContent.css */
 button.button-link:not([disabled="true"]):active:hover {
   background-color: transparent;
   color: #0A84FF;
   text-decoration: none;
 }
 
 .addon-control.replacement {
-  background-color: #0a84ff;
-  border-color: #0a84ff;
-  color: #fff;
+  background-color: var(--in-content-primary-button-background);
+  border-color: var(--in-content-primary-button-background);
+  color: var(--in-content-selected-text);
 }
 
 .addon-control.replacement:active,
 .addon-control.replacement:hover {
-  background-color: #0060df;
-  border-color: #0060df;
+  background-color: var(--in-content-primary-button-hover);
+  border-color: var(--in-content-primary-button-hover);
 }
 
 .addon-control.replacement:active:hover {
-  background-color: #003eaa;
-  border-color: #003eaa;
+  background-color: var(--in-content-primary-button-active);
+  border-color: var(--in-content-primary-button-active);
 }
 
 /*** telemetry experiments ***/
 
 #detail-experiment-container {
   font-size: 80%;
   margin-bottom: 1em;
 }