Skip to content

Commit

Permalink
Tests added, Fixes #101
Browse files Browse the repository at this point in the history
  • Loading branch information
PaulTaykalo committed Jul 12, 2019
1 parent 4776570 commit 8662695
Show file tree
Hide file tree
Showing 5 changed files with 254 additions and 65 deletions.
4 changes: 4 additions & 0 deletions XADMaster.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1418,6 +1418,7 @@
E424FB4721CAE11D00E1C950 /* XADArchiveParserTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E424FB4621CAE11D00E1C950 /* XADArchiveParserTests.m */; };
E424FB4E21CAEC0300E1C950 /* XADZipParserTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E424FB4D21CAEC0300E1C950 /* XADZipParserTests.m */; };
E46E6296225DC2DE00D44E0A /* XADSFXDetectionParserTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E46E6295225DC2DE00D44E0A /* XADSFXDetectionParserTests.m */; };
E4BB35EF22D8CE7B00EE22CB /* XADZipParserStructures.h in Headers */ = {isa = PBXBuildFile; fileRef = E4BB35EE22D8CE7B00EE22CB /* XADZipParserStructures.h */; };
/* End PBXBuildFile section */

/* Begin PBXBuildRule section */
Expand Down Expand Up @@ -2133,6 +2134,7 @@
E424FB4621CAE11D00E1C950 /* XADArchiveParserTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XADArchiveParserTests.m; sourceTree = "<group>"; };
E424FB4D21CAEC0300E1C950 /* XADZipParserTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XADZipParserTests.m; sourceTree = "<group>"; };
E46E6295225DC2DE00D44E0A /* XADSFXDetectionParserTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XADSFXDetectionParserTests.m; sourceTree = "<group>"; };
E4BB35EE22D8CE7B00EE22CB /* XADZipParserStructures.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XADZipParserStructures.h; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -2806,6 +2808,7 @@
children = (
1B06D5A20DDA666C00D9C000 /* XADZipParser.h */,
1B06D5A30DDA666C00D9C000 /* XADZipParser.m */,
E4BB35EE22D8CE7B00EE22CB /* XADZipParserStructures.h */,
1B69134C0F4CA44F00A415E0 /* XADZipSFXParsers.h */,
1B69134D0F4CA44F00A415E0 /* XADZipSFXParsers.m */,
1BC89F110EE0CD71006B47FE /* XADDeflateHandle.h */,
Expand Down Expand Up @@ -3549,6 +3552,7 @@
1B75B8EC134E5BA800510EA5 /* XADDiskDoublerMethod2Handle.h in Headers */,
1B75B8ED134E5BA900510EA5 /* XADDiskDoublerParser.h in Headers */,
1B75B8EE134E5BAB00510EA5 /* XADFastLZSSHandle.h in Headers */,
E4BB35EF22D8CE7B00EE22CB /* XADZipParserStructures.h in Headers */,
1B75B8EF134E5BAC00510EA5 /* XADGzipParser.h in Headers */,
1B75B8F0134E5BAC00510EA5 /* xadIO.h in Headers */,
1B75B8F1134E5BAD00510EA5 /* XADISO9660Parser.h in Headers */,
Expand Down
144 changes: 143 additions & 1 deletion XADMasterTests/XADZipParserTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ - (void)testReadingCentralDirectoryRecord
*(buffer++) = 0x51;
*(buffer++) = 0x50;

XADMemoryHandle *handle = [CSMemoryHandle memoryHandleForReadingBuffer:initial length:fileSize];
XADMemoryHandle *handle = [CSMemoryHandle memoryHandleForReadingBuffer:initial length:(unsigned)fileSize];
XADZipParser * parser = [[XADZipParser alloc] init];
[parser setHandle:handle];

Expand All @@ -275,6 +275,148 @@ - (void)testReadingCentralDirectoryRecord

}

