From bfc90878badbf9fa469a8b328bf1b0d29d8b5f95 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 5 Oct 2017 23:56:43 +1100 Subject: [PATCH 1/2] Handle corrupted data portions. Fix #358 --- src/ImageSharp/Formats/Png/PngDecoderCore.cs | 13 ++++++++++++- tests/ImageSharp.Tests/TestImages.cs | 1 + tests/Images/Input/Png/big-corrupted-chunk.png | Bin 0 -> 9195 bytes 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 tests/Images/Input/Png/big-corrupted-chunk.png diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index 3bca4b261..7149b74d8 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -1124,12 +1124,23 @@ namespace SixLabors.ImageSharp.Formats.Png { var chunk = new PngChunk(); this.ReadChunkLength(chunk); - if (chunk.Length < 0) + + if (chunk.Length == -1) { + // IEND return null; } + if (chunk.Length < 0 || chunk.Length > this.currentStream.Length - this.currentStream.Position) + { + // Not a valid chunk so we skip back all but one of the four bytes we have just read. + // That lets us read one byte at a time until we reach a known chunk. + this.currentStream.Position -= 3; + return chunk; + } + this.ReadChunkType(chunk); + if (chunk.Type == PngChunkTypes.Data) { return chunk; diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index dbcacb4f3..8af9d170b 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -20,6 +20,7 @@ namespace SixLabors.ImageSharp.Tests public const string Blur = "Png/blur.png"; public const string Indexed = "Png/indexed.png"; public const string Splash = "Png/splash.png"; + public const string CorruptedChunk = "Png/big-corrupted-chunk.png"; public const string Cross = "Png/cross.png"; public const string Powerpoint = "Png/pp.png"; public const string SplashInterlaced = "Png/splash-interlaced.png"; diff --git a/tests/Images/Input/Png/big-corrupted-chunk.png b/tests/Images/Input/Png/big-corrupted-chunk.png new file mode 100644 index 0000000000000000000000000000000000000000..83026897717a00976c0851e2a7b693e4f7fdaec5 GIT binary patch literal 9195 zcmbVybx>T*wl6xk2Mad11cn)$!8Jf|cXwxShu{H1f&>U2Jh%l9!QCymyAxb5Ip=)$ zy+3ZgSs6)HI5>Fh7aE9)@ba}sfPeYI zk-AA~yQw)@x_O$wEa1eX z`ail}T0%6|Zf?#{c6LusPmm`k$O&fkg5~FD2XnA}KQS2>dJ2#MH^%O^D{j(to?);H;qV-+~=o{}ZT}kgs}=EIWqAMi`;{&z)x8DFe{D#2`CCdI^F(#g!- z!NSo^R#J%OWdvkyV-Dpowcs{4H-oTon7_DeX~AW|X2QkE^Fr~PTXOMnLO6N&|B>@Q z;rYeIdBG4c7r%tK7z854BgQ8#CdMZw&BrG##t9LZ`UflP=;~(TXlC(`Zkrd~|G{$p zuUM!A%)-RY38wDkWdBbVC|f(ZIk{RpIRhmm{?0l#h#SbHW#ee>2u~8s_8x{8yx*HvfYa|8EiaH{SgJH-hXhMzQ}*m;Wn${^@$j$-m@(7sE^Azst$O z@uh}fFU1nOcHjL{v}m%DV(MP=hx#aP>KgSwJ$!^LqhB$R=7m;cR3vegbAcXO89z8_R6lrwslf*8`qC+y?p zkk@R{(%lbRlFlWCcF8ChD431{@C%fn=sxyK5%3rkp+ckQI(^ST+s`;;l)f9M)y zP<#oM)JUG2o3X_HeEK2!>m3f}tYoOI9n|H0q>?fh@9T~!YM)kxSrge~Dr}+J+7#(H zSuT=8o{~2#y06psjPH$jE-EyCLFdb;N;w~W#&jxN2~e@M)UJW35g$=ea4`LSgzvkx z0s^zT4<`@|#bdU?BOcY9nsHMMWbMqZCnVzf8guowpnyV1KmBWY z>XmiRPa)pd2Ur`7SU20ze@36p>{~Sh*$R1B^#$FuS=|U(w*K6dzT0_YbkpmP2@v9& zYrmorBRrg{`m&Sh@`FT&h9M&?T;v8Wu#1UHT~3?rwXNko=528%Gsa!IKFH}^BaMaxSP3j0`&eL2c+QJCpvElbC4-i`Vk%v_&y?0Hf@ z85k(`VauZ8{A^xI`60dI=7VA-?LH|;&dy?wv`o00S6bVB&>kEFA>nEs#%e^dLF{ce z-p7#rV=K_FzYfu0sT$t?mcvDYnKf!_58f4UfViB8Lxqkz30d$e>sHNC7TWkVBFVg` zB_gU5O$)@=m?}OBd!_Ju%Xy;P)W!74{6gkvh>qTu##yuG`tboOrW=2!i`Q|dwudl4 zM;D3{Q#9%#N|@FeYZ5B@Yx_()`%Mc8b{{Rii?0#DrpIzZ=t*s?#ZVL|NwapfH*D#e zHjJI~iI&JUM2*b;c}@MyOE(-FrlENjkAFl+IH6M`@#7GPL%dvSBse=aGqMUZeQx|L z;LSqr*3#Ov)rx}@a+iiaK&w@O+fu)Fjl<$Q#;d{0;nAv@a=mTknK#g#QZ0CM9`Ysf!eUN)lne)B~v&> zvc>G}hd;1`8w8@?qVTT;m$!O?;Dv>pkieqfd6gv_`MIS-mJYgQ4F|KMB^p9%z9Dou z{V9l6h-FBg6nM&kzm7dvIZ9vOcH+&v_G;N+%on`#A|k&%Ykn8&E}avJMIMi&jL;3H zit(RGkmz`LL(`2Mi*miZdOnBgbG=Wmzj=0NuG+5l=k4k3()7Nj%4FkYy*mX_97+f& zpy$o2>I6XOaJo=l997fM#|q&=z(R`r9f4~&4i)L_&ik*g4X*k*YWm?rq#lDD>l%Aw z_GV`s%S*VO`8-{`SW@&Aaf*he*gp#Smu~JSy;i9h2wUUZ?≥RPx%zrhhte9xv-) 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 literal 0 HcmV?d00001 From 25647a5afc02c3d2a85eb3551fd27bd63cd6f821 Mon Sep 17 00:00:00 2001 From: JimBobSquarePants Date: Fri, 6 Oct 2017 09:00:25 +1100 Subject: [PATCH 2/2] Add missing test for #359 --- tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs | 1 + tests/ImageSharp.Tests/TestImages.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs index fc759fb56..d39d0651d 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs @@ -24,6 +24,7 @@ namespace SixLabors.ImageSharp.Tests TestImages.Png.Splash, TestImages.Png.Indexed, TestImages.Png.FilterVar, TestImages.Png.Bad.ChunkLength1, + TestImages.Png.Bad.CorruptedChunk, TestImages.Png.VimImage1, TestImages.Png.VersioningImage1, diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 8af9d170b..c2a6ed1ad 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -20,7 +20,6 @@ namespace SixLabors.ImageSharp.Tests public const string Blur = "Png/blur.png"; public const string Indexed = "Png/indexed.png"; public const string Splash = "Png/splash.png"; - public const string CorruptedChunk = "Png/big-corrupted-chunk.png"; public const string Cross = "Png/cross.png"; public const string Powerpoint = "Png/pp.png"; public const string SplashInterlaced = "Png/splash-interlaced.png"; @@ -57,6 +56,7 @@ namespace SixLabors.ImageSharp.Tests // Odd chunk lengths public const string ChunkLength1 = "Png/chunklength1.png"; public const string ChunkLength2 = "Png/chunklength2.png"; + public const string CorruptedChunk = "Png/big-corrupted-chunk.png"; } public static readonly string[] All =