diff --git a/Sources/CompressNIO/ByteBuffer+Compressor.swift b/Sources/CompressNIO/ByteBuffer+Compressor.swift index a64610a..dc3941f 100644 --- a/Sources/CompressNIO/ByteBuffer+Compressor.swift +++ b/Sources/CompressNIO/ByteBuffer+Compressor.swift @@ -98,6 +98,8 @@ extension ByteBuffer { try process(window) window.moveReaderIndex(to: 0) window.moveWriterIndex(to: 0) + } catch let error as CompressNIOError where error == .inputBufferOverflow { + // can ignore CompressNIOError.inputBufferOverflow errors here } } @@ -146,6 +148,8 @@ extension ByteBuffer { try self.decompressStream(to: &buffer, with: decompressor) } catch let error as CompressNIOError where error == CompressNIOError.bufferOverflow { try _decompress(iteration: iteration + 1, bufferSize: bufferSize) + } catch let error as CompressNIOError where error == .inputBufferOverflow { + // can ignore CompressNIOError.inputBufferOverflow errors here } } @@ -196,7 +200,11 @@ extension ByteBuffer { to byteBuffer: inout ByteBuffer, with decompressor: NIODecompressor ) throws { - try decompressor.streamInflate(from: &self, to: &byteBuffer) + do { + try decompressor.streamInflate(from: &self, to: &byteBuffer) + } catch let error as CompressNIOError where error == .inputBufferOverflow { + // can ignore CompressNIOError.inputBufferOverflow errors here + } } /// A version of compressStream which you provide a fixed sized window buffer to and a process closure. @@ -352,6 +360,8 @@ extension ByteBuffer { try await process(window) window.moveReaderIndex(to: 0) window.moveWriterIndex(to: 0) + } catch let error as CompressNIOError where error == .inputBufferOverflow { + // can ignore CompressNIOError.inputBufferOverflow errors here } } diff --git a/Sources/CompressNIO/Error.swift b/Sources/CompressNIO/Error.swift index 3062f53..d45d4fe 100644 --- a/Sources/CompressNIO/Error.swift +++ b/Sources/CompressNIO/Error.swift @@ -5,18 +5,22 @@ import NIOCore public struct CompressNIOError: Swift.Error, CustomStringConvertible, Equatable { fileprivate enum ErrorEnum: String { case bufferOverflow + case inputBufferOverflow case corruptData case noMoreMemory case unfinished case internalError } + fileprivate let error: ErrorEnum - + /// return as String - public var description: String { return error.rawValue } - + public var description: String { return self.error.rawValue } + /// output buffer is too small public static let bufferOverflow = CompressNIOError(error: .bufferOverflow) + /// input buffer is too small + public static let inputBufferOverflow = CompressNIOError(error: .inputBufferOverflow) /// input data is corrupt public static let corruptData = CompressNIOError(error: .corruptData) /// ran out of memory diff --git a/Sources/CompressNIO/Zlib.swift b/Sources/CompressNIO/Zlib.swift index 1673178..5a35c42 100644 --- a/Sources/CompressNIO/Zlib.swift +++ b/Sources/CompressNIO/Zlib.swift @@ -308,7 +308,11 @@ final class ZlibDecompressor: NIODecompressor { throw CompressNIOError.bufferOverflow } case Z_BUF_ERROR: - throw CompressNIOError.bufferOverflow + if self.stream.avail_in == 0 { + throw CompressNIOError.inputBufferOverflow + } else { + throw CompressNIOError.bufferOverflow + } case Z_DATA_ERROR: throw CompressNIOError.corruptData case Z_MEM_ERROR: diff --git a/Tests/CompressNIOTests/NIOCompressTests.swift b/Tests/CompressNIOTests/NIOCompressTests.swift index 467c8a9..d79b65d 100644 --- a/Tests/CompressNIOTests/NIOCompressTests.swift +++ b/Tests/CompressNIOTests/NIOCompressTests.swift @@ -315,6 +315,24 @@ class CompressNIOTests: XCTestCase { try self.testCompressionAlgorithm(.deflate(configuration: .init(memoryLevel: 9))) } + func testDecompressWithInputBufferError() throws { + var buffer1 = ByteBuffer(bytes: [0xAA, 0xE6, 0x52, 0x50, 0x50, 0x50, 0x72, 0x2C, 0x2D, 0xC9, 0x4F, 0x4A, 0xCC, 0xC8, 0x0B, 0xA8, 0x04, 0x00, 0x00, 0x00, 0xFF, 0xFF]) + var buffer2 = ByteBuffer(bytes: [0x2A, 0xC9, 0xC8, 0xCF, 0xD3, 0x37, 0xD0, 0x33, 0xD3, 0x33, 0x50, 0xB2, 0x52, 0xA8, 0xE6, 0x52, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF]) + var buffer3 = ByteBuffer(bytes: [0x02, 0x03, 0x25, 0x43, 0x3D, 0x20, 0x04, 0x0B, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF]) + var buffer4 = ByteBuffer(bytes: [0x52, 0x80, 0x01, 0xA5, 0xA4, 0xD4, 0x8C, 0xC4, 0xB2, 0x4C, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF]) + var buffer5 = ByteBuffer(bytes: [0xCA, 0x2F, 0x02, 0x0A, 0x2B, 0xF9, 0x7B, 0x2B, 0xE9, 0x40, 0xA4, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF]) + var buffer6 = ByteBuffer(bytes: [0x42, 0x91, 0x72, 0xCE, 0xC9, 0x07, 0x00, 0x00, 0x00, 0xFF, 0xFF]) + + let decompressor = CompressionAlgorithm.deflate().decompressor + try decompressor.startStream() + _ = try buffer1.decompressStream(with: decompressor, maxSize: 65536) + _ = try buffer2.decompressStream(with: decompressor, maxSize: 65536) + _ = try buffer3.decompressStream(with: decompressor, maxSize: 65536) + _ = try buffer4.decompressStream(with: decompressor, maxSize: 65536) + _ = try buffer5.decompressStream(with: decompressor, maxSize: 65536) + _ = try buffer6.decompressStream(with: decompressor, maxSize: 65536) + } + func testTwoStreamsInParallel() throws { let buffer = self.createRandomBuffer(size: 1024) var bufferToCompress = buffer