- (void)testReadingCentralDirectoryRecordWithExtraStartDisk
{
off_t fileSize = 200;
uint8_t * initial = malloc(fileSize);
uint8_t * buffer = initial;

uint16_t extId = 1;
uint16_t originalStartDisk = 0xffff;
uint32_t extraDisk = 0x01020304;
uint16_t extSize = sizeof(extraDisk); // should be 4

uint16_t extralength = sizeof(extId) + sizeof(extSize) + sizeof(extraDisk);

memset(buffer, 0, fileSize);

// central id
*(buffer++) = 0x50;
*(buffer++) = 0x4b;
*(buffer++) = 0x01;
*(buffer++) = 0x02;

// version made by 2 bytes
*(buffer++) = 0x02;
*(buffer++) = 0x01;

// version needed to extract 2 bytes
*(buffer++) = 0x04;
*(buffer++) = 0x03;

// general purpose bit flag 2 bytes
*(buffer++) = 0x06;
*(buffer++) = 0x05;

// compression method 2 bytes
*(buffer++) = 0x08;
*(buffer++) = 0x07;

// last mod file time 2 bytes
*(buffer++) = 0x0C;
*(buffer++) = 0x0B;

// last mod file date 2 bytes
*(buffer++) = 0x0A;
*(buffer++) = 0x09;

// crc-32 4 bytes
*(buffer++) = 0x10;
*(buffer++) = 0x0f;
*(buffer++) = 0x0e;
*(buffer++) = 0x0d;

// compressed size 4 bytes
*(buffer++) = 0x14;
*(buffer++) = 0x13;
*(buffer++) = 0x12;
*(buffer++) = 0x11;

// uncompressed size 4 bytes
*(buffer++) = 0x18;
*(buffer++) = 0x17;
*(buffer++) = 0x16;
*(buffer++) = 0x15;

// file name length 2 bytes
*(buffer++) = 0x00;
*(buffer++) = 0x00;

// extra field length 2 bytes
*(buffer++) = (extralength >> 0) & 0xff;
*(buffer++) = (extralength >> 8) & 0xff;

// file comment length 2 bytes
*(buffer++) = 0x00;
*(buffer++) = 0x00;

// disk number start 2 bytes
*(buffer++) = (originalStartDisk >> 0) & 0xff;
*(buffer++) = (originalStartDisk >> 8) & 0xff;

// internal file attributes 2 bytes
*(buffer++) = 0x31;
*(buffer++) = 0x30;

// external file attributes 4 bytes
*(buffer++) = 0x43;
*(buffer++) = 0x42;
*(buffer++) = 0x41;
*(buffer++) = 0x40;

// relative offset of local header 4 bytes
*(buffer++) = 0x53;
*(buffer++) = 0x52;
*(buffer++) = 0x51;
*(buffer++) = 0x50;

// EXTRA INFORMATION

// EXTID
*(buffer++) = 0x01;
*(buffer++) = 0x00;

// EXTSize
*(buffer++) = (extSize >> 0) & 0xff;
*(buffer++) = (extSize >> 8) & 0xff;

// ext disk
*(buffer++) = (extraDisk >> 0) & 0xff;
*(buffer++) = (extraDisk >> 8) & 0xff;
*(buffer++) = (extraDisk >> 16) & 0xff;
*(buffer++) = (extraDisk >> 24) & 0xff;



XADMemoryHandle *handle = [CSMemoryHandle memoryHandleForReadingBuffer:initial length:(unsigned)fileSize];
XADZipParser * parser = [[XADZipParser alloc] init];
[parser setHandle:handle];

XADZipParserCentralDirectoryRecord cdr = [parser readCentralDirectoryRecord];

XCTAssertEqual(cdr.system, 0x01);
XCTAssertEqual(cdr.creatorversion, 0x02);
XCTAssertEqual(cdr.extractversion, 0x0304);
XCTAssertEqual(cdr.flags, 0x0506);
XCTAssertEqual(cdr.compressionmethod, 0x0708);
XCTAssertEqual(cdr.date, 0x090A0B0C);
XCTAssertEqual(cdr.crc, 0x0D0E0F10);
XCTAssertEqual(cdr.compsize, 0x11121314);
XCTAssertEqual(cdr.uncompsize, 0x15161718);
XCTAssertEqual(cdr.namelength, 0x00);
XCTAssertEqual(cdr.commentlength, 0x00);
XCTAssertEqual(cdr.infileattrib, 0x3031);
XCTAssertEqual(cdr.extfileattrib, 0x40414243);
XCTAssertEqual(cdr.locheaderoffset, 0x50515253);

XCTAssertEqual(cdr.extralength, 0x08);

// From extra field
XCTAssertEqual(cdr.startdisk, 0x01020304);

}


#pragma mark - Private

- (XADZipParserTestsSUT)_handleWithExtendedTimeStampModificationTime:(BOOL)modificationTime value:(int32_t)modificationValue
Expand Down
54 changes: 1 addition & 53 deletions XADZipParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,59 +19,7 @@
* MA 02110-1301 USA
*/
#import "XADMacArchiveParser.h"

