Bug 1294736 - [3.2] Detect and decode XZ streams when extracting files. r=glandium,snorp
authorEugen Sawin <esawin@mozilla.com>
Tue, 23 Aug 2016 16:01:14 +0200
changeset 318538 630fc916b83f6ba243d7f6cef688971e8fff103a
parent 318537 d0155687dae8b38cf72488e163e50b198924a94a
child 318539 ae62367e77a92d321ca62a7dccab092feab74a1b
push id20725
push userphilringnalda@gmail.com
push dateThu, 20 Oct 2016 01:36:01 +0000
treeherderfx-team@998ad5a74da8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersglandium, snorp
bugs1294736
milestone52.0a1
Bug 1294736 - [3.2] Detect and decode XZ streams when extracting files. r=glandium,snorp
mozglue/linker/Mappable.cpp
--- a/mozglue/linker/Mappable.cpp
+++ b/mozglue/linker/Mappable.cpp
@@ -16,16 +16,17 @@
 
 #ifdef ANDROID
 #include <linux/ashmem.h>
 #endif
 #include <sys/stat.h>
 #include <errno.h>
 #include "ElfLoader.h"
 #include "SeekableZStream.h"
+#include "XZStream.h"
 #include "Logging.h"
 
 using mozilla::MakeUnique;
 using mozilla::UniquePtr;
 
 class CacheValidator
 {
 public:
@@ -188,16 +189,42 @@ MappableExtractFile::Create(const char *
       ERROR("inflateEnd failed: %s", zStream.msg);
       return nullptr;
     }
     if (zStream.total_out != stream->GetUncompressedSize()) {
       ERROR("File not fully uncompressed! %ld / %d", zStream.total_out,
           static_cast<unsigned int>(stream->GetUncompressedSize()));
       return nullptr;
     }
+  } else if (XZStream::IsXZ(stream->GetBuffer(), stream->GetSize())) {
+    XZStream xzStream(stream->GetBuffer(), stream->GetSize());
+
+    if (!xzStream.Init()) {
+      ERROR("Couldn't initialize XZ decoder");
+      return nullptr;
+    }
+    DEBUG_LOG("XZStream created, compressed=%u, uncompressed=%u",
+              xzStream.Size(), xzStream.UncompressedSize());
+
+    if (ftruncate(fd, xzStream.UncompressedSize()) == -1) {
+      ERROR("Couldn't ftruncate %s to decompress library", file.get());
+      return nullptr;
+    }
+    MappedPtr buffer(MemoryRange::mmap(nullptr, xzStream.UncompressedSize(),
+                                       PROT_WRITE, MAP_SHARED, fd, 0));
+    if (buffer == MAP_FAILED) {
+      ERROR("Couldn't map %s to decompress library", file.get());
+      return nullptr;
+    }
+    const size_t written = xzStream.Decode(buffer, buffer.GetLength());
+    DEBUG_LOG("XZStream decoded %u", written);
+    if (written != buffer.GetLength()) {
+      ERROR("Error decoding XZ file %s", file.get());
+      return nullptr;
+    }
   } else if (stream->GetType() == Zip::Stream::STORE) {
     SeekableZStream zStream;
     if (!zStream.Init(stream->GetBuffer(), stream->GetSize())) {
       ERROR("Couldn't initialize SeekableZStream for %s", name);
       return nullptr;
     }
     if (ftruncate(fd, zStream.GetUncompressedSize()) == -1) {
       ERROR("Couldn't ftruncate %s to decompress library", file.get());