From f5a9c98062107495cdcfbddfbc67de69aa9e9bb2 Mon Sep 17 00:00:00 2001 From: onevcat Date: Thu, 29 Aug 2019 10:51:39 +0900 Subject: [PATCH 1/2] Fix a size overflow when calculate data length --- APNGKit/Disassembler.swift | 18 ++++++++++++++---- APNGKit/Frame.swift | 4 ++-- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/APNGKit/Disassembler.swift b/APNGKit/Disassembler.swift index cdf0678..02f2311 100644 --- a/APNGKit/Disassembler.swift +++ b/APNGKit/Disassembler.swift @@ -35,7 +35,8 @@ #endif let signatureOfPNGLength = 8 -let kMaxPNGSize: UInt32 = 1000000; +let kMaxPNGSize: UInt32 = 1000000 +let kUserAllocMaxBytes: UInt32 = 100*1024*1024 // Reading callback for libpng func readData(_ pngPointer: png_structp?, outBytes: png_bytep?, byteCountToRead: png_size_t) { @@ -60,8 +61,8 @@ struct APNGMeta { let firstFrameHidden: Bool - var length: UInt32 { - return height * rowBytes + var length: Int { + return Int(height) * Int(rowBytes) } var firstImageIndex: Int { @@ -291,6 +292,10 @@ class Disassembler { let height = png_get_image_height(pngPointer, infoPointer) let rowBytes = UInt32(png_get_rowbytes(pngPointer, infoPointer)) + if width > kMaxPNGSize || height > kMaxPNGSize { + throw DisassemblerError.fileSizeExceeded + } + // Decode acTL var frameCount: UInt32 = 0, playCount: UInt32 = 0 png_get_acTL(pngPointer, infoPointer, &frameCount, &playCount) @@ -312,7 +317,12 @@ class Disassembler { frameCount: frameCount, playCount: playCount, firstFrameHidden: firstFrameHidden) - + + if meta.length > kUserAllocMaxBytes { + throw DisassemblerError.fileSizeExceeded + + } + bufferFrame = Frame(length: meta.length, bytesInRow: meta.rowBytes) currentFrame = Frame(length: meta.length, bytesInRow: meta.rowBytes) apngMeta = meta diff --git a/APNGKit/Frame.swift b/APNGKit/Frame.swift index 4ea1154..43c6cda 100644 --- a/APNGKit/Frame.swift +++ b/APNGKit/Frame.swift @@ -88,8 +88,8 @@ class Frame { var duration: TimeInterval = 0 - init(length: UInt32, bytesInRow: UInt32) { - self.length = Int(length) + init(length: Int, bytesInRow: UInt32) { + self.length = length self.bytesInRow = Int(bytesInRow) self.bytes = UnsafeMutablePointer.allocate(capacity: self.length) From 526b9783f369db377a534d45d65f35c3fe26b240 Mon Sep 17 00:00:00 2001 From: onevcat Date: Thu, 29 Aug 2019 11:18:51 +0900 Subject: [PATCH 2/2] Add test case for overflow --- APNGKit.xcodeproj/project.pbxproj | 7 +++++++ APNGKitTests/APNGImageTests.swift | 5 +++++ TestImages/malformed-size.apng | Bin 0 -> 98087 bytes 3 files changed, 12 insertions(+) create mode 100644 TestImages/malformed-size.apng diff --git a/APNGKit.xcodeproj/project.pbxproj b/APNGKit.xcodeproj/project.pbxproj index d50a8ed..e9c3081 100644 --- a/APNGKit.xcodeproj/project.pbxproj +++ b/APNGKit.xcodeproj/project.pbxproj @@ -48,6 +48,8 @@ 4B7D4ED61B9559BF005C0598 /* filter_neon_intrinsics.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B7D4ED41B9559BF005C0598 /* filter_neon_intrinsics.c */; }; 4B7D4ED71B9559BF005C0598 /* filter_neon.S in Sources */ = {isa = PBXBuildFile; fileRef = 4B7D4ED51B9559BF005C0598 /* filter_neon.S */; }; 4B7D4ED91B955CBF005C0598 /* arm_init.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B7D4ED81B955CBF005C0598 /* arm_init.c */; }; + 4BA1EFA7231767BE00D6D06C /* malformed-size.apng in Resources */ = {isa = PBXBuildFile; fileRef = 4BA1EFA6231767BD00D6D06C /* malformed-size.apng */; }; + 4BA1EFA8231767BE00D6D06C /* malformed-size.apng in Resources */ = {isa = PBXBuildFile; fileRef = 4BA1EFA6231767BD00D6D06C /* malformed-size.apng */; }; 4BF022041B94442800F00CDE /* APNGImageViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BF022031B94442800F00CDE /* APNGImageViewTests.swift */; }; B25269641E8FD9840096A0A7 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = B25269631E8FD9840096A0A7 /* libz.tbd */; }; B25269661E8FDA090096A0A7 /* GCDTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B19504F1E6D21670047B7DE /* GCDTimer.swift */; }; @@ -185,6 +187,7 @@ 4B7D4ED41B9559BF005C0598 /* filter_neon_intrinsics.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = filter_neon_intrinsics.c; sourceTree = ""; }; 4B7D4ED51B9559BF005C0598 /* filter_neon.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = filter_neon.S; sourceTree = ""; }; 4B7D4ED81B955CBF005C0598 /* arm_init.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = arm_init.c; sourceTree = ""; }; + 4BA1EFA6231767BD00D6D06C /* malformed-size.apng */ = {isa = PBXFileReference; lastKnownFileType = file; name = "malformed-size.apng"; path = "TestImages/malformed-size.apng"; sourceTree = SOURCE_ROOT; }; 4BF022031B94442800F00CDE /* APNGImageViewTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = APNGImageViewTests.swift; sourceTree = ""; }; B252695A1E8FD8EA0096A0A7 /* APNGKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = APNGKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 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 @@ D1614E1C1B91EDD700050104 /* TestImages */ = { isa = PBXGroup; children = ( + 4BA1EFA6231767BD00D6D06C /* malformed-size.apng */, 4B5DF6831B99718C00C4D421 /* demo.png */, D187FEE81B934F1B0013372D /* pyani.apng */, D190199F1B93351300E16EDB /* elephant_apng.apng */, @@ -575,6 +579,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, Base, ); @@ -606,6 +611,7 @@ buildActionMask = 2147483647; files = ( D1614E251B91EDE200050104 /* over_previous.apng in Resources */, + 4BA1EFA7231767BE00D6D06C /* malformed-size.apng in Resources */, D1614E331B91EE0000050104 /* minimalAPNG.apng in Resources */, D19019A01B93351400E16EDB /* elephant_apng.apng in Resources */, D1614E261B91EDE200050104 /* spinfox.apng in Resources */, @@ -630,6 +636,7 @@ buildActionMask = 2147483647; files = ( B25310201E90AA3200A65CEA /* ball.apng in Resources */, + 4BA1EFA8231767BE00D6D06C /* malformed-size.apng in Resources */, B253101F1E90AA3200A65CEA /* minimalAPNG.apng in Resources */, B253101D1E90AA3200A65CEA /* elephant_apng.apng in Resources */, B25310231E90AA3200A65CEA /* over_previous.apng in Resources */, diff --git a/APNGKitTests/APNGImageTests.swift b/APNGKitTests/APNGImageTests.swift index 5370535..b9e8f1a 100644 --- a/APNGKitTests/APNGImageTests.swift +++ b/APNGKitTests/APNGImageTests.swift @@ -198,6 +198,11 @@ class APNGImageTests: XCTestCase { let image = APNGImage(named: "", in: .testBundle) XCTAssertNil(image, "Empty string should result in nil") } + + func testOverflowImage() { + let image = APNGImage(named: "malformed-size", in: .testBundle) + XCTAssertNil(image) + } } private extension CocoaImage { diff --git a/TestImages/malformed-size.apng b/TestImages/malformed-size.apng new file mode 100644 index 0000000000000000000000000000000000000000..48c75daa66790ba21760d22030906554d1d4c4e5 GIT binary patch literal 98087 zcmeI(KTBIt7zg01Acla@p@T{*n2r|x2-P-410tnlS7~wa3%JIuL%|Q=5ITuM?cAZD zaduF$NQaQ2lV89^y+>V~iVz{W?{h-#pXBCn-sf!L{eAnivN%?rEN59ZR$Hom&Pw@J zekcv+r$+hwZ@OFmQeV!`L-~8;WbyS}exBU8|13S5kGn&-X1Rh*!%EOlK;7_%};;;0RjXF5FkK+ z009C7`d2`bU)Kf!0t5&UAV7cs0RjXF5C|q9$scUPl}msC0RjXF5FkK+009Ew1tj_V zw`s%52oNAZfB*pk1PBlyK%lS!lKh3;T7?lHK!5-N0t5&UAV7csfhPz^@`vx)06>5M z0RjXF5FkK+009Eg1SI*R?YMdg5FkK+009C72oNAZAi97g{}Z|>JW7B70RjXF5FkK+ z009C7dLtmo-y27>5FkK+009C72oNAZfB=EP7LeqR-m;;70t5&UAV7cs0RjXF5C|tA z$scaZ6-4w&+bo&@ z0RjXF5FkK+009C72=rJ$l0SIIhVlszAV7cs0RjXF5FkJxo`58OyggSj0RjXF5FkK+ z009C72*ehUBb;HfB*pk1PBlyK!5-N0tAXIAk81UX+!k{2oNAZfB*pk1PBly5KusxKj5Y- znE(L-1PBlyK!5-N0t7+}Nb?uD?L%z@2oNAZfB*pk1PBly(5C|TY5vXG@lIM`?c+-I I=liwoTYf7zt^fc4 literal 0 HcmV?d00001