Skip to content

Commit a0dd8e5

Browse files
authored
Merge pull request #90 from onevcat/fix/size-overflow
Fix a size overflow when calculate data length
2 parents 332578c + 526b978 commit a0dd8e5

File tree

5 files changed

+28
-6
lines changed

5 files changed

+28
-6
lines changed

APNGKit.xcodeproj/project.pbxproj

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
4B7D4ED61B9559BF005C0598 /* filter_neon_intrinsics.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B7D4ED41B9559BF005C0598 /* filter_neon_intrinsics.c */; };
4949
4B7D4ED71B9559BF005C0598 /* filter_neon.S in Sources */ = {isa = PBXBuildFile; fileRef = 4B7D4ED51B9559BF005C0598 /* filter_neon.S */; };
5050
4B7D4ED91B955CBF005C0598 /* arm_init.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B7D4ED81B955CBF005C0598 /* arm_init.c */; };
51+
4BA1EFA7231767BE00D6D06C /* malformed-size.apng in Resources */ = {isa = PBXBuildFile; fileRef = 4BA1EFA6231767BD00D6D06C /* malformed-size.apng */; };
52+
4BA1EFA8231767BE00D6D06C /* malformed-size.apng in Resources */ = {isa = PBXBuildFile; fileRef = 4BA1EFA6231767BD00D6D06C /* malformed-size.apng */; };
5153
4BF022041B94442800F00CDE /* APNGImageViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BF022031B94442800F00CDE /* APNGImageViewTests.swift */; };
5254
B25269641E8FD9840096A0A7 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = B25269631E8FD9840096A0A7 /* libz.tbd */; };
5355
B25269661E8FDA090096A0A7 /* GCDTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B19504F1E6D21670047B7DE /* GCDTimer.swift */; };
@@ -185,6 +187,7 @@
185187
4B7D4ED41B9559BF005C0598 /* filter_neon_intrinsics.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = filter_neon_intrinsics.c; sourceTree = "<group>"; };
186188
4B7D4ED51B9559BF005C0598 /* filter_neon.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = filter_neon.S; sourceTree = "<group>"; };
187189
4B7D4ED81B955CBF005C0598 /* arm_init.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = arm_init.c; sourceTree = "<group>"; };
190+
4BA1EFA6231767BD00D6D06C /* malformed-size.apng */ = {isa = PBXFileReference; lastKnownFileType = file; name = "malformed-size.apng"; path = "TestImages/malformed-size.apng"; sourceTree = SOURCE_ROOT; };
188191
4BF022031B94442800F00CDE /* APNGImageViewTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = APNGImageViewTests.swift; sourceTree = "<group>"; };
189192
B252695A1E8FD8EA0096A0A7 /* APNGKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = APNGKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
190193
B25269631E8FD9840096A0A7 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/lib/libz.tbd; sourceTree = DEVELOPER_DIR; };
@@ -371,6 +374,7 @@
371374
D1614E1C1B91EDD700050104 /* TestImages */ = {
372375
isa = PBXGroup;
373376
children = (
377+
4BA1EFA6231767BD00D6D06C /* malformed-size.apng */,
374378
4B5DF6831B99718C00C4D421 /* demo.png */,
375379
D187FEE81B934F1B0013372D /* pyani.apng */,
376380
D190199F1B93351300E16EDB /* elephant_apng.apng */,
@@ -575,6 +579,7 @@
575579
developmentRegion = English;
576580
hasScannedForEncodings = 0;
577581
knownRegions = (
582+
English,
578583
en,
579584
Base,
580585
);
@@ -606,6 +611,7 @@
606611
buildActionMask = 2147483647;
607612
files = (
608613
D1614E251B91EDE200050104 /* over_previous.apng in Resources */,
614+
4BA1EFA7231767BE00D6D06C /* malformed-size.apng in Resources */,
609615
D1614E331B91EE0000050104 /* minimalAPNG.apng in Resources */,
610616
D19019A01B93351400E16EDB /* elephant_apng.apng in Resources */,
611617
D1614E261B91EDE200050104 /* spinfox.apng in Resources */,
@@ -630,6 +636,7 @@
630636
buildActionMask = 2147483647;
631637
files = (
632638
B25310201E90AA3200A65CEA /* ball.apng in Resources */,
639+
4BA1EFA8231767BE00D6D06C /* malformed-size.apng in Resources */,
633640
B253101F1E90AA3200A65CEA /* minimalAPNG.apng in Resources */,
634641
B253101D1E90AA3200A65CEA /* elephant_apng.apng in Resources */,
635642
B25310231E90AA3200A65CEA /* over_previous.apng in Resources */,

APNGKit/Disassembler.swift

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@
3535
#endif
3636

3737
let signatureOfPNGLength = 8
38-
let kMaxPNGSize: UInt32 = 1000000;
38+
let kMaxPNGSize: UInt32 = 1000000
39+
let kUserAllocMaxBytes: UInt32 = 100*1024*1024
3940

4041
// Reading callback for libpng
4142
func readData(_ pngPointer: png_structp?, outBytes: png_bytep?, byteCountToRead: png_size_t) {
@@ -60,8 +61,8 @@ struct APNGMeta {
6061

6162
let firstFrameHidden: Bool
6263

63-
var length: UInt32 {
64-
return height * rowBytes
64+
var length: Int {
65+
return Int(height) * Int(rowBytes)
6566
}
6667

6768
var firstImageIndex: Int {
@@ -291,6 +292,10 @@ class Disassembler {
291292
let height = png_get_image_height(pngPointer, infoPointer)
292293
let rowBytes = UInt32(png_get_rowbytes(pngPointer, infoPointer))
293294

295+
if width > kMaxPNGSize || height > kMaxPNGSize {
296+
throw DisassemblerError.fileSizeExceeded
297+
}
298+
294299
// Decode acTL
295300
var frameCount: UInt32 = 0, playCount: UInt32 = 0
296301
png_get_acTL(pngPointer, infoPointer, &frameCount, &playCount)
@@ -312,7 +317,12 @@ class Disassembler {
312317
frameCount: frameCount,
313318
playCount: playCount,
314319
firstFrameHidden: firstFrameHidden)
315-
320+
321+
if meta.length > kUserAllocMaxBytes {
322+
throw DisassemblerError.fileSizeExceeded
323+
324+
}
325+
316326
bufferFrame = Frame(length: meta.length, bytesInRow: meta.rowBytes)
317327
currentFrame = Frame(length: meta.length, bytesInRow: meta.rowBytes)
318328
apngMeta = meta

APNGKit/Frame.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ class Frame {
8888

8989
var duration: TimeInterval = 0
9090

91-
init(length: UInt32, bytesInRow: UInt32) {
92-
self.length = Int(length)
91+
init(length: Int, bytesInRow: UInt32) {
92+
self.length = length
9393
self.bytesInRow = Int(bytesInRow)
9494

9595
self.bytes = UnsafeMutablePointer<UInt8>.allocate(capacity: self.length)

APNGKitTests/APNGImageTests.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,11 @@ class APNGImageTests: XCTestCase {
198198
let image = APNGImage(named: "", in: .testBundle)
199199
XCTAssertNil(image, "Empty string should result in nil")
200200
}
201+
202+
func testOverflowImage() {
203+
let image = APNGImage(named: "malformed-size", in: .testBundle)
204+
XCTAssertNil(image)
205+
}
201206
}
202207

203208
private extension CocoaImage {

TestImages/malformed-size.apng

95.8 KB
Binary file not shown.

0 commit comments

Comments
 (0)