Skip to content

Commit

Permalink
Support unlimitedFrameCount and skipChecksumVerify
Browse files Browse the repository at this point in the history
  • Loading branch information
onevcat committed Oct 20, 2021
1 parent b698b55 commit f958375
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 9 deletions.
26 changes: 18 additions & 8 deletions Source/APNGKit/APNGDecoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ class APNGDecoder {
private let reader: Reader

private var resetStatus: ResetStatus!

private let options: APNGImage.DecodingOptions

let cachePolicy: APNGImage.CachePolicy

convenience init(data: Data, options: APNGImage.DecodingOptions = []) throws {
Expand All @@ -76,18 +76,20 @@ class APNGDecoder {
self.reader = reader
self.options = options

let skipChecksumVerify = options.contains(.skipChecksumVerify)

// Decode and load the common part and at least make the first frame prepared.
guard let signature = try reader.read(upToCount: 8),
signature.bytes == Self.pngSignature
else {
throw APNGKitError.decoderError(.fileFormatError)
}
let ihdr = try reader.readChunk(type: IHDR.self)
let ihdr = try reader.readChunk(type: IHDR.self, skipChecksumVerify: skipChecksumVerify)
imageHeader = ihdr.chunk

let acTLResult: UntilChunkResult<acTL>
do {
acTLResult = try reader.readUntil(type: acTL.self)
acTLResult = try reader.readUntil(type: acTL.self, skipChecksumVerify: skipChecksumVerify)
} catch { // Can not read a valid `acTL`. Should be treated as a normal PNG.
throw APNGKitError.decoderError(.lackOfChunk(acTL.name))
}
Expand All @@ -104,7 +106,7 @@ class APNGDecoder {
// alloc JIT.
//
// For now, just hard code a reasonable upper limitation.
if numberOfFrames >= 1024 {
if numberOfFrames >= 1024 && !options.contains(.unlimitedFrameCount) {
throw APNGKitError.decoderError(.invalidNumberOfFrames(value: numberOfFrames))
}
frames = [APNGFrame?](repeating: nil, count: acTLResult.chunk.numberOfFrames)
Expand Down Expand Up @@ -200,7 +202,7 @@ class APNGDecoder {
}

if !firstPass { // Animation with only one frame,check IEND.
_ = try reader.readChunk(type: IEND.self)
_ = try reader.readChunk(type: IEND.self, skipChecksumVerify: skipChecksumVerify)

// Dispatch to give the user a chance to setup delegate after they get the returned APNG image.
DispatchQueue.main.async { self.onFirstPassDone() }
Expand Down Expand Up @@ -247,7 +249,7 @@ class APNGDecoder {

image = try render(frame: frame, data: data, index: newIndex)
if !firstPass {
_ = try reader.readChunk(type: IEND.self)
_ = try reader.readChunk(type: IEND.self, skipChecksumVerify: options.contains(.skipChecksumVerify))
DispatchQueue.main.asyncOrSyncIfMain {
self.onFirstPassDone()
}
Expand Down Expand Up @@ -456,13 +458,17 @@ class APNGDecoder {
var result: [fdAT] = []
var allData: Data = .init()

let skipChecksumVerify = options.contains(.skipChecksumVerify)

var frameDataEnd = false
while !frameDataEnd {
try reader.peek { info, action in
switch info.name.bytes {
case fdAT.nameBytes:
let peekAction: PeekAction =
options.contains(.loadFrameData) ? .read(type: fdAT.self) : .readIndexedfdAT()
options.contains(.loadFrameData) ?
.read(type: fdAT.self, skipChecksumVerify: skipChecksumVerify) :
.readIndexedfdAT(skipChecksumVerify: skipChecksumVerify)
let (chunk, data) = try action(peekAction).fdAT
try checkSequenceNumber(chunk)
result.append(chunk)
Expand All @@ -485,13 +491,17 @@ class APNGDecoder {
var chunks: [IDAT] = []
var allData: Data = .init()

let skipChecksumVerify = options.contains(.skipChecksumVerify)

var imageDataEnd = false
while !imageDataEnd {
try reader.peek { info, action in
switch info.name.bytes {
case IDAT.nameBytes:
let peekAction: PeekAction =
options.contains(.loadFrameData) ? .read(type: IDAT.self) : .readIndexedIDAT()
options.contains(.loadFrameData) ?
.read(type: IDAT.self, skipChecksumVerify: skipChecksumVerify) :
.readIndexedIDAT(skipChecksumVerify: skipChecksumVerify)
let (chunk, data) = try action(peekAction).IDAT
chunks.append(chunk)
allData.append(data)
Expand Down
2 changes: 1 addition & 1 deletion Source/APNGKit/APNGImage.DecodingOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ extension APNGImage {
///
/// Enable this to ask APNGKit to skip this check. It improves the CPU performance a bit, but with the risk of
/// reading and trust unchecked chunks. It is not recommended to skip the check.
public static let skipChecksumCheck = DecodingOptions(rawValue: 1 << 5)
public static let skipChecksumVerify = DecodingOptions(rawValue: 1 << 5)

/// Unsets frame count limitation when reading an APNG image.
///
Expand Down

0 comments on commit f958375

Please sign in to comment.