Bug 1903629 - Run nsIZipReader.test() on the recovery archive before decompressing it. r=backup-reviewers,fchasen

Differential Revision: https://phabricator.services.mozilla.com/D214304
This commit is contained in:
Mike Conley
2024-06-22 00:52:40 +00:00
parent ad5e2c22bd
commit 45c44b8ada
4 changed files with 52 additions and 2 deletions

View File

@@ -1077,13 +1077,27 @@ export class BackupService extends EventTarget {
* decompressed within. * decompressed within.
* @returns {Promise<undefined>} * @returns {Promise<undefined>}
*/ */
async #decompressRecoveryFile(recoveryFilePath, recoveryFolderDestPath) { async decompressRecoveryFile(recoveryFilePath, recoveryFolderDestPath) {
let recoveryFile = await IOUtils.getFile(recoveryFilePath); let recoveryFile = await IOUtils.getFile(recoveryFilePath);
let recoveryArchive = new lazy.ZipReader(recoveryFile); let recoveryArchive = new lazy.ZipReader(recoveryFile);
lazy.logConsole.log( lazy.logConsole.log(
"Decompressing recovery folder to ", "Decompressing recovery folder to ",
recoveryFolderDestPath recoveryFolderDestPath
); );
try {
// null is passed to test if we're meant to CRC test the entire
// ZIP file. If an exception is thrown, this means we failed the CRC
// check. See the nsIZipReader.idl documentation for details.
recoveryArchive.test(null);
} catch (e) {
recoveryArchive.close();
lazy.logConsole.error("Compressed recovery file was corrupt.");
await IOUtils.remove(recoveryFilePath, {
retryReadonly: true,
});
throw new Error("Corrupt archive.");
}
await this.#decompressChildren(recoveryFolderDestPath, "", recoveryArchive); await this.#decompressChildren(recoveryFolderDestPath, "", recoveryArchive);
recoveryArchive.close(); recoveryArchive.close();
} }
@@ -1746,7 +1760,7 @@ export class BackupService extends EventTarget {
BackupService.PROFILE_FOLDER_NAME, BackupService.PROFILE_FOLDER_NAME,
"recovery" "recovery"
); );
await this.#decompressRecoveryFile( await this.decompressRecoveryFile(
RECOVERY_FILE_DEST_PATH, RECOVERY_FILE_DEST_PATH,
RECOVERY_FOLDER_DEST_PATH RECOVERY_FOLDER_DEST_PATH
); );

View File

@@ -396,3 +396,38 @@ add_task(async function test_createArchive_early_binary_stream_close() {
await IOUtils.remove(FAKE_ARCHIVE_PATH); await IOUtils.remove(FAKE_ARCHIVE_PATH);
}); });
/**
* Tests that if the nsIZipReader fails the CRC check, that the ZIP recovery
* file is destroyed and an exception is thrown.
*/
add_task(async function test_createArchive_corrupt_zip() {
let bs = new BackupService();
let corruptZipFile = do_get_file("data/corrupt.zip");
let fakeRecoveryFilePath = await IOUtils.createUniqueDirectory(
PathUtils.tempDir,
"testCreateArchiveCorruptZipSource"
);
const CORRUPT_ZIP_SOURCE = PathUtils.join(
fakeRecoveryFilePath,
"corrupt.zip"
);
await IOUtils.copy(corruptZipFile.path, CORRUPT_ZIP_SOURCE);
let fakeRecoveryPath = await IOUtils.createUniqueDirectory(
PathUtils.tempDir,
"testCreateArchiveCorruptZipDest"
);
await Assert.rejects(
bs.decompressRecoveryFile(CORRUPT_ZIP_SOURCE, fakeRecoveryPath),
/Corrupt/
);
let children = await IOUtils.getChildren(fakeRecoveryPath);
Assert.equal(children.length, 0, "Nothing was decompressed.");
Assert.ok(
!(await IOUtils.exists(CORRUPT_ZIP_SOURCE)),
"Corrupt zip was deleted."
);
});

View File

@@ -23,6 +23,7 @@ support-files = ["data/test_xulstore.json"]
support-files = ["data/test_archive.template.html"] support-files = ["data/test_archive.template.html"]
["test_BackupService_archive.js"] ["test_BackupService_archive.js"]
support-files = ["data/corrupt.zip"]
skip-if = ["apple_silicon && automation"] # bug 1729538 skip-if = ["apple_silicon && automation"] # bug 1729538
["test_BackupService_enable_disable_encryption.js"] ["test_BackupService_enable_disable_encryption.js"]