diff --git a/modules/woff2/README.mozilla b/modules/woff2/README.mozilla
index 0304010d5..7e4a54669 100644
--- a/modules/woff2/README.mozilla
+++ b/modules/woff2/README.mozilla
@@ -11,11 +11,8 @@ The in-tree copy is updated by running
   sh update.sh
 from within the modules/woff2 directory.
 
-Current version: [commit 63b8fb6d0d797f04e77ee825fd8fcf7ea6205aac].
+Current version: [commit e580ebc30a54becf69a75f6e6d6008536ae0c0b4].
 
 redefine-unique_ptr.patch redefines the class std::unique_ptr to workaround a
 build issue with missing C++11 features.
 See https://bugzilla.mozilla.org/show_bug.cgi?id=1227058
-
-missing-assert-header.patch contains the upstream change from commit
-07cd303dd2959cbf69a6840706c0896e49e42677 adding the missing assert.h header.
diff --git a/modules/woff2/moz.build b/modules/woff2/moz.build
index 5bfd36996..c4d813e9b 100644
--- a/modules/woff2/moz.build
+++ b/modules/woff2/moz.build
@@ -4,10 +4,8 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-EXPORTS += [
-    'src/woff2_dec.h',
-    'src/woff2_out.h',
-]
+#with Files('**'):
+#    BUG_COMPONENT = ('Core', 'Graphics: Text')
 
 UNIFIED_SOURCES += [
     'src/table_tags.cc',
diff --git a/modules/woff2/redefine-unique_ptr.patch b/modules/woff2/redefine-unique_ptr.patch
index 888ed8cc1..dd03b34bd 100644
--- a/modules/woff2/redefine-unique_ptr.patch
+++ b/modules/woff2/redefine-unique_ptr.patch
@@ -19,7 +19,7 @@ diff --git a/modules/woff2/src/woff2_dec.cc b/modules/woff2/src/woff2_dec.cc
 +  #define unique_ptr UniquePtr
 +}
 +
- #include "./decode.h"
+ #include "./brotli/decode.h"
  #include "./buffer.h"
  #include "./port.h"
  #include "./round.h"
