Bug 1309249: Add filepath to OS.File.read errors for lz4 decompression;r?Yoric draft
authorSumit Tiwari <sumi29@gmail.com>
Sun, 16 Oct 2016 11:30:47 -0400
changeset 427487 2c0a0eb6f90fecd8252ff018918399567c2bf1df
parent 425666 a1768c915756429b74f73fac2e8dd4e7b4919730
child 430567 e417d17a7e974628add4c0a6f97b22b700190c80
child 430568 5da42680d020a8342ac1e42c09f2d581a8be97a2
child 430569 791df192e09a5c87c5516a4f5928b6ffe8f11dcd
push id33027
push userbmo:sumi29@gmail.com
push dateThu, 20 Oct 2016 12:43:42 +0000
reviewersYoric
bugs1309249
milestone52.0a1
Bug 1309249: Add filepath to OS.File.read errors for lz4 decompression;r?Yoric MozReview-Commit-ID: 3zeRnFYot69
toolkit/components/lz4/lz4.js
toolkit/components/osfile/modules/osfile_shared_front.jsm
toolkit/components/osfile/tests/xpcshell/test_compression.js
--- a/toolkit/components/lz4/lz4.js
+++ b/toolkit/components/lz4/lz4.js
@@ -100,24 +100,26 @@ function compressFileContent(array, opti
 
   return new Uint8Array(outputArray.buffer, 0, HEADER_SIZE + compressedSize);
 }
 exports.compressFileContent = compressFileContent;
 
 function decompressFileContent(array, options = {}) {
   let bytes = SharedAll.normalizeBufferArgs(array, options.bytes || null);
   if (bytes < HEADER_SIZE) {
-    throw new LZError("decompress", "becauseLZNoHeader", "Buffer is too short (no header)");
+    throw new LZError("decompress", "becauseLZNoHeader",
+      `Buffer is too short (no header) - Data: ${ options.path || array }`);
   }
 
   // Read headers
   let expectMagicNumber = new DataView(array.buffer, 0, MAGIC_NUMBER.byteLength);
   for (let i = 0; i < MAGIC_NUMBER.byteLength; ++i) {
     if (expectMagicNumber.getUint8(i) != MAGIC_NUMBER[i]) {
-      throw new LZError("decompress", "becauseLZWrongMagicNumber", "Invalid header (no magic number");
+      throw new LZError("decompress", "becauseLZWrongMagicNumber",
+        `Invalid header (no magic number) - Data: ${ options.path || array }`);
     }
   }
 
   let sizeBuf = new DataView(array.buffer, MAGIC_NUMBER.byteLength, BYTES_IN_SIZE_HEADER);
   let expectDecompressedSize =
     sizeBuf.getUint8(0) +
     (sizeBuf.getUint8(1) << 8) +
     (sizeBuf.getUint8(2) << 16) +
@@ -134,17 +136,18 @@ function decompressFileContent(array, op
   let outputBuffer = new Uint8Array(expectDecompressedSize);
   let decompressedBytes = (new SharedAll.Type.size_t.implementation(0));
 
   // Decompress
   let success = Primitives.decompress(inputData, bytes - HEADER_SIZE,
                                       outputBuffer, outputBuffer.byteLength,
                                       decompressedBytes.address());
   if (!success) {
-    throw new LZError("decompress", "becauseLZInvalidContent", "Invalid content:Decompression stopped at " + decompressedBytes.value);
+    throw new LZError("decompress", "becauseLZInvalidContent",
+      `Invalid content: Decompression stopped at ${decompressedBytes.value} - Data: ${ options.path || array }`);
   }
   return new Uint8Array(outputBuffer.buffer, outputBuffer.byteOffset, decompressedBytes.value);
 }
 exports.decompressFileContent = decompressFileContent;
 
 if (typeof Components != "undefined") {
   this.Lz4 = {
     compressFileContent: compressFileContent,
--- a/toolkit/components/osfile/modules/osfile_shared_front.jsm
+++ b/toolkit/components/osfile/modules/osfile_shared_front.jsm
@@ -321,16 +321,18 @@ AbstractFile.read = function read(path, 
   if ("bytes" in options && typeof options.bytes != "number") {
     throw new TypeError("Invalid type for option bytes");
   }
   let file = exports.OS.File.open(path);
   try {
     let buffer = file.read(bytes, options);
     if ("compression" in options) {
       if (options.compression == "lz4") {
+        options = Object.create(options);
+        options.path = path;
         buffer = Lz4.decompressFileContent(buffer, options);
       } else {
         throw OS.File.Error.invalidArgument("Compression");
       }
     }
     if (!("encoding" in options)) {
       return buffer;
     }
--- a/toolkit/components/osfile/tests/xpcshell/test_compression.js
+++ b/toolkit/components/osfile/tests/xpcshell/test_compression.js
@@ -41,14 +41,58 @@ add_task(function test_uncompressed() {
   let exn;
   // Force decompression, reading should fail
   try {
     yield OS.File.read(path, { compression: "lz4" });
   } catch (ex) {
     exn = ex;
   }
   do_check_true(!!exn);
-  do_check_true(exn.message.indexOf("Invalid header") != -1);
+  // Check the exception message (and that it contains the file name)
+  do_check_true(exn.message.indexOf(`Invalid header (no magic number) - Data: ${ path }`) != -1);
+});
+
+add_task(function test_no_header() {
+  let path = OS.Path.join(OS.Constants.Path.tmpDir, "no_header.tmp");
+  let array = new Uint8Array(8).fill(0,0);  // Small array with no header
+
+  do_print("Writing data with no header");
+
+  let bytes = yield OS.File.writeAtomic(path, array); // No compression
+  let exn;
+  // Force decompression, reading should fail
+  try {
+    yield OS.File.read(path, { compression: "lz4" });
+  } catch (ex) {
+    exn = ex;
+  }
+  do_check_true(!!exn);
+  // Check the exception message (and that it contains the file name)
+  do_check_true(exn.message.indexOf(`Buffer is too short (no header) - Data: ${ path }`) != -1);
+});
+
+add_task(function test_invalid_content() {
+  let path = OS.Path.join(OS.Constants.Path.tmpDir, "invalid_content.tmp");
+  let arr1 = new Uint8Array([109, 111, 122, 76, 122, 52, 48, 0]);
+  let arr2 = new Uint8Array(248).fill(1,0);
+
+  let array = new Uint8Array(arr1.length + arr2.length);
+  array.set(arr1);
+  array.set(arr2, arr1.length);
+
+  do_print("Writing invalid data (with a valid header and only ones after that)");
+
+  let bytes = yield OS.File.writeAtomic(path, array); // No compression
+  let exn;
+  // Force decompression, reading should fail
+  try {
+    yield OS.File.read(path, { compression: "lz4" });
+  } catch (ex) {
+    exn = ex;
+  }
+  do_check_true(!!exn);
+  // Check the exception message (and that it contains the file name)
+  do_check_true(exn.message.indexOf(`Invalid content: Decompression stopped at 0 - Data: ${ path }`) != -1);
 });
 
 add_task(function() {
   do_test_finished();
-});
+});
\ No newline at end of file