Skip to content

Commit

Permalink
Made ignoreCRCMismatches property public, so it can be set by an API …
Browse files Browse the repository at this point in the history
…consumer, for purposes such as implementing a user preference to always ignore mismatches for a given file (or all files, etc.) (Issue #82)
  • Loading branch information
abbeycode committed Sep 26, 2019
1 parent 8a11a3c commit b68a02d
Show file tree
Hide file tree
Showing 13 changed files with 65 additions and 78 deletions.
27 changes: 19 additions & 8 deletions Classes/URKArchive.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ DllHppIgnore
typedef NS_ENUM(NSInteger, URKErrorCode) {

/**
* The archive's header is empty
* The last file of the archive has been read
*/
URKErrorCodeEndOfArchive = ERAR_END_ARCHIVE,

Expand All @@ -35,7 +35,7 @@ typedef NS_ENUM(NSInteger, URKErrorCode) {
URKErrorCodeNoMemory = ERAR_NO_MEMORY,

/**
* The header is broken
* The header's CRC doesn't match the decompressed data's CRC
*/
URKErrorCodeBadData = ERAR_BAD_DATA,

Expand Down Expand Up @@ -173,6 +173,17 @@ extern NSString *URKErrorDomain;
*/
@property(nullable, strong) NSProgress *progress;

/**
* When performing operations on a RAR archive, the contents of compressed files are checked
* against the record of what they were when the archive was created. If there's a mismatch,
* either the metadata (header) or archive contents have become corrupted. You can defeat this check by
* setting this property to YES, though there may be security implications to turning the
* warnings off, as it may indicate a maliciously crafted archive intended to exploit a vulnerability.
*
* It's recommended to leave the decision of how to treat archives with mismatched CRCs to the user
*/
@property (assign) BOOL ignoreCRCMismatches;


/**
* **DEPRECATED:** Creates and returns an archive at the given path
Expand Down Expand Up @@ -475,16 +486,16 @@ extern NSString *URKErrorDomain;
- (BOOL)validatePassword;

/**
Extract each file in the archive, checking whether the data matches the CRC checksum
stored at the time it was written
Iterate through the archive, checking for any errors, including CRC mismatches between
the archived file and its header
@return YES if the data is all correct, false if any check failed
@return YES if the data is all correct, false if any check failed (_even if ignoreCRCMismatches is YES_)
*/
- (BOOL)checkDataIntegrity;

/**
Extract each file in the archive, checking whether the data matches the CRC checksum
stored at the time it was written. If any file doesn't match, run the given block
Iterate through the archive, checking for any errors, including CRC mismatches between
the archived file and its header. If any file's CRC doesn't match, run the given block
to allow the API consumer to decide whether to ignore mismatches. NOTE: This may be a
security risk. The block is intended to prompt the user, which is why it's forced onto
the main thread, rather than making a design-time decision
Expand All @@ -502,7 +513,7 @@ extern NSString *URKErrorDomain;
- (BOOL)checkDataIntegrityIgnoringCRCMismatches:(BOOL(^)(void))ignoreCRCMismatches;

/**
Extract a particular file, to determine if its data matches the CRC
Check a particular file, to determine if its data matches the CRC
checksum stored at the time it written
@param filePath The file in the archive to check
Expand Down
1 change: 0 additions & 1 deletion Classes/URKArchive.mm
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ - (instancetype)initWithFile:(NSURL *)fileURL password:(NSString*)password error

@property (assign) NSString *lastArchivePath;
@property (assign) NSString *lastFilepath;
@property (assign) BOOL ignoreCRCMismatches;

@end

Expand Down
27 changes: 26 additions & 1 deletion Tests/CheckDataTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ - (void)testCheckDataIntegrity_ModifiedCRC {
XCTAssertFalse(success, @"Data integrity check passed for archive with a modified CRC");
}

- (void)testCheckDataIntegrity_ModifiedCRC_IgnoringMismatches {
NSURL *testArchiveURL = self.testFileURLs[@"Modified CRC Archive.rar"];
URKArchive *archive = [[URKArchive alloc] initWithURL:testArchiveURL error:nil];
archive.ignoreCRCMismatches = YES;

// Still expect failure, so a consumer can still tell that data is mismatched
BOOL success = [archive checkDataIntegrity];
XCTAssertFalse(success, @"Data integrity check passed for archive with a modified CRC");
}

#pragma mark - checkDataIntegrityOfFile

- (void)testCheckDataIntegrityForFile {
Expand Down Expand Up @@ -91,6 +101,16 @@ - (void)testCheckDataIntegrityForFile_ModifiedCRC {
XCTAssertFalse(success, @"Data integrity check passed for archive with modified CRC");
}

- (void)testCheckDataIntegrityForFile_ModifiedCRC_IgnoringMismatches {
NSURL *testArchiveURL = self.testFileURLs[@"Modified CRC Archive.rar"];
URKArchive *archive = [[URKArchive alloc] initWithURL:testArchiveURL error:nil];
archive.ignoreCRCMismatches = YES;

// Still expect failure, so a consumer can still tell that data is mismatched
BOOL success = [archive checkDataIntegrityOfFile:@"README.md"];
XCTAssertFalse(success, @"Data integrity check passed for archive with modified CRC");
}

- (void)testCheckDataIntegrityIgnoringCRCMismatches {
NSArray *testArchives = @[@"Test Archive.rar",
@"Test Archive (Password).rar",
Expand All @@ -112,7 +132,8 @@ - (void)testCheckDataIntegrityIgnoringCRCMismatches {

XCTAssertTrue(success, @"Data integrity check failed for %@", testArchiveName);
XCTAssertFalse(blockInvoked, @"Block prompting whether to ignore CRC mismatches should not have been called");
}
XCTAssertFalse(archive.ignoreCRCMismatches);
}
}

- (void)testCheckDataIntegrityIgnoringCRCMismatches_InBackground {
Expand All @@ -137,6 +158,7 @@ - (void)testCheckDataIntegrityIgnoringCRCMismatches_InBackground {
[self waitForExpectationsWithTimeout:10 handler:nil];
XCTAssertTrue(blockInvoked, @"Block prompting whether to ignore CRC mismatches should have been called");
XCTAssertEqualObjects(blockThread, [NSThread mainThread]);
XCTAssertTrue(archive.ignoreCRCMismatches);
}

- (void)testCheckDataIntegrityIgnoringCRCMismatches_NotAnArchive {
Expand All @@ -151,6 +173,7 @@ - (void)testCheckDataIntegrityIgnoringCRCMismatches_NotAnArchive {

XCTAssertFalse(success, @"Data integrity check passed for non-archive");
XCTAssertFalse(blockInvoked, @"Block prompting whether to ignore CRC mismatches should not have been called");
XCTAssertFalse(archive.ignoreCRCMismatches);
}

- (void)testCheckDataIntegrityIgnoringCRCMismatches_ModifiedCRC_Ignore {
Expand All @@ -165,6 +188,7 @@ - (void)testCheckDataIntegrityIgnoringCRCMismatches_ModifiedCRC_Ignore {

XCTAssertTrue(success, @"Data integrity check failed for archive with modified CRC, when instructed to ignore");
XCTAssertTrue(blockInvoked, @"Block prompting whether to ignore CRC mismatches should have been called");
XCTAssertTrue(archive.ignoreCRCMismatches);
}

- (void)testCheckDataIntegrityIgnoringCRCMismatches_ModifiedCRC_DontIgnore {
Expand All @@ -179,6 +203,7 @@ - (void)testCheckDataIntegrityIgnoringCRCMismatches_ModifiedCRC_DontIgnore {

XCTAssertFalse(success, @"Data integrity check passed for archive with modified CRC");
XCTAssertTrue(blockInvoked, @"Block prompting whether to ignore CRC mismatches should have been called");
XCTAssertFalse(archive.ignoreCRCMismatches);
}

@end
7 changes: 1 addition & 6 deletions Tests/ExtractBufferedDataTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,7 @@ - (void)testExtractBufferedData_ModifiedCRC_IgnoringMismatches
NSURL *archiveURL = self.testFileURLs[@"Modified CRC Archive.rar"];
NSString *extractedFile = @"README.md";
URKArchive *archive = [[URKArchive alloc] initWithURL:archiveURL error:nil];

BOOL checkIntegritySuccess = [archive checkDataIntegrityIgnoringCRCMismatches:^BOOL{
return YES;
}];

XCTAssertTrue(checkIntegritySuccess, @"Data integrity check failed for archive with modified CRC, when instructed to ignore");
archive.ignoreCRCMismatches = YES;

NSError *error = nil;
NSMutableData *reconstructedFile = [NSMutableData data];
Expand Down
7 changes: 1 addition & 6 deletions Tests/ExtractDataTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,7 @@ - (void)testExtractData_ModifiedCRC
- (void)testExtractData_ModifiedCRC_IgnoringMismatches
{
URKArchive *archive = [[URKArchive alloc] initWithURL:self.testFileURLs[@"Modified CRC Archive.rar"] error:nil];

BOOL checkIntegritySuccess = [archive checkDataIntegrityIgnoringCRCMismatches:^BOOL{
return YES;
}];

XCTAssertTrue(checkIntegritySuccess, @"Data integrity check failed for archive with modified CRC, when instructed to ignore");
archive.ignoreCRCMismatches = YES;

NSError *error = nil;
NSData *data = [archive extractDataFromFile:@"README.md" error:&error];
Expand Down
18 changes: 4 additions & 14 deletions Tests/ExtractFilesTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -265,13 +265,8 @@ - (void)testExtractFiles_ModifiedCRC_IgnoreCRCMismatches
NSFileManager *fm = [NSFileManager defaultManager];

URKArchive *archive = [[URKArchive alloc] initWithURL:self.testFileURLs[@"Modified CRC Archive.rar"] error:nil];

BOOL fileHasIntegrity = [archive checkDataIntegrityIgnoringCRCMismatches:^BOOL{
return YES;
}];

XCTAssertTrue(fileHasIntegrity);

archive.ignoreCRCMismatches = YES;

NSString *extractDirectory = [self randomDirectoryWithPrefix:@"ExtractInvalidArchive"];
NSURL *extractURL = [self.tempDirectory URLByAppendingPathComponent:extractDirectory];

Expand All @@ -295,13 +290,8 @@ - (void)testExtractFiles_ModifiedCRC_DontIgnoreCRCMismatches
NSFileManager *fm = [NSFileManager defaultManager];

URKArchive *archive = [[URKArchive alloc] initWithURL:self.testFileURLs[@"Modified CRC Archive.rar"] error:nil];

BOOL fileHasIntegrity = [archive checkDataIntegrityIgnoringCRCMismatches:^BOOL{
return NO;
}];

XCTAssertFalse(fileHasIntegrity);

archive.ignoreCRCMismatches = YES;

NSString *extractDirectory = [self randomDirectoryWithPrefix:@"ExtractInvalidArchive"];
NSURL *extractURL = [self.tempDirectory URLByAppendingPathComponent:extractDirectory];

Expand Down
7 changes: 1 addition & 6 deletions Tests/IterateFileInfoTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -230,12 +230,7 @@ - (void)testIterateFileInfo_ModifiedCRC
- (void)testIterateFileInfo_ModifiedCRC_IgnoringMismatches
{
URKArchive *archive = [[URKArchive alloc] initWithURL:self.testFileURLs[@"Modified CRC Archive.rar"] error:nil];

BOOL checkIntegritySuccess = [archive checkDataIntegrityIgnoringCRCMismatches:^BOOL{
return YES;
}];

XCTAssertTrue(checkIntegritySuccess, @"Data integrity check failed for archive with modified CRC, when instructed to ignore");
archive.ignoreCRCMismatches = YES;

NSError *error = nil;
__block int calledCount = 0;
Expand Down
9 changes: 2 additions & 7 deletions Tests/ListFileInfoTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -199,13 +199,8 @@ - (void)testListFileInfo_ModifiedCRC
- (void)testListFileInfo_ModifiedCRC_IgnoringMismatches
{
URKArchive *archive = [[URKArchive alloc] initWithURL:self.testFileURLs[@"Modified CRC Archive.rar"] error:nil];

BOOL checkIntegritySuccess = [archive checkDataIntegrityIgnoringCRCMismatches:^BOOL{
return YES;
}];

XCTAssertTrue(checkIntegritySuccess, @"Data integrity check failed for archive with modified CRC, when instructed to ignore");

archive.ignoreCRCMismatches = YES;

NSError *error = nil;
NSArray<URKFileInfo*> *files = [archive listFileInfo:&error];

Expand Down
7 changes: 1 addition & 6 deletions Tests/ListFilenamesTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -196,12 +196,7 @@ - (void)testListFilenames_ModifiedCRC_IgnoringMismatch
{
NSURL *testArchiveURL = self.testFileURLs[@"Modified CRC Archive.rar"];
URKArchive *archive = [[URKArchive alloc] initWithURL:testArchiveURL error:nil];

BOOL checkIntegritySuccess = [archive checkDataIntegrityIgnoringCRCMismatches:^BOOL{
return YES;
}];

XCTAssertTrue(checkIntegritySuccess, @"Data integrity check failed for archive with modified CRC, when instructed to ignore");
archive.ignoreCRCMismatches = YES;

NSError *error = nil;
NSArray *filesInArchive = [archive listFilenames:&error];
Expand Down
9 changes: 2 additions & 7 deletions Tests/ListVolumesTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,8 @@ - (void)testSingleVolume_ModifiedCRC {
- (void)testSingleVolume_ModifiedCRC_IgnoringMismatch {
NSURL *testArchiveURL = self.testFileURLs[@"Modified CRC Archive.rar"];
URKArchive *archive = [[URKArchive alloc] initWithURL:testArchiveURL error:nil];

BOOL checkIntegritySuccess = [archive checkDataIntegrityIgnoringCRCMismatches:^BOOL{
return YES;
}];

XCTAssertTrue(checkIntegritySuccess, @"Data integrity check failed for archive with modified CRC, when instructed to ignore");

archive.ignoreCRCMismatches = YES;

NSError *listVolumesError = nil;
NSArray<NSURL*> *volumeURLs = [archive listVolumeURLs:&listVolumesError];

Expand Down
9 changes: 2 additions & 7 deletions Tests/PerformOnDataTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -100,13 +100,8 @@ - (void)testPerformOnData_ModifiedCRC_IgnoringMismatches
{
NSURL *testArchiveURL = self.testFileURLs[@"Modified CRC Archive.rar"];
URKArchive *archive = [[URKArchive alloc] initWithURL:testArchiveURL error:nil];

BOOL checkIntegritySuccess = [archive checkDataIntegrityIgnoringCRCMismatches:^BOOL{
return YES;
}];

XCTAssertTrue(checkIntegritySuccess, @"Data integrity check failed for archive with modified CRC, when instructed to ignore");

archive.ignoreCRCMismatches = YES;

__block NSUInteger fileIndex = 0;
NSError *error = nil;

Expand Down
9 changes: 2 additions & 7 deletions Tests/PerformOnFilesTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,8 @@ - (void)testPerformOnFiles_ModifiedCRC_MismatchesIgnored
NSURL *testArchiveURL = self.testFileURLs[@"Modified CRC Archive.rar"];
NSString *password = nil;
URKArchive *archive = [[URKArchive alloc] initWithURL:testArchiveURL password:password error:nil];

BOOL checkIntegritySuccess = [archive checkDataIntegrityIgnoringCRCMismatches:^BOOL{
return YES;
}];

XCTAssertTrue(checkIntegritySuccess, @"Data integrity check failed for archive with modified CRC, when instructed to ignore");

archive.ignoreCRCMismatches = YES;

__block NSUInteger fileIndex = 0;
NSError *error = nil;

Expand Down
6 changes: 4 additions & 2 deletions Tests/URKArchiveTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ - (void)testFileURL {
: self.testFileURLs[testArchiveName]);

URKArchive *archive = [[URKArchive alloc] initWithURL:testArchiveURL error:nil];

XCTAssertFalse(archive.ignoreCRCMismatches);

NSURL *resolvedURL = archive.fileURL.URLByResolvingSymlinksInPath;
XCTAssertNotNil(resolvedURL, @"Nil URL returned for valid archive");
XCTAssertTrue([testArchiveURL isEqual:resolvedURL], @"Resolved URL doesn't match original");
Expand All @@ -56,7 +57,8 @@ - (void)testFilename {
: self.testFileURLs[testArchiveName]);

URKArchive *archive = [[URKArchive alloc] initWithURL:testArchiveURL error:nil];

XCTAssertFalse(archive.ignoreCRCMismatches);

NSString *resolvedFilename = archive.filename;
XCTAssertNotNil(resolvedFilename, @"Nil filename returned for valid archive");

Expand Down

0 comments on commit b68a02d

Please sign in to comment.