Bug 1309249: Add filepath to OS.File.read errors for lz4 decompression;r?Yoric
MozReview-Commit-ID: 3zeRnFYot69
--- 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