diff --git a/.jazzy.yaml b/.jazzy.yaml index 0b6549cb..6fa59613 100644 --- a/.jazzy.yaml +++ b/.jazzy.yaml @@ -3,11 +3,11 @@ sourcekitten_sourcefile: docs.json clean: true author: Timofey Solomko module: SWCompression -module_version: 4.5.6 +module_version: 4.5.7 copyright: '© 2020 Timofey Solomko' readme: README.md github_url: https://github.com/tsolomko/SWCompression -github_file_prefix: https://github.com/tsolomko/SWCompression/tree/4.5.6 +github_file_prefix: https://github.com/tsolomko/SWCompression/tree/4.5.7 theme: fullwidth custom_categories: diff --git a/CHANGELOG.md b/CHANGELOG.md index fae75d4a..269a0fd7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## 4.5.7 + +- Fixed a crash when trying to open a very small file as a 7-Zip container, a BZip2 "archive", a GZip archive (both when + using `unarchive` and `multiUnarchive`), a LZMA "archive", a XZ archive (both when using `unarchive` and `splitUnarchive`), + a ZIP container, or a Zlib archive. +- Fixed a crash when trying to open an unexpectedly truncated file as a GZip or XZ archive. +- Fixed a crash when trying to open an invalid file as a ZIP container. The `ZipError.notFoundCentralDirectoryEnd` error + is now thrown instead as was originally intended. +- Fixed a crash when trying to read a GZip or Zlib header from a very small file. +- Fixed a compilation warning in BZip2. + ## 4.5.6 - Fixed a compiling issue on Linux with Swift 5.3. diff --git a/SWCompression.podspec b/SWCompression.podspec index 8d3a1fe9..f9c3caf0 100644 --- a/SWCompression.podspec +++ b/SWCompression.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "SWCompression" - s.version = "4.5.6" + s.version = "4.5.7" s.summary = "A framework with functions for working with compression, archives and containers." s.description = "A framework with (de)compression algorithms and functions for processing various archives and containers." diff --git a/SWCompression.xcodeproj/SWCompression.plist b/SWCompression.xcodeproj/SWCompression.plist index 518b2856..46a41309 100644 --- a/SWCompression.xcodeproj/SWCompression.plist +++ b/SWCompression.xcodeproj/SWCompression.plist @@ -15,9 +15,9 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 4.5.6 + 4.5.7 CFBundleVersion - 73 + 74 NSHumanReadableCopyright Copyright © 2020 Timofey Solomko. All rights reserved. diff --git a/SWCompression.xcodeproj/TestSWCompression.plist b/SWCompression.xcodeproj/TestSWCompression.plist index 46874253..a8ecec80 100644 --- a/SWCompression.xcodeproj/TestSWCompression.plist +++ b/SWCompression.xcodeproj/TestSWCompression.plist @@ -15,8 +15,8 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 4.5.6 + 4.5.7 CFBundleVersion - 73 + 74 diff --git a/SWCompression.xcodeproj/project.pbxproj b/SWCompression.xcodeproj/project.pbxproj index aee91300..da0e0662 100644 --- a/SWCompression.xcodeproj/project.pbxproj +++ b/SWCompression.xcodeproj/project.pbxproj @@ -213,6 +213,8 @@ 06F066771FFB763400312A82 /* test8.bz2 in Resources */ = {isa = PBXBuildFile; fileRef = 06F066111FFB763300312A82 /* test8.bz2 */; }; 06F276DF1F2BAB4A00E67335 /* 7zEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06F276DE1F2BAB4900E67335 /* 7zEntry.swift */; }; 06FEAD921F54B9CD00AD016E /* EncodingTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06FEAD911F54B9CD00AD016E /* EncodingTree.swift */; }; + E66F36242538726E00076A6E /* test_empty.lzma in Resources */ = {isa = PBXBuildFile; fileRef = E66F36232538726E00076A6E /* test_empty.lzma */; }; + E66F362C2538E2B700076A6E /* test_empty.zlib in Resources */ = {isa = PBXBuildFile; fileRef = E66F362B2538E2B700076A6E /* test_empty.zlib */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -433,6 +435,8 @@ 06F276DE1F2BAB4900E67335 /* 7zEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = 7zEntry.swift; sourceTree = ""; }; 06FEAD911F54B9CD00AD016E /* EncodingTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = EncodingTree.swift; path = Sources/Common/CodingTree/EncodingTree.swift; sourceTree = SOURCE_ROOT; }; 06FED40B1DD7717E0013DFB2 /* BZip2.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BZip2.swift; sourceTree = ""; }; + E66F36232538726E00076A6E /* test_empty.lzma */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_empty.lzma; sourceTree = ""; }; + E66F362B2538E2B700076A6E /* test_empty.zlib */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_empty.zlib; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -745,6 +749,7 @@ children = ( 06F065C41FFB763300312A82 /* test.zlib */, 06F065C51FFB763300312A82 /* random_file.zlib */, + E66F362B2538E2B700076A6E /* test_empty.zlib */, ); path = Zlib; sourceTree = ""; @@ -838,6 +843,7 @@ 06F065F41FFB763300312A82 /* test9.lzma */, 06F065F31FFB763300312A82 /* test10.lzma */, 06F065F21FFB763300312A82 /* test11.lzma */, + E66F36232538726E00076A6E /* test_empty.lzma */, ); path = LZMA; sourceTree = ""; @@ -1032,9 +1038,11 @@ 06F066391FFB763400312A82 /* test8.xz in Resources */, 06F0662F1FFB763400312A82 /* test9.gz in Resources */, 064DF453245618A300D285F3 /* bad_cd_ext_ts.zip in Resources */, + E66F36242538726E00076A6E /* test_empty.lzma in Resources */, 06F066751FFB763400312A82 /* test1.bz2 in Resources */, 064D01A920FD071300CAE058 /* текстовый файл.answer in Resources */, 06F0662D1FFB763400312A82 /* test6.gz in Resources */, + E66F362C2538E2B700076A6E /* test_empty.zlib in Resources */, 06F0664D1FFB763400312A82 /* test_ustar.tar in Resources */, 06F0665A1FFB763400312A82 /* test11.lzma in Resources */, 06F066401FFB763400312A82 /* test_zip_bzip2.zip in Resources */, @@ -1241,7 +1249,7 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CURRENT_PROJECT_VERSION = 73; + CURRENT_PROJECT_VERSION = 74; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; @@ -1300,7 +1308,7 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CURRENT_PROJECT_VERSION = 73; + CURRENT_PROJECT_VERSION = 74; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; "FRAMEWORK_SEARCH_PATHS[sdk=appletvos*]" = "\"$(SRCROOT)/Carthage/Build/tvOS\""; @@ -1340,7 +1348,7 @@ APPLICATION_EXTENSION_API_ONLY = YES; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 73; + DYLIB_CURRENT_VERSION = 74; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = SWCompression.xcodeproj/SWCompression.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -1367,7 +1375,7 @@ APPLICATION_EXTENSION_API_ONLY = YES; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 73; + DYLIB_CURRENT_VERSION = 74; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = SWCompression.xcodeproj/SWCompression.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; diff --git a/Sources/7-Zip/7zContainer.swift b/Sources/7-Zip/7zContainer.swift index c0c3e4f9..d9fa1794 100644 --- a/Sources/7-Zip/7zContainer.swift +++ b/Sources/7-Zip/7zContainer.swift @@ -202,6 +202,10 @@ public class SevenZipContainer: Container { } private static func readHeader(_ data: Data) throws -> SevenZipHeader? { + // Valid 7-Zip container must contain at least a SignatureHeader, which is 32 bytes long. + guard data.count >= 32 + else { throw SevenZipError.wrongSignature } + let bitReader = MsbBitReader(data: data) // **SignatureHeader** @@ -223,19 +227,18 @@ public class SevenZipContainer: Container { let nextHeaderSize = bitReader.int(fromBytes: 8) let nextHeaderCRC = bitReader.uint32() - bitReader.offset = 12 + bitReader.offset -= 20 guard CheckSums.crc32(bitReader.bytes(count: 20)) == startHeaderCRC else { throw SevenZipError.wrongCRC } // **Header** bitReader.offset += nextHeaderOffset - let headerStartIndex = bitReader.offset - let headerEndIndex: Int - if bitReader.isFinished { return nil // In case of completely empty container. } + let headerStartIndex = bitReader.offset + let headerEndIndex: Int let type = bitReader.byte() let header: SevenZipHeader diff --git a/Sources/BZip2/BZip2.swift b/Sources/BZip2/BZip2.swift index ad717fbe..aed1442f 100644 --- a/Sources/BZip2/BZip2.swift +++ b/Sources/BZip2/BZip2.swift @@ -26,6 +26,10 @@ public class BZip2: DecompressionAlgorithm { } static func decompress(_ bitReader: MsbBitReader) throws -> Data { + // Valid BZip2 "archive" must contain at least 14 bytes of data. + guard bitReader.bitsLeft >= 14 * 8 + else { throw BZip2Error.wrongMagic } + /// An array for storing output data var out = Data() diff --git a/Sources/GZip/GzipArchive.swift b/Sources/GZip/GzipArchive.swift index a5b1cad4..648e1f35 100644 --- a/Sources/GZip/GzipArchive.swift +++ b/Sources/GZip/GzipArchive.swift @@ -77,6 +77,10 @@ public class GzipArchive: Archive { } private static func processMember(_ bitReader: LsbBitReader) throws -> Member { + // Valid GZip archive must contain at least 33 bytes of data. + guard bitReader.bitsLeft >= 33 * 8 + else { throw GzipError.wrongMagic } + let header = try GzipHeader(bitReader) let memberData = try Deflate.decompress(bitReader) diff --git a/Sources/GZip/GzipHeader.swift b/Sources/GZip/GzipHeader.swift index 74401b1e..b2f85de5 100644 --- a/Sources/GZip/GzipHeader.swift +++ b/Sources/GZip/GzipHeader.swift @@ -58,6 +58,10 @@ public struct GzipHeader { } init(_ reader: LsbBitReader) throws { + // Valid GZip header must contain at least 2 bytes of data. + guard reader.bytesLeft >= 10 + else { throw GzipError.wrongMagic } + // First two bytes should be correct 'magic' bytes let magic = reader.uint16() guard magic == 0x8b1f else { throw GzipError.wrongMagic } diff --git a/Sources/LZMA/LZMA.swift b/Sources/LZMA/LZMA.swift index ad86fb42..06a922e3 100644 --- a/Sources/LZMA/LZMA.swift +++ b/Sources/LZMA/LZMA.swift @@ -23,6 +23,10 @@ public class LZMA: DecompressionAlgorithm { - Returns: Decompressed data. */ public static func decompress(data: Data) throws -> Data { + // Valid LZMA "archive" must contain at least 13 bytes of data with properties and uncompressed size. + guard data.count >= 13 + else { throw LZMAError.wrongProperties } + let byteReader = LittleEndianByteReader(data: data) let properties = try LZMAProperties(byteReader) let uncompSize = byteReader.int(fromBytes: 8) diff --git a/Sources/LZMA/LZMADecoder.swift b/Sources/LZMA/LZMADecoder.swift index 9512e4ee..a18f5a95 100644 --- a/Sources/LZMA/LZMADecoder.swift +++ b/Sources/LZMA/LZMADecoder.swift @@ -255,8 +255,7 @@ final class LZMADecoder { // Middle bits of distance are decoded as direct bits from RangeDecoder. dist += rangeDecoder.decode(directBits: (numDirectBits - LZMAConstants.numAlignBits)) << LZMAConstants.numAlignBits - // Low 4 bits are decoded with a bit tree decoder (called 'AlignDecoder')... - // ...with "Reverse" scheme. + // Low 4 bits are decoded with a bit tree decoder (called 'AlignDecoder') using "Reverse" scheme. dist += alignDecoder.reverseDecode(with: rangeDecoder) } rep0 = dist diff --git a/Sources/LZMA/LZMARangeDecoder.swift b/Sources/LZMA/LZMARangeDecoder.swift index fde97a95..3521c213 100644 --- a/Sources/LZMA/LZMARangeDecoder.swift +++ b/Sources/LZMA/LZMARangeDecoder.swift @@ -19,6 +19,10 @@ final class LZMARangeDecoder { } init?(_ byteReader: LittleEndianByteReader) { + // To initialize rande decoder at least 5 bytes are necessary. + guard byteReader.bytesLeft >= 5 + else { return nil } + self.byteReader = byteReader let byte = self.byteReader.byte() diff --git a/Sources/TAR/TarEntryInfo.swift b/Sources/TAR/TarEntryInfo.swift index 88daba26..36a12873 100644 --- a/Sources/TAR/TarEntryInfo.swift +++ b/Sources/TAR/TarEntryInfo.swift @@ -264,7 +264,7 @@ public struct TarEntryInfo: ContainerEntryInfo { let linkName = byteReader.tarCString(maxLength: 100) // There are two different formats utilizing this section of TAR header: GNU format and POSIX (aka "ustar"; - // also PAX containers can also be considered POSIX). They differ in the value of magic field as well as what + // PAX containers can also be considered as POSIX). They differ in the value of magic field as well as what // comes after deviceMinorNumber field. While "ustar" format may contain prefix for file name, GNU format // uses this place for storing atime/ctime and fields related to sparse-files. In practice, these fields are // rarely used by GNU tar and only present if "incremental backups" options were used. Thus, GNU format TAR @@ -309,7 +309,7 @@ public struct TarEntryInfo: ContainerEntryInfo { if local != nil || global != nil { self.format = .pax - } else if magic == 0x00_20_20_72_61_74_73_75 || longName != nil || longLinkName != nil { + } else if magic == 0x0020207261747375 || longName != nil || longLinkName != nil { self.format = .gnu } else if magic == 0x3030007261747375 || magic == 0x3030207261747375 { self.format = .ustar diff --git a/Sources/XZ/XZArchive.swift b/Sources/XZ/XZArchive.swift index ca6aea6e..3a6c605f 100644 --- a/Sources/XZ/XZArchive.swift +++ b/Sources/XZ/XZArchive.swift @@ -35,6 +35,10 @@ public class XZArchive: Archive { var result = Data() while !byteReader.isFinished { + // Valid XZ archive must contain at least 32 bytes of data. + guard byteReader.bytesLeft >= 32 + else { throw XZError.wrongMagic } + let streamResult = try processStream(byteReader) result.append(streamResult.data) guard !streamResult.checkError @@ -68,6 +72,10 @@ public class XZArchive: Archive { var result = [Data]() while !byteReader.isFinished { + // Valid XZ archive must contain at least 32 bytes of data. + guard byteReader.bytesLeft >= 32 + else { throw XZError.wrongMagic } + let streamResult = try processStream(byteReader) result.append(streamResult.data) guard !streamResult.checkError diff --git a/Sources/ZIP/ZipContainer.swift b/Sources/ZIP/ZipContainer.swift index 736ed7a0..020d6239 100644 --- a/Sources/ZIP/ZipContainer.swift +++ b/Sources/ZIP/ZipContainer.swift @@ -141,6 +141,10 @@ public class ZipContainer: Container { } private static func infoWithHelper(_ data: Data) throws -> [ZipEntryInfoHelper] { + // Valid ZIP container must contain at least an End of Central Directory record, which is at least 22 bytes long. + guard data.count >= 22 + else { throw ZipError.notFoundCentralDirectoryEnd } + let byteReader = LittleEndianByteReader(data: data) var entries = [ZipEntryInfoHelper]() @@ -152,7 +156,7 @@ public class ZipContainer: Container { // We found it! break } - if byteReader.offset == 0 { + if byteReader.offset == 4 { throw ZipError.notFoundCentralDirectoryEnd } byteReader.offset -= 5 diff --git a/Sources/Zlib/ZlibArchive.swift b/Sources/Zlib/ZlibArchive.swift index 8e6b8593..e7d5084a 100644 --- a/Sources/Zlib/ZlibArchive.swift +++ b/Sources/Zlib/ZlibArchive.swift @@ -23,6 +23,10 @@ public class ZlibArchive: Archive { - Returns: Unarchived data. */ public static func unarchive(archive data: Data) throws -> Data { + // Valid Zlib archive must contain at least 8 bytes of data. + guard data.count >= 8 + else { throw ZlibError.wrongCompressionMethod } + /// Object with input data which supports convenient work with bit shifts. let bitReader = LsbBitReader(data: data) diff --git a/Sources/Zlib/ZlibHeader.swift b/Sources/Zlib/ZlibHeader.swift index 72c3e54b..f71c8218 100644 --- a/Sources/Zlib/ZlibHeader.swift +++ b/Sources/Zlib/ZlibHeader.swift @@ -45,6 +45,10 @@ public struct ZlibHeader { } init(_ reader: LsbBitReader) throws { + // Valid Zlib header must contain at least 2 bytes of data. + guard reader.bytesLeft >= 2 + else { throw ZlibError.wrongCompressionMethod } + // compressionMethod and compressionInfo combined are needed later for integrity check. let cmf = reader.byte() // First four bits are compression method. @@ -65,7 +69,7 @@ public struct ZlibHeader { // fcheck, fdict and compresionLevel together make flags byte which is used in integrity check. let flags = reader.byte() - // First five bits are fcheck bits which are supposed to be integrity check: + // First five bits are fcheck bits which are used for integrity check: // let fcheck = flags & 0x1F // Sixth bit indicate if archive contain Adler-32 checksum of preset dictionary. diff --git a/Sources/swcomp/main.swift b/Sources/swcomp/main.swift index e90ac2a3..f7c62315 100644 --- a/Sources/swcomp/main.swift +++ b/Sources/swcomp/main.swift @@ -7,7 +7,7 @@ import Foundation import SWCompression import SwiftCLI -let cli = CLI(name: "swcomp", version: "4.5.6", +let cli = CLI(name: "swcomp", version: "4.5.7", description: """ swcomp - a small command-line client for SWCompression framework. Serves as an example of SWCompression usage. diff --git a/Tests/BZip2Tests.swift b/Tests/BZip2Tests.swift index 4db58c1d..3107c973 100644 --- a/Tests/BZip2Tests.swift +++ b/Tests/BZip2Tests.swift @@ -54,4 +54,13 @@ class BZip2Tests: XCTestCase { try self.perform(test: "test9") } + func testBadFile_short() { + XCTAssertThrowsError(try BZip2.decompress(data: Data([0]))) + } + + func testBadFile_invalid() throws { + let testData = try Constants.data(forAnswer: "test6") + XCTAssertThrowsError(try BZip2.decompress(data: testData)) + } + } diff --git a/Tests/GzipTests.swift b/Tests/GzipTests.swift index 13fc74e0..8f662df5 100644 --- a/Tests/GzipTests.swift +++ b/Tests/GzipTests.swift @@ -139,4 +139,16 @@ class GzipTests: XCTestCase { XCTAssertEqual(data, answerData) } + func testBadFile_short() { + XCTAssertThrowsError(try GzipArchive.unarchive(archive: Data([0]))) + XCTAssertThrowsError(try GzipArchive.multiUnarchive(archive: Data([0]))) + XCTAssertThrowsError(try GzipHeader(archive: Data([0]))) + } + + func testBadFile_invalid() throws { + let testData = try Constants.data(forAnswer: "test6") + XCTAssertThrowsError(try GzipArchive.unarchive(archive: testData)) + XCTAssertThrowsError(try GzipArchive.multiUnarchive(archive: testData)) + } + } diff --git a/Tests/LzmaTests.swift b/Tests/LzmaTests.swift index 63a0c68d..1081a273 100644 --- a/Tests/LzmaTests.swift +++ b/Tests/LzmaTests.swift @@ -34,4 +34,22 @@ class LzmaTests: XCTestCase { try self.perform(test: "test11") } + func testLzmaEmpty() throws { + let testData = try Constants.data(forTest: "test_empty", withType: LzmaTests.testType) + XCTAssertEqual(try LZMA.decompress(data: testData), Data()) + } + + func testBadFile_short() { + // Not enough data for LZMA properties. + XCTAssertThrowsError(try LZMA.decompress(data: Data([0, 1, 2, 3]))) + // Not enough data to initialize range decoder. + XCTAssertThrowsError(try LZMA.decompress(data: Data([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]))) + } + + func testBadFile_invalid() throws { + let testData = try Constants.data(forAnswer: "test7") + XCTAssertThrowsError(try LZMA.decompress(data: testData)) + } + + } diff --git a/Tests/SevenZipTests.swift b/Tests/SevenZipTests.swift index 049a4fbe..affbe2c2 100644 --- a/Tests/SevenZipTests.swift +++ b/Tests/SevenZipTests.swift @@ -10,6 +10,15 @@ class SevenZipTests: XCTestCase { private static let testType: String = "7z" + func testBadFile_short() { + XCTAssertThrowsError(try SevenZipContainer.open(container: Data([0, 1, 2]))) + } + + func testBadFile_invalid() throws { + let testData = try Constants.data(forAnswer: "test6") + XCTAssertThrowsError(try SevenZipContainer.open(container: testData)) + } + func test1() throws { let testData = try Constants.data(forTest: "test1", withType: SevenZipTests.testType) let entries = try SevenZipContainer.open(container: testData) diff --git a/Tests/TarTests.swift b/Tests/TarTests.swift index 2debc652..17ccce19 100644 --- a/Tests/TarTests.swift +++ b/Tests/TarTests.swift @@ -10,6 +10,17 @@ class TarTests: XCTestCase { private static let testType: String = "tar" + func testBadFile_short() { + XCTAssertThrowsError(try TarContainer.open(container: Data([0, 1, 2]))) + } + + func testBadFile_invalid() throws { + // This is potentially a misleading test, since there is no way to guarantee that a file is not a TAR container. + // We use randomly generated data, since the 0-filled data is processed as an empty container. + let testData = try Constants.data(forAnswer: "test7") + XCTAssertThrowsError(try TarContainer.open(container: testData)) + } + func test() throws { let testData = try Constants.data(forTest: "test", withType: TarTests.testType) diff --git a/Tests/Test Files b/Tests/Test Files index b2f6a804..073da4e0 160000 --- a/Tests/Test Files +++ b/Tests/Test Files @@ -1 +1 @@ -Subproject commit b2f6a8042c372fab86e185e3d7000436dea6d769 +Subproject commit 073da4e01c87d9c1e599e507d1bb21e307c564ad diff --git a/Tests/XzTests.swift b/Tests/XzTests.swift index 558c7bf3..af7a1de9 100644 --- a/Tests/XzTests.swift +++ b/Tests/XzTests.swift @@ -110,4 +110,14 @@ class XZTests: XCTestCase { XCTAssertEqual(decompressedData, answerData) } + func testBadFile_short() { + XCTAssertThrowsError(try XZArchive.unarchive(archive: Data([0, 1, 2]))) + XCTAssertThrowsError(try XZArchive.splitUnarchive(archive: Data([0, 1, 2]))) + } + + func testBadFile_invalid() throws { + let testData = try Constants.data(forAnswer: "test6") + XCTAssertThrowsError(try XZArchive.unarchive(archive: testData)) + } + } diff --git a/Tests/ZipTests.swift b/Tests/ZipTests.swift index baf3a3db..69fd3ec6 100644 --- a/Tests/ZipTests.swift +++ b/Tests/ZipTests.swift @@ -10,6 +10,15 @@ class ZipTests: XCTestCase { private static let testType: String = "zip" + func testBadFile_short() { + XCTAssertThrowsError(try ZipContainer.open(container: Data([0, 1, 2, 3, 4, 5, 6, 7]))) + } + + func testBadFile_invalid() throws { + let testData = try Constants.data(forAnswer: "test6") + XCTAssertThrowsError(try ZipContainer.open(container: testData)) + } + func testBigContainer() throws { let testData = try Constants.data(forTest: "SWCompressionSourceCode", withType: ZipTests.testType) diff --git a/Tests/ZlibTests.swift b/Tests/ZlibTests.swift index d24dfa56..5040f746 100644 --- a/Tests/ZlibTests.swift +++ b/Tests/ZlibTests.swift @@ -37,4 +37,19 @@ class ZlibTests: XCTestCase { XCTAssertEqual(testData, reextractedData) } + func testZlibEmpty() throws { + let testData = try Constants.data(forTest: "test_empty", withType: ZlibTests.testType) + XCTAssertEqual(try ZlibArchive.unarchive(archive: testData), Data()) + } + + func testBadFile_short() { + XCTAssertThrowsError(try ZlibArchive.unarchive(archive: Data([0x78]))) + XCTAssertThrowsError(try ZlibHeader(archive: Data([0x78]))) + } + + func testBadFile_invalid() throws { + let testData = try Constants.data(forAnswer: "test6") + XCTAssertThrowsError(try ZlibArchive.unarchive(archive: testData)) + } + }