Page MenuHomeWildfire Games

D1511.id10165.diff
No OneTemporary

Size
5 KB
Referenced Files
None
Subscribers
None

D1511.id10165.diff

Index: source/lib/file/archive/archive_zip.cpp
===================================================================
--- source/lib/file/archive/archive_zip.cpp
+++ source/lib/file/archive/archive_zip.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2017 Wildfire Games.
+/* Copyright (C) 2019 Wildfire Games.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@@ -269,6 +269,11 @@
cd_size = (size_t)read_le32(&m_cd_size);
}
+ off_t getCommentLength() const
+ {
+ return static_cast<off_t>(read_le16(&m_comment_len));
+ }
+
private:
u32 m_magic;
u16 m_diskNum;
@@ -521,8 +526,41 @@
io::Operation op(*file.get(), buf, scanSize, ofs);
RETURN_STATUS_IF_ERR(io::Run(op));
+ // Scanning for ECDR first assumes no comment exists
+ // (standard case), so ECDR structure exists right at
+ // end of file
+ off_t offsetInBlock = scanSize - sizeof(ECDR);
+ const ECDR* ecdr = nullptr;
+
+ for (off_t commentSize = 0; (commentSize <= offsetInBlock) && !ecdr; ++commentSize)
+ {
+ const u8 *pECDRTest = buf + offsetInBlock - commentSize;
+ if(*(const u32*)pECDRTest == ecdr_magic)
+ {
+ // Signature matches, test whether comment
+ // fills up the whole space following the
+ // ECDR
+ ecdr = (const ECDR*)pECDRTest;
+ if (commentSize != ecdr->getCommentLength())
+ {
+ // Signature matches but there is some other data between
+ // header, comment and EOF. There are three possibilities
+ // for this:
+ // 1) Header file format and size differ from what we expect
+ // 2) File has been truncated
+ // 3) The magic id occurs inside a zip comment
+ ecdr = nullptr;
+ }
+ else
+ {
+ // Seems like a valid archive header before an archive-level
+ // comment
+ break;
+ }
+ }
+ }
+
// look for ECDR in buffer
- const ECDR* ecdr = (const ECDR*)FindRecord(buf, scanSize, buf, ecdr_magic, sizeof(ECDR));
if(!ecdr)
return INFO::CANNOT_HANDLE;
@@ -535,16 +573,10 @@
const size_t maxScanSize = 66000u; // see below
UniqueRange buf(io::Allocate(maxScanSize));
- // expected case: ECDR at EOF; no file comment
- Status ret = ScanForEcdr(file, fileSize, (u8*)buf.get(), sizeof(ECDR), cd_numEntries, cd_ofs, cd_size);
- if(ret == INFO::OK)
- return INFO::OK;
- // worst case: ECDR precedes 64 KiB of file comment
- ret = ScanForEcdr(file, fileSize, (u8*)buf.get(), maxScanSize, cd_numEntries, cd_ofs, cd_size);
+ Status ret = ScanForEcdr(file, fileSize, static_cast<u8*>(buf.get()), maxScanSize, cd_numEntries, cd_ofs, cd_size);
if(ret == INFO::OK)
return INFO::OK;
- // both ECDR scans failed - this is not a valid Zip file.
io::Operation op(*file.get(), buf.get(), sizeof(LFH));
RETURN_STATUS_IF_ERR(io::Run(op));
// the Zip file has an LFH but lacks an ECDR. this can happen if
Index: source/lib/file/archive/tests/test_archive_zip.h
===================================================================
--- source/lib/file/archive/tests/test_archive_zip.h
+++ source/lib/file/archive/tests/test_archive_zip.h
@@ -0,0 +1,60 @@
+/* Copyright (C) 2019 Wildfire Games.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <iostream>
+
+#include "lib/self_test.h"
+#include "lib/file/archive/archive_zip.h"
+
+class TestArchiveZip : public CxxTest::TestSuite
+{
+public:
+ void test_scan_suspiciousZipFile()
+ {
+ resultbuffer = "";
+ PIArchiveReader testee =
+ CreateArchiveReader_Zip(
+ DataDir() / "mods" / "_test.lib" / "test.zip");
+
+ TS_ASSERT(nullptr != testee);
+
+ testee->ReadEntries(TestArchiveZip::ArchiveEntryCallback, 0);
+
+ TS_ASSERT_EQUALS("buildzipwithcomment.sh", resultbuffer);
+ }
+
+private:
+ static std::string resultbuffer;
+
+ static void ArchiveEntryCallback(
+ const VfsPath &path,
+ const CFileInfo &UNUSED(fileInfo),
+ PIArchiveFile UNUSED(archiveFile),
+ uintptr_t UNUSED(cbData))
+ {
+ resultbuffer = path.string8();
+ }
+};
+
+// Implementation of the static buffer used to communicate with ArchiveEntryCallback
+std::string TestArchiveZip::resultbuffer;
+

File Metadata

Mime Type
text/plain
Expires
Tue, Sep 24, 12:38 AM (18 h, 18 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3375159
Default Alt Text
D1511.id10165.diff (5 KB)

Event Timeline