typedef struct XADZipParserCentralDirectoryRecord
{
//central file header signature 4 bytes (0x02014b50)
uint32_t centralid;

// version made by 2 bytes (crateor 1 byte and system - 1 bye)
int creatorversion;
int system;

// version needed to extract 2 bytes
int extractversion;

// general purpose bit flag 2 bytes
int flags;

// compression method 2 bytes
int compressionmethod;

// last mod file time 2 bytes
// last mod file date 2 bytes
uint32_t date;

// crc-32 4 bytes
uint32_t crc;

// compressed size 4 bytes
off_t compsize;

// uncompressed size 4 bytes
off_t uncompsize;

// file name length 2 bytes
int namelength;

// extra field length 2 bytes
int extralength;

// file comment length 2 bytes
int commentlength;

// disk number start 2 bytes
int startdisk;

// internal file attributes 2 bytes
int infileattrib;

// external file attributes 4 bytes
uint32_t extfileattrib;

// relative offset of local header 4 bytes
off_t locheaderoffset;
} XADZipParserCentralDirectoryRecord;
#import "XADZipParserStructures.h"

@interface XADZipParser:XADMacArchiveParser
{
Expand Down
39 changes: 28 additions & 11 deletions XADZipParser.m
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ -(XADZipParserCentralDirectoryRecord)readCentralDirectoryRecord

// Read central directory extra fields, just to find the Zip64 field.
int length=cdr.extralength;
while(length>9)
while(length>=8)
{
int extid=[fh readUInt16LE];
int size=[fh readUInt16LE];
Expand All @@ -392,17 +392,34 @@ -(XADZipParserCentralDirectoryRecord)readCentralDirectoryRecord

if(extid==1)
{
off_t uncompsize64=[fh readUInt64LE];
off_t compsize64=[fh readUInt64LE];
off_t locheaderoffset64=[fh readUInt64LE];
int startdisk64=[fh readUInt32LE];
if(cdr.uncompsize==0xffffffff) cdr.uncompsize=uncompsize64;
if(cdr.compsize==0xffffffff) cdr.compsize=compsize64;
if(cdr.locheaderoffset==0xffffffff) cdr.locheaderoffset=locheaderoffset64;
if(cdr.startdisk==0xffff) cdr.startdisk=startdisk64;
break;
//
// From https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT
//
// 4.5.3 -Zip64 Extended Information Extra Field (0x0001):
// ... fields MUST only appear if the corresponding Local or Central directory record field is set to 0xFFFF or 0xFFFFFFFF.
//
// This means the ZIP64 fields must only appear if they're set to set to 0xFFFF or 0xFFFFFFFF in the Local/Central records.
// Always reading them might result in a crash and a parse failure, even if the headers are correct.
//
if(cdr.uncompsize==0xffffffff) {
cdr.uncompsize=[fh readUInt64LE];
}
if(cdr.compsize==0xffffffff) {
cdr.compsize=[fh readUInt64LE];
}
if(cdr.locheaderoffset==0xffffffff) {
cdr.locheaderoffset=[fh readUInt64LE];
}
if(cdr.startdisk==0xffff) {
cdr.startdisk=[fh readUInt32LE];
}
//
// We can't break since not always all fields are present so we need to seek to the next extra.
// Investigated here: https://github.com/aonez/Keka/issues/423
//
//break;
//
}

[fh seekToFileOffset:nextextra];
}
if(length) [fh skipBytes:length];
Expand Down
78 changes: 78 additions & 0 deletions XADZipParserStructures.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* XADZipParserStructures.h
*
* Copyright (c) 2017-present, MacPaw Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/

#ifndef XADZipParserStructures_h
#define XADZipParserStructures_h

typedef struct XADZipParserCentralDirectoryRecord
{
//central file header signature 4 bytes (0x02014b50)
uint32_t centralid;

// version made by 2 bytes (crateor 1 byte and system - 1 bye)
int creatorversion;
int system;

// version needed to extract 2 bytes
int extractversion;

// general purpose bit flag 2 bytes
int flags;

// compression method 2 bytes
int compressionmethod;

// last mod file time 2 bytes
// last mod file date 2 bytes
uint32_t date;

// crc-32 4 bytes
uint32_t crc;

// compressed size 4 bytes
off_t compsize;

// uncompressed size 4 bytes
off_t uncompsize;

// file name length 2 bytes
int namelength;

// extra field length 2 bytes
int extralength;

// file comment length 2 bytes
int commentlength;

// disk number start 2 bytes
int startdisk;

// internal file attributes 2 bytes
int infileattrib;

// external file attributes 4 bytes
uint32_t extfileattrib;

// relative offset of local header 4 bytes
off_t locheaderoffset;
} XADZipParserCentralDirectoryRecord;

#endif /* XADZipParserStructures_h */

0 comments on commit 8662695

Please sign in to comment.