Bug 684347: nsZipWriter::addEntryChannel(queue=true) creates corrupt zip file. r=mossop

This commit is contained in:
Kris Maglione 2011-10-25 17:30:59 -07:00
parent 41186fd050
commit dc516e92fb
3 changed files with 57 additions and 38 deletions

View File

@ -912,7 +912,7 @@ inline nsresult nsZipWriter::BeginProcessingAddition(nsZipQueueItem* aItem,
PRUint32 zipAttributes = ZIP_ATTRS(aItem->mPermissions, ZIP_ATTRS_FILE);
if (aItem->mStream) {
if (aItem->mStream || aItem->mChannel) {
nsRefPtr<nsZipHeader> header = new nsZipHeader();
NS_ENSURE_TRUE(header, NS_ERROR_OUT_OF_MEMORY);
@ -922,33 +922,23 @@ inline nsresult nsZipWriter::BeginProcessingAddition(nsZipQueueItem* aItem,
NS_ENSURE_SUCCESS(rv, rv);
nsRefPtr<nsZipDataStream> stream = new nsZipDataStream();
NS_ENSURE_TRUE(stream, NS_ERROR_OUT_OF_MEMORY);
rv = stream->Init(this, mStream, header, aItem->mCompression);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIInputStreamPump> pump;
rv = NS_NewInputStreamPump(getter_AddRefs(pump), aItem->mStream, -1,
-1, 0, 0, true);
NS_ENSURE_SUCCESS(rv, rv);
if (aItem->mStream) {
nsCOMPtr<nsIInputStreamPump> pump;
rv = NS_NewInputStreamPump(getter_AddRefs(pump), aItem->mStream,
-1, -1, 0, 0, true);
NS_ENSURE_SUCCESS(rv, rv);
rv = pump->AsyncRead(stream, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
if (aItem->mChannel) {
nsRefPtr<nsZipHeader> header = new nsZipHeader();
NS_ENSURE_TRUE(header, NS_ERROR_OUT_OF_MEMORY);
header->Init(aItem->mZipEntry, aItem->mModTime, zipAttributes,
mCDSOffset);
nsRefPtr<nsZipDataStream> stream = new nsZipDataStream();
NS_ENSURE_TRUE(stream, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = stream->Init(this, mStream, header, aItem->mCompression);
NS_ENSURE_SUCCESS(rv, rv);
rv = aItem->mChannel->AsyncOpen(stream, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
rv = pump->AsyncRead(stream, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
rv = aItem->mChannel->AsyncOpen(stream, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}

View File

@ -63,6 +63,9 @@ const PR_MSEC_PER_SEC = 1000;
const DATA_DIR = "data/";
var ioSvc = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService);
var ZipWriter = Components.Constructor("@mozilla.org/zipwriter;1",
"nsIZipWriter");
var ZipReader = Components.Constructor("@mozilla.org/libjar/zip-reader;1",

View File

@ -20,6 +20,7 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Kris Maglione <maglione.k@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -70,17 +71,20 @@ var observer = {
var zipR = new ZipReader(tmpFile);
for (var i = 0; i < TESTS.length; i++) {
do_check_true(zipR.hasEntry(TESTS[i].name));
var source = do_get_file(DATA_DIR + TESTS[i].name);
var entry = zipR.getEntry(TESTS[i].name);
do_check_eq(entry.realSize, TESTS[i].size);
do_check_eq(entry.size, TESTS[i].size);
do_check_eq(entry.CRC32, TESTS[i].crc);
do_check_eq(Math.floor(entry.lastModifiedTime / PR_USEC_PER_SEC),
Math.floor(source.lastModifiedTime / PR_MSEC_PER_SEC));
for (let method in methods) {
var entryName = method + "/" + TESTS[i].name;
do_check_true(zipR.hasEntry(entryName));
zipR.test(TESTS[i].name);
var entry = zipR.getEntry(entryName);
do_check_eq(entry.realSize, TESTS[i].size);
do_check_eq(entry.size, TESTS[i].size);
do_check_eq(entry.CRC32, TESTS[i].crc);
do_check_eq(Math.floor(entry.lastModifiedTime / PR_USEC_PER_SEC),
Math.floor(source.lastModifiedTime / PR_MSEC_PER_SEC));
zipR.test(entryName);
}
}
zipR.close();
@ -88,17 +92,39 @@ var observer = {
}
};
var methods = {
file: function method_file(entry, source)
{
zipW.addEntryFile(entry, Ci.nsIZipWriter.COMPRESSION_NONE, source,
true);
},
channel: function method_channel(entry, source)
{
zipW.addEntryChannel(entry, source.lastModifiedTime * PR_MSEC_PER_SEC,
Ci.nsIZipWriter.COMPRESSION_NONE,
ioSvc.newChannelFromURI(ioSvc.newFileURI(source)), true);
},
stream: function method_stream(entry, source)
{
zipW.addEntryStream(entry, source.lastModifiedTime * PR_MSEC_PER_SEC,
Ci.nsIZipWriter.COMPRESSION_NONE,
ioSvc.newChannelFromURI(ioSvc.newFileURI(source)).open(), true);
}
}
function run_test()
{
zipW.open(tmpFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
for (var i = 0; i < TESTS.length; i++) {
var source = do_get_file(DATA_DIR+TESTS[i].name);
zipW.addEntryFile(TESTS[i].name, Ci.nsIZipWriter.COMPRESSION_NONE, source,
true);
size += ZIP_FILE_HEADER_SIZE + ZIP_CDS_HEADER_SIZE +
(ZIP_EXTENDED_TIMESTAMP_SIZE * 2) +
(TESTS[i].name.length*2) + TESTS[i].size;
for (let method in methods) {
var entry = method + "/" + TESTS[i].name;
methods[method](entry, source);
size += ZIP_FILE_HEADER_SIZE + ZIP_CDS_HEADER_SIZE +
(ZIP_EXTENDED_TIMESTAMP_SIZE * 2) +
(entry.length*2) + TESTS[i].size;
}
}
do_test_pending();
zipW.processQueue(observer, null);