Bug 1359240 - When loading an SVG glyph, check if the SVG document is gz-compressed, and decompress before attempting to parse. r=jrmuizel
authorJonathan Kew <jkew@mozilla.com>
Mon, 20 May 2019 21:01:18 +0000
changeset 474602 7fa4002399902562260739f6fbe478939b7a8857
parent 474601 9d1bdc51c250e4e9618390f4f2b891fba1ab39bd
child 474603 3c7314a697e25a55ac35bcc0bf7a888db385d467
push id36042
push userdvarga@mozilla.com
push dateTue, 21 May 2019 04:19:40 +0000
treeherdermozilla-central@ca560ff55451 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1359240
milestone69.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1359240 - When loading an SVG glyph, check if the SVG document is gz-compressed, and decompress before attempting to parse. r=jrmuizel Differential Revision: https://phabricator.services.mozilla.com/D31107
gfx/thebes/gfxSVGGlyphs.cpp
--- a/gfx/thebes/gfxSVGGlyphs.cpp
+++ b/gfx/thebes/gfxSVGGlyphs.cpp
@@ -27,16 +27,17 @@
 #include "nsStringStream.h"
 #include "nsStreamUtils.h"
 #include "nsIPrincipal.h"
 #include "nsSVGUtils.h"
 #include "nsContentUtils.h"
 #include "gfxFont.h"
 #include "gfxContext.h"
 #include "harfbuzz/hb.h"
+#include "zlib.h"
 
 #define SVG_CONTENT_TYPE NS_LITERAL_CSTRING("image/svg+xml")
 #define UTF8_CHARSET NS_LITERAL_CSTRING("utf-8")
 
 using namespace mozilla;
 using mozilla::dom::Document;
 using mozilla::dom::Element;
 
@@ -252,17 +253,54 @@ size_t gfxSVGGlyphs::SizeOfIncludingThis
 Element* gfxSVGGlyphsDocument::GetGlyphElement(uint32_t aGlyphId) {
   return mGlyphIdMap.Get(aGlyphId);
 }
 
 gfxSVGGlyphsDocument::gfxSVGGlyphsDocument(const uint8_t* aBuffer,
                                            uint32_t aBufLen,
                                            gfxSVGGlyphs* aSVGGlyphs)
     : mOwner(aSVGGlyphs) {
-  ParseDocument(aBuffer, aBufLen);
+  if (aBufLen >= 14 && aBuffer[0] == 31 && aBuffer[1] == 139) {
+    // It's a gzip-compressed document; decompress it before parsing.
+    // The original length (modulo 2^32) is found in the last 4 bytes
+    // of the data, stored in little-endian format. We read it as
+    // individual bytes to avoid possible alignment issues.
+    // (Note that if the original length was >2^32, then origLen here
+    // will be incorrect; but then the inflate() call will not return
+    // Z_STREAM_END and we'll bail out safely.)
+    size_t origLen = (size_t(aBuffer[aBufLen - 1]) << 24) +
+                     (size_t(aBuffer[aBufLen - 2]) << 16) +
+                     (size_t(aBuffer[aBufLen - 3]) << 8) +
+                     size_t(aBuffer[aBufLen - 4]);
+    AutoTArray<uint8_t, 4096> outBuf;
+    if (outBuf.SetLength(origLen, mozilla::fallible)) {
+      z_stream s = {0};
+      s.next_in = const_cast<Byte*>(aBuffer);
+      s.avail_in = aBufLen;
+      s.next_out = outBuf.Elements();
+      s.avail_out = outBuf.Length();
+      // The magic number 16 here is the zlib flag to expect gzip format,
+      // see http://www.zlib.net/manual.html#Advanced
+      if (Z_OK == inflateInit2(&s, 16 + MAX_WBITS)) {
+        int result = inflate(&s, Z_FINISH);
+        if (Z_STREAM_END == result) {
+          MOZ_ASSERT(size_t(s.next_out - outBuf.Elements()) == origLen);
+          ParseDocument(outBuf.Elements(), outBuf.Length());
+        } else {
+          NS_WARNING("Failed to decompress SVG glyphs document");
+        }
+        inflateEnd(&s);
+      }
+    } else {
+      NS_WARNING("Failed to allocate memory for SVG glyphs document");
+    }
+  } else {
+    ParseDocument(aBuffer, aBufLen);
+  }
+
   if (!mDocument) {
     NS_WARNING("Could not parse SVG glyphs document");
     return;
   }
 
   Element* root = mDocument->GetRootElement();
   if (!root) {
     NS_WARNING("Could not parse SVG glyphs document");