Skip to content

Commit

Permalink
Add inputBufferOverflow error
Browse files Browse the repository at this point in the history
To catch when we overflow the input buffer instead of the output buffer. An input buffer overflow can be ignored while streaming
  • Loading branch information
adam-fowler committed Apr 10, 2024
1 parent 3c6d9c3 commit 2af9ad0
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 5 deletions.
12 changes: 11 additions & 1 deletion Sources/CompressNIO/ByteBuffer+Compressor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}

Expand Down Expand Up @@ -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
}
}

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
}
}

Expand Down
10 changes: 7 additions & 3 deletions Sources/CompressNIO/Error.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 5 additions & 1 deletion Sources/CompressNIO/Zlib.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
18 changes: 18 additions & 0 deletions Tests/CompressNIOTests/NIOCompressTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 2af9ad0

Please sign in to comment.