diff --git a/modules/woff2/src/buffer.h b/modules/woff2/src/buffer.h
index 588ac0d33..08681a6fc 100644
--- a/modules/woff2/src/buffer.h
+++ b/modules/woff2/src/buffer.h
@@ -65,8 +65,8 @@ inline bool Failure(const char *f, int l, const char *fn) {
 // -----------------------------------------------------------------------------
 class Buffer {
  public:
-  Buffer(const uint8_t *buffer, size_t len)
-      : buffer_(buffer),
+  Buffer(const uint8_t *data, size_t len)
+      : buffer_(data),
         length_(len),
         offset_(0) { }
 
@@ -74,7 +74,7 @@ class Buffer {
     return Read(NULL, n_bytes);
   }
 
-  bool Read(uint8_t *buffer, size_t n_bytes) {
+  bool Read(uint8_t *data, size_t n_bytes) {
     if (n_bytes > 1024 * 1024 * 1024) {
       return FONT_COMPRESSION_FAILURE();
     }
@@ -82,8 +82,8 @@ class Buffer {
         (offset_ > length_ - n_bytes)) {
       return FONT_COMPRESSION_FAILURE();
     }
-    if (buffer) {
-      std::memcpy(buffer, buffer_ + offset_, n_bytes);
+    if (data) {
+      std::memcpy(data, buffer_ + offset_, n_bytes);
     }
     offset_ += n_bytes;
     return true;
diff --git a/modules/woff2/src/convert_woff2ttf_fuzzer.cc b/modules/woff2/src/convert_woff2ttf_fuzzer.cc
new file mode 100644
index 000000000..3fdd15bc2
--- /dev/null
+++ b/modules/woff2/src/convert_woff2ttf_fuzzer.cc
@@ -0,0 +1,13 @@
+#include <stddef.h>
+#include <stdint.h>
+
+#include "woff2_dec.h"
+
+// Entry point for LibFuzzer.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  std::string buf;
+  woff2::WOFF2StringOut out(&buf);
+  out.SetMaxSize(30 * 1024 * 1024);
+  woff2::ConvertWOFF2ToTTF(data, size, &out);
+  return 0;
+}
diff --git a/modules/woff2/src/convert_woff2ttf_fuzzer_new_entry.cc b/modules/woff2/src/convert_woff2ttf_fuzzer_new_entry.cc
new file mode 100644
index 000000000..75114a91b
--- /dev/null
+++ b/modules/woff2/src/convert_woff2ttf_fuzzer_new_entry.cc
@@ -0,0 +1,12 @@
+#include <string>
+#include "woff2_dec.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t data_size) {
+  // Decode using newer entry pattern.
+  // Same pattern as woff2_decompress.
+  std::string output(std::min(woff2::ComputeWOFF2FinalSize(data, data_size),
+                              woff2::kDefaultMaxSize), 0);
+  woff2::WOFF2StringOut out(&output);
+  woff2::ConvertWOFF2ToTTF(data, data_size, &out);
+  return 0;
+}
diff --git a/modules/woff2/src/font.cc b/modules/woff2/src/font.cc
index 060673005..8dc104382 100644
--- a/modules/woff2/src/font.cc
+++ b/modules/woff2/src/font.cc
@@ -105,6 +105,12 @@ bool ReadTrueTypeFont(Buffer* file, const uint8_t* data, size_t len,
     last_offset = i.first + i.second;
   }
 
+  // Sanity check key tables
+  const Font::Table* head_table = font->FindTable(kHeadTableTag);
+  if (head_table != NULL && head_table->length < 52) {
+    return FONT_COMPRESSION_FAILURE();
+  }
+
   return true;
 }
 
@@ -325,8 +331,11 @@ int NumGlyphs(const Font& font) {
     return 0;
   }
   int index_fmt = IndexFormat(font);
-  int num_glyphs = (loca_table->length / (index_fmt == 0 ? 2 : 4)) - 1;
-  return num_glyphs;
+  int loca_record_size = (index_fmt == 0 ? 2 : 4);
+  if (loca_table->length < loca_record_size) {
+    return 0;
+  }
+  return (loca_table->length / loca_record_size) - 1;
 }
 
 int IndexFormat(const Font& font) {
diff --git a/modules/woff2/src/glyph.cc b/modules/woff2/src/glyph.cc
index 1dadafcb7..4c6b60a14 100644
--- a/modules/woff2/src/glyph.cc
+++ b/modules/woff2/src/glyph.cc
@@ -118,25 +118,27 @@ bool ReadGlyph(const uint8_t* data, size_t len, Glyph* glyph) {
 
     // Read the run-length coded flags.
     std::vector<std::vector<uint8_t> > flags(num_contours);
-    uint8_t flag = 0;
-    uint8_t flag_repeat = 0;
-    for (int i = 0; i < num_contours; ++i) {
-      flags[i].resize(glyph->contours[i].size());
-      for (size_t j = 0; j < glyph->contours[i].size(); ++j) {
-        if (flag_repeat == 0) {
-          if (!buffer.ReadU8(&flag)) {
-            return FONT_COMPRESSION_FAILURE();
-          }
-          if (flag & kFLAG_REPEAT) {
-            if (!buffer.ReadU8(&flag_repeat)) {
+    {
+      uint8_t flag = 0;
+      uint8_t flag_repeat = 0;
+      for (int i = 0; i < num_contours; ++i) {
+        flags[i].resize(glyph->contours[i].size());
+        for (size_t j = 0; j < glyph->contours[i].size(); ++j) {
+          if (flag_repeat == 0) {
+            if (!buffer.ReadU8(&flag)) {
               return FONT_COMPRESSION_FAILURE();
             }
+            if (flag & kFLAG_REPEAT) {
+              if (!buffer.ReadU8(&flag_repeat)) {
+                return FONT_COMPRESSION_FAILURE();
+              }
+            }
+          } else {
+            flag_repeat--;
           }
-        } else {
-          flag_repeat--;
+          flags[i][j] = flag;
+          glyph->contours[i][j].on_curve = flag & kFLAG_ONCURVE;
         }
-        flags[i][j] = flag;
-        glyph->contours[i][j].on_curve = flag & kFLAG_ONCURVE;
       }
     }
 
diff --git a/modules/woff2/src/normalize.cc b/modules/woff2/src/normalize.cc
index b538b91a8..1af3b7db6 100644
--- a/modules/woff2/src/normalize.cc
+++ b/modules/woff2/src/normalize.cc
@@ -52,7 +52,7 @@ bool WriteNormalizedLoca(int index_fmt, int num_glyphs, Font* font) {
   loca_table->buffer.resize(Round4(num_glyphs + 1) * glyph_sz);
   loca_table->length = (num_glyphs + 1) * glyph_sz;
 
-  uint8_t* glyf_dst = &glyf_table->buffer[0];
+  uint8_t* glyf_dst = num_glyphs ? &glyf_table->buffer[0] : NULL;
   uint8_t* loca_dst = &loca_table->buffer[0];
   uint32_t glyf_offset = 0;
   size_t loca_offset = 0;
@@ -78,16 +78,13 @@ bool WriteNormalizedLoca(int index_fmt, int num_glyphs, Font* font) {
     }
     glyf_offset += glyf_dst_size;
   }
-  if (glyf_offset == 0) {
-    return false;
-  }
 
   StoreLoca(index_fmt, glyf_offset, &loca_offset, loca_dst);
 
   glyf_table->buffer.resize(glyf_offset);
-  glyf_table->data = &glyf_table->buffer[0];
+  glyf_table->data = glyf_offset ? &glyf_table->buffer[0] : NULL;
   glyf_table->length = glyf_offset;
-  loca_table->data = &loca_table->buffer[0];
+  loca_table->data = loca_offset ? &loca_table->buffer[0] : NULL;
 
   return true;
 }
diff --git a/modules/woff2/src/port.h b/modules/woff2/src/port.h
index bac47a93a..b302d6c49 100644
--- a/modules/woff2/src/port.h
+++ b/modules/woff2/src/port.h
@@ -60,4 +60,15 @@ inline int Log2Floor(uint32 n) {
 #define PREDICT_TRUE(x) (x)
 #endif
 
+#if (defined(__ARM_ARCH) && (__ARM_ARCH == 7)) || \
+    (defined(M_ARM) && (M_ARM == 7)) || \
+    defined(__aarch64__) || defined(__ARM64_ARCH_8__) || defined(__i386) || \
+    defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
+#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+#define WOFF_LITTLE_ENDIAN
+#elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+#define WOFF_BIG_ENDIAN
+#endif  /* endianness */
+#endif  /* CPU whitelist */
+
 #endif  // WOFF2_PORT_H_
diff --git a/modules/woff2/src/store_bytes.h b/modules/woff2/src/store_bytes.h
index e026cd33a..82c1bd84a 100644
--- a/modules/woff2/src/store_bytes.h
+++ b/modules/woff2/src/store_bytes.h
@@ -22,6 +22,8 @@
 #include <stddef.h>
 #include <string.h>
 
+#include "./port.h"
+
 namespace woff2 {
 
 inline size_t StoreU32(uint8_t* dst, size_t offset, uint32_t x) {
@@ -33,12 +35,11 @@ inline size_t StoreU32(uint8_t* dst, size_t offset, uint32_t x) {
 }
 
 inline size_t Store16(uint8_t* dst, size_t offset, int x) {
-#if (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
-  uint16_t v = ((x & 0xFF) << 8) | ((x & 0xFF00) >> 8);
-  memcpy(dst + offset, &v, 2);
-#elif (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
-  uint16_t v = static_cast<uint16_t>(x);
-  memcpy(dst + offset, &v, 2);
+#if defined(WOFF_LITTLE_ENDIAN)
+  *reinterpret_cast<uint16_t*>(dst + offset) =
+      ((x & 0xFF) << 8) | ((x & 0xFF00) >> 8);
+#elif defined(WOFF_BIG_ENDIAN)
+  *reinterpret_cast<uint16_t*>(dst + offset) = static_cast<uint16_t>(x);
 #else
   dst[offset] = x >> 8;
   dst[offset + 1] = x;
@@ -54,14 +55,12 @@ inline void StoreU32(uint32_t val, size_t* offset, uint8_t* dst) {
 }
 
 inline void Store16(int val, size_t* offset, uint8_t* dst) {
-#if (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
-  uint16_t v = ((val & 0xFF) << 8) | ((val & 0xFF00) >> 8);
-  memcpy(dst + *offset, &v, 2);
+#if defined(WOFF_LITTLE_ENDIAN)
+  *reinterpret_cast<uint16_t*>(dst + *offset) =
       ((val & 0xFF) << 8) | ((val & 0xFF00) >> 8);
   *offset += 2;
-#elif (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
-  uint16_t v = static_cast<uint16_t>(val);
-  memcpy(dst + *offset, &v, 2);
+#elif defined(WOFF_BIG_ENDIAN)
+  *reinterpret_cast<uint16_t*>(dst + *offset) = static_cast<uint16_t>(val);
   *offset += 2;
 #else
   dst[(*offset)++] = val >> 8;
diff --git a/modules/woff2/src/variable_length.cc b/modules/woff2/src/variable_length.cc
index 944a17f2e..264eb0a16 100644
--- a/modules/woff2/src/variable_length.cc
+++ b/modules/woff2/src/variable_length.cc
@@ -49,8 +49,8 @@ void Write255UShort(std::vector<uint8_t>* out, int value) {
 void Store255UShort(int val, size_t* offset, uint8_t* dst) {
   std::vector<uint8_t> packed;
   Write255UShort(&packed, val);
-  for (uint8_t val : packed) {
-    dst[(*offset)++] = val;
+  for (uint8_t packed_byte : packed) {
+    dst[(*offset)++] = packed_byte;
   }
 }
 
diff --git a/modules/woff2/src/woff2_common.cc b/modules/woff2/src/woff2_common.cc
index 9dc7cbd5c..c19acdbd9 100644
--- a/modules/woff2/src/woff2_common.cc
+++ b/modules/woff2/src/woff2_common.cc
@@ -18,6 +18,8 @@
 
 #include "./woff2_common.h"
 
+#include "./port.h"
+
 namespace woff2 {
 
 
@@ -25,13 +27,12 @@ uint32_t ComputeULongSum(const uint8_t* buf, size_t size) {
   uint32_t checksum = 0;
   size_t aligned_size = size & ~3;
   for (size_t i = 0; i < aligned_size; i += 4) {
-    uint32_t v;
-    memcpy(&v, buf + i, 4);
-#if (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
+#if defined(WOFF_LITTLE_ENDIAN)
+    uint32_t v = *reinterpret_cast<const uint32_t*>(buf + i);
     checksum += (((v & 0xFF) << 24) | ((v & 0xFF00) << 8) |
       ((v & 0xFF0000) >> 8) | ((v & 0xFF000000) >> 24));
-#elif (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
-    checksum += v;
+#elif defined(WOFF_BIG_ENDIAN)
+    checksum += *reinterpret_cast<const uint32_t*>(buf + i);
 #else
     checksum += (buf[i] << 24) | (buf[i + 1] << 16) |
       (buf[i + 2] << 8) | buf[i + 3];
diff --git a/modules/woff2/src/woff2_dec.cc b/modules/woff2/src/woff2_dec.cc
index 97b869fe6..23ce8e495 100644
--- a/modules/woff2/src/woff2_dec.cc
+++ b/modules/woff2/src/woff2_dec.cc
@@ -36,7 +36,7 @@ namespace std
   #define unique_ptr UniquePtr
 }
 
-#include "./decode.h"
+#include "./brotli/decode.h"
 #include "./buffer.h"
 #include "./port.h"
 #include "./round.h"
@@ -751,9 +751,10 @@ bool ReconstructTransformedHmtx(const uint8_t* transformed_buf,
 bool Woff2Uncompress(uint8_t* dst_buf, size_t dst_size,
   const uint8_t* src_buf, size_t src_size) {
   size_t uncompressed_size = dst_size;
-  int ok = BrotliDecompressBuffer(src_size, src_buf,
-                                  &uncompressed_size, dst_buf);
-  if (PREDICT_FALSE(!ok || uncompressed_size != dst_size)) {
+  BrotliDecoderResult result = BrotliDecoderDecompress(
+      src_size, src_buf, &uncompressed_size, dst_buf);
+  if (PREDICT_FALSE(result != BROTLI_DECODER_RESULT_SUCCESS ||
+                    uncompressed_size != dst_size)) {
     return FONT_COMPRESSION_FAILURE();
   }
   return true;
@@ -1307,6 +1308,9 @@ bool ConvertWOFF2ToTTF(const uint8_t* data, size_t length,
 
   const uint8_t* src_buf = data + hdr.compressed_offset;
   std::vector<uint8_t> uncompressed_buf(hdr.uncompressed_size);
+  if (PREDICT_FALSE(hdr.uncompressed_size < 1)) {
+    return FONT_COMPRESSION_FAILURE();
+  }
   if (PREDICT_FALSE(!Woff2Uncompress(&uncompressed_buf[0],
                                      hdr.uncompressed_size, src_buf,
                                      hdr.compressed_length))) {
diff --git a/modules/woff2/src/woff2_enc.cc b/modules/woff2/src/woff2_enc.cc
index d100ad51b..4e83a674f 100644
--- a/modules/woff2/src/woff2_enc.cc
+++ b/modules/woff2/src/woff2_enc.cc
@@ -23,7 +23,7 @@
 #include <string>
 #include <vector>
 
-#include "./compressor.h"
+#include "./brotli/encode.h"
 #include "./buffer.h"
 #include "./font.h"
 #include "./normalize.h"
@@ -34,7 +34,6 @@
 #include "./variable_length.h"
 #include "./woff2_common.h"
 
-
 namespace woff2 {
 
 namespace {
@@ -47,16 +46,11 @@ using std::vector;
 const size_t kWoff2HeaderSize = 48;
 const size_t kWoff2EntrySize = 20;
 
-
-bool Compress(const uint8_t* data, const size_t len,
-              uint8_t* result, uint32_t* result_len,
-              brotli::BrotliParams::Mode mode, int quality) {
+bool Compress(const uint8_t* data, const size_t len, uint8_t* result,
+              uint32_t* result_len, BrotliEncoderMode mode, int quality) {
   size_t compressed_len = *result_len;
-  brotli::BrotliParams params;
-  params.mode = mode;
-  params.quality = quality;
-  if (brotli::BrotliCompressBuffer(params, len, data, &compressed_len, result)
-      == 0) {
+  if (BrotliEncoderCompress(quality, BROTLI_DEFAULT_WINDOW, mode, len, data,
+                            &compressed_len, result) == 0) {
     return false;
   }
   *result_len = compressed_len;
@@ -67,14 +61,14 @@ bool Woff2Compress(const uint8_t* data, const size_t len,
                    uint8_t* result, uint32_t* result_len,
                    int quality) {
   return Compress(data, len, result, result_len,
-                  brotli::BrotliParams::MODE_FONT, quality);
+                  BROTLI_MODE_FONT, quality);
 }
 
 bool TextCompress(const uint8_t* data, const size_t len,
                   uint8_t* result, uint32_t* result_len,
                   int quality) {
   return Compress(data, len, result, result_len,
-                  brotli::BrotliParams::MODE_TEXT, quality);
+                  BROTLI_MODE_TEXT, quality);
 }
 
 int KnownTableIndex(uint32_t tag) {
@@ -111,7 +105,8 @@ size_t TableEntrySize(const Table& table) {
 
 size_t ComputeWoff2Length(const FontCollection& font_collection,
                           const std::vector<Table>& tables,
-                          std::map<uint32_t, uint16_t> index_by_offset,
+                          std::map<std::pair<uint32_t, uint32_t>, uint16_t>
+                            index_by_tag_offset,
                           size_t compressed_data_length,
                           size_t extended_metadata_length) {
   size_t size = kWoff2HeaderSize;
@@ -134,7 +129,8 @@ size_t ComputeWoff2Length(const FontCollection& font_collection,
         // no collection entry for xform table
         if (table.tag & 0x80808080) continue;
 
-        uint16_t table_index = index_by_offset[table.offset];
+        std::pair<uint32_t, uint32_t> tag_offset(table.tag, table.offset);
+        uint16_t table_index = index_by_tag_offset[tag_offset];
         size += Size255UShort(table_index);  // 255UInt16 index entry
       }
     }
@@ -326,7 +322,7 @@ bool ConvertTTFToWOFF2(const uint8_t *data, size_t length,
   }
 
   std::vector<Table> tables;
-  std::map<uint32_t, uint16_t> index_by_offset;
+  std::map<std::pair<uint32_t, uint32_t>, uint16_t> index_by_tag_offset;
 
   for (const auto& font : font_collection.fonts) {
 
@@ -336,8 +332,9 @@ bool ConvertTTFToWOFF2(const uint8_t *data, size_t length,
         continue;
       }
 
-      if (index_by_offset.find(src_table.offset) == index_by_offset.end()) {
-        index_by_offset[src_table.offset] = tables.size();
+      std::pair<uint32_t, uint32_t> tag_offset(src_table.tag, src_table.offset);
+      if (index_by_tag_offset.find(tag_offset) == index_by_tag_offset.end()) {
+        index_by_tag_offset[tag_offset] = tables.size();
       } else {
         return false;
       }
@@ -362,7 +359,8 @@ bool ConvertTTFToWOFF2(const uint8_t *data, size_t length,
   }
 
   size_t woff2_length = ComputeWoff2Length(font_collection, tables,
-      index_by_offset, total_compressed_length, compressed_metadata_buf_length);
+      index_by_tag_offset, total_compressed_length,
+      compressed_metadata_buf_length);
   if (woff2_length > *result_length) {
 #ifdef FONT_COMPRESSION_BIN
     fprintf(stderr, "Result allocation was too small (%zd vs %zd bytes).\n",
@@ -435,14 +433,15 @@ bool ConvertTTFToWOFF2(const uint8_t *data, size_t length,
           table.IsReused() ? table.reuse_of->offset : table.offset;
         uint32_t table_length =
           table.IsReused() ? table.reuse_of->length : table.length;
-        if (index_by_offset.find(table_offset) == index_by_offset.end()) {
+        std::pair<uint32_t, uint32_t> tag_offset(table.tag, table_offset);
+        if (index_by_tag_offset.find(tag_offset) == index_by_tag_offset.end()) {
 #ifdef FONT_COMPRESSION_BIN
           fprintf(stderr, "Missing table index for offset 0x%08x\n",
                   table_offset);
 #endif
           return FONT_COMPRESSION_FAILURE();
         }
-        uint16_t index = index_by_offset[table_offset];
+        uint16_t index = index_by_tag_offset[tag_offset];
         Store255UShort(index, &offset, result);
 
       }
