From b133dc79401487448fb58855bf1c06531610a19e Mon Sep 17 00:00:00 2001 From: Johannes Bildstein Date: Fri, 11 May 2018 21:05:26 +0200 Subject: [PATCH 1/8] fix calculation of ICC profile ID and add tests for it --- .../MetaData/Profiles/ICC/IccProfile.cs | 44 ++++++++++----- .../MetaData/Profiles/ICC/IccProfileTests.cs | 39 +++++++++++++ .../TestDataIcc/IccTestDataProfiles.cs | 55 +++++++++++-------- 3 files changed, 101 insertions(+), 37 deletions(-) create mode 100644 tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccProfileTests.cs diff --git a/src/ImageSharp/MetaData/Profiles/ICC/IccProfile.cs b/src/ImageSharp/MetaData/Profiles/ICC/IccProfile.cs index df85b2ab8..82f16683b 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/IccProfile.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/IccProfile.cs @@ -108,7 +108,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc #if !NETSTANDARD1_1 /// - /// Calculates the MD5 hash value of an ICC profile header + /// Calculates the MD5 hash value of an ICC profile /// /// The data of which to calculate the hash value /// The calculated hash @@ -117,22 +117,38 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc Guard.NotNull(data, nameof(data)); Guard.IsTrue(data.Length >= 128, nameof(data), "Data length must be at least 128 to be a valid profile header"); - byte[] header = new byte[128]; - Buffer.BlockCopy(data, 0, header, 0, 128); + const int profileFlagPos = 44; + const int renderingIntentPos = 64; + const int profileIdPos = 84; + + // need to copy some values because they need to be zero for the hashing + byte[] temp = new byte[24]; + Buffer.BlockCopy(data, profileFlagPos, temp, 0, 4); + Buffer.BlockCopy(data, renderingIntentPos, temp, 4, 4); + Buffer.BlockCopy(data, profileIdPos, temp, 8, 16); using (var md5 = MD5.Create()) { - // Zero out some values - Array.Clear(header, 44, 4); // Profile flags - Array.Clear(header, 64, 4); // Rendering Intent - Array.Clear(header, 84, 16); // Profile ID - - // Calculate hash - byte[] hash = md5.ComputeHash(data); - - // Read values from hash - var reader = new IccDataReader(hash); - return reader.ReadProfileId(); + try + { + // Zero out some values + Array.Clear(data, profileFlagPos, 4); + Array.Clear(data, renderingIntentPos, 4); + Array.Clear(data, profileIdPos, 16); + + // Calculate hash + byte[] hash = md5.ComputeHash(data); + + // Read values from hash + var reader = new IccDataReader(hash); + return reader.ReadProfileId(); + } + finally + { + Buffer.BlockCopy(temp, 0, data, profileFlagPos, 4); + Buffer.BlockCopy(temp, 4, data, renderingIntentPos, 4); + Buffer.BlockCopy(temp, 8, data, profileIdPos, 16); + } } } diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccProfileTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccProfileTests.cs new file mode 100644 index 000000000..f49cb6bd8 --- /dev/null +++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccProfileTests.cs @@ -0,0 +1,39 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Icc +{ + public class IccProfileTests + { + +#if !NETSTANDARD1_1 + + [Theory] + [MemberData(nameof(IccTestDataProfiles.ProfileIdTestData), MemberType = typeof(IccTestDataProfiles))] + public void CalculateHash_WithByteArray_CalculatesProfileHash(byte[] data, IccProfileId expected) + { + IccProfileId result = IccProfile.CalculateHash(data); + + Assert.Equal(expected, result); + } + + [Fact] + public void CalculateHash_WithByteArray_DoesNotModifyData() + { + byte[] data = IccTestDataProfiles.Profile_Random_Array; + byte[] copy = new byte[data.Length]; + Buffer.BlockCopy(data, 0, copy, 0, data.Length); + + IccProfileId result = IccProfile.CalculateHash(data); + + Assert.Equal(data, copy); + } + +#endif + + } +} diff --git a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataProfiles.cs b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataProfiles.cs index 3cf66ffed..a5f0ce3fd 100644 --- a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataProfiles.cs +++ b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataProfiles.cs @@ -9,6 +9,27 @@ namespace SixLabors.ImageSharp.Tests { internal static class IccTestDataProfiles { + public static readonly IccProfileId Header_Random_Id_Value = new IccProfileId(0x84A8D460, 0xC716B6F3, 0x9B0E4C3D, 0xAB95F838); + public static readonly IccProfileId Profile_Random_Id_Value = new IccProfileId(0x917D6DE6, 0x84C958D1, 0x3BB0F5BB, 0xADD1134F); + + public static readonly byte[] Header_Random_Id_Array = + { +#if !NETSTANDARD1_1 + 0x84, 0xA8, 0xD4, 0x60, 0xC7, 0x16, 0xB6, 0xF3, 0x9B, 0x0E, 0x4C, 0x3D, 0xAB, 0x95, 0xF8, 0x38, +#else + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +#endif + }; + + public static readonly byte[] Profile_Random_Id_Array = + { +#if !NETSTANDARD1_1 + 0x91, 0x7D, 0x6D, 0xE6, 0x84, 0xC9, 0x58, 0xD1, 0x3B, 0xB0, 0xF5, 0xBB, 0xAD, 0xD1, 0x13, 0x4F, +#else + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +#endif + }; + public static readonly IccProfileHeader Header_Random_Write = CreateHeaderRandomValue( 562, // should be overwritten new IccProfileId(1, 2, 3, 4), // should be overwritten @@ -16,20 +37,13 @@ namespace SixLabors.ImageSharp.Tests public static readonly IccProfileHeader Header_Random_Read = CreateHeaderRandomValue(132, #if !NETSTANDARD1_1 - new IccProfileId(2931428592, 418415738, 3086756963, 2237536530), + Header_Random_Id_Value, #else IccProfileId.Zero, #endif "acsp"); - public static readonly byte[] Header_Random_Array = CreateHeaderRandomArray(132, 0, new byte[] - { -#if !NETSTANDARD1_1 - 0xAE, 0xBA, 0x0C, 0xF0, 0x18, 0xF0, 0x84, 0x7A, 0xB7, 0xFC, 0x2C, 0x63, 0x85, 0x5E, 0x19, 0x12, -#else - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -#endif - }); + public static readonly byte[] Header_Random_Array = CreateHeaderRandomArray(132, 0, Header_Random_Id_Array); public static IccProfileHeader CreateHeaderRandomValue(uint size, IccProfileId id, string fileSignature) { @@ -45,11 +59,7 @@ namespace SixLabors.ImageSharp.Tests DeviceModel = 987654321u, FileSignature = "acsp", Flags = IccProfileFlag.Embedded | IccProfileFlag.Independent, -#if !NETSTANDARD1_1 - Id = new IccProfileId(2931428592, 418415738, 3086756963, 2237536530), -#else - Id = IccProfileId.Zero, -#endif + Id = id, PcsIlluminant = new Vector3(4, 5, 6), PrimaryPlatformSignature = IccPrimaryPlatformType.MicrosoftCorporation, ProfileConnectionSpace = IccColorSpaceType.CieXyz, @@ -94,14 +104,7 @@ namespace SixLabors.ImageSharp.Tests }); } - public static byte[] Profile_Random_Array = ArrayHelper.Concat(CreateHeaderRandomArray(168, 2, new byte[] - { -#if !NETSTANDARD1_1 - 0xA9, 0x71, 0x8F, 0xC1, 0x1E, 0x2D, 0x64, 0x1B, 0x10, 0xF4, 0x7D, 0x6A, 0x5B, 0xF6, 0xAC, 0xB9 -#else - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -#endif - }), + public static byte[] Profile_Random_Array = ArrayHelper.Concat(CreateHeaderRandomArray(168, 2, Profile_Random_Id_Array), new byte[] { 0x00, 0x00, 0x00, 0x00, // tag signature (Unknown) @@ -118,7 +121,7 @@ namespace SixLabors.ImageSharp.Tests public static IccProfile Profile_Random_Val = new IccProfile(CreateHeaderRandomValue(168, #if !NETSTANDARD1_1 - new IccProfileId(0xA9718FC1, 0x1E2D641B, 0x10F47D6A, 0x5BF6ACB9), + Profile_Random_Id_Value, #else IccProfileId.Zero, #endif @@ -128,5 +131,11 @@ namespace SixLabors.ImageSharp.Tests IccTestDataTagDataEntry.Unknown_Val, IccTestDataTagDataEntry.Unknown_Val }); + + public static object[][] ProfileIdTestData = + { + new object[] { Header_Random_Array, Header_Random_Id_Value }, + new object[] { Profile_Random_Array, Profile_Random_Id_Value }, + }; } } From ae8924c392450bcfe4ef5def1b4a2fa4f29ebee8 Mon Sep 17 00:00:00 2001 From: Dirk Lemstra Date: Sat, 19 May 2018 22:45:42 +0200 Subject: [PATCH 2/8] Fixed bug when marking a value as an array. --- src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs index c00eec601..4f28449d6 100644 --- a/src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs +++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs @@ -387,7 +387,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif value = this.ConvertValue(dataType, offsetBuffer, numberOfComponents); } - exifValue = new ExifValue(tag, dataType, value, isArray: value != null && numberOfComponents > 1); + exifValue = new ExifValue(tag, dataType, value, isArray: value != null && numberOfComponents != 1); return true; } From bbf6b22b83731d952b73df649ba08f6b037ea28d Mon Sep 17 00:00:00 2001 From: Dirk Lemstra Date: Mon, 21 May 2018 11:50:04 +0200 Subject: [PATCH 3/8] Added unit test. --- .../MetaData/Profiles/Exif/ExifProfileTests.cs | 16 ++++++++++++++++ tests/ImageSharp.Tests/TestImages.cs | 1 + .../Input/Jpg/issues/Issue520-InvalidCast.jpg | Bin 0 -> 7751 bytes 3 files changed, 17 insertions(+) create mode 100644 tests/Images/Input/Jpg/issues/Issue520-InvalidCast.jpg diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs index d98c61279..3c69b57fd 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs @@ -292,6 +292,22 @@ namespace SixLabors.ImageSharp.Tests } } + [Fact] + public void TestArrayValueWithUnspecifiedSize() + { + // This images contains array in the exif profile that has zero components. + Image image = TestFile.Create(TestImages.Jpeg.Issues.InvalidCast520).CreateImage(); + + ExifProfile profile = image.MetaData.ExifProfile; + Assert.NotNull(profile); + + // Force parsing of the profile. + Assert.Equal(24, profile.Values.Count); + + byte[] bytes = profile.ToByteArray(); + Assert.Equal(495, bytes.Length); + } + private static ExifProfile GetExifProfile() { Image image = TestFile.Create(TestImages.Jpeg.Baseline.Floorplan).CreateImage(); diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 85f12bc80..d261f9497 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -136,6 +136,7 @@ namespace SixLabors.ImageSharp.Tests public const string MultiHuffmanBaseline394 = "Jpg/issues/Issue394-MultiHuffmanBaseline-Speakers.jpg"; public const string NoEoiProgressive517 = "Jpg/issues/Issue517-No-EOI-Progressive.jpg"; public const string BadRstProgressive518 = "Jpg/issues/Issue518-Bad-RST-Progressive.jpg"; + public const string InvalidCast520 = "Jpg/issues/Issue520-InvalidCast.jpg"; } public static readonly string[] All = Baseline.All.Concat(Progressive.All).ToArray(); diff --git a/tests/Images/Input/Jpg/issues/Issue520-InvalidCast.jpg b/tests/Images/Input/Jpg/issues/Issue520-InvalidCast.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bf7c4c72a412dcec48d486dde63bb70ebd7e3bc0 GIT binary patch literal 7751 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 Date: Tue, 22 May 2018 16:56:32 +0200 Subject: [PATCH 4/8] add check for ICC profile validity --- .../Jpeg/GolangPort/OrigJpegDecoderCore.cs | 5 +++ .../Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs | 7 +++- .../MetaData/Profiles/ICC/IccProfile.cs | 14 ++++++++ .../MetaData/Profiles/ICC/IccProfileTests.cs | 10 ++++++ .../TestDataIcc/IccTestDataProfiles.cs | 32 +++++++++++++++++++ 5 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs index 875f16ec2..998b84665 100644 --- a/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs @@ -412,6 +412,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort } this.InitDerivedMetaDataProperties(); + + if (this.MetaData.IccProfile?.CheckIsValid() == false) + { + this.MetaData.IccProfile = null; + } } /// diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs index df803a920..a04e6ea69 100644 --- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs @@ -255,7 +255,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort { // It's highly unlikely that APPn related data will be found after the SOS marker // We should have gathered everything we need by now. - return; + break; } case PdfJsJpegConstants.Markers.DHT: @@ -334,6 +334,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort // Read on. fileMarker = FindNextFileMarker(this.markerBuffer, this.InputStream); } + + if (this.MetaData.IccProfile?.CheckIsValid() == false) + { + this.MetaData.IccProfile = null; + } } /// diff --git a/src/ImageSharp/MetaData/Profiles/ICC/IccProfile.cs b/src/ImageSharp/MetaData/Profiles/ICC/IccProfile.cs index 82f16683b..ee4e9ce1d 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/IccProfile.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/IccProfile.cs @@ -165,6 +165,20 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc Buffer.BlockCopy(bytes, 0, this.data, currentLength, bytes.Length); } + /// + /// Checks for signs of a corrupt profile. + /// + /// This is not an absolute proof of validity but should weed out most corrupt data. + /// True if the profile is valid; False otherwise + public bool CheckIsValid() + { + return Enum.IsDefined(typeof(IccColorSpaceType), this.Header.DataColorSpace) && + Enum.IsDefined(typeof(IccColorSpaceType), this.Header.ProfileConnectionSpace) && + Enum.IsDefined(typeof(IccRenderingIntent), this.Header.RenderingIntent) && + this.Header.Size >= 128 && + this.Header.Size < 50_000_000; // it's unlikely there is a profile bigger than 50MB + } + /// /// Converts this instance to a byte array. /// diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccProfileTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccProfileTests.cs index f49cb6bd8..2e2c92182 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccProfileTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccProfileTests.cs @@ -35,5 +35,15 @@ namespace SixLabors.ImageSharp.Tests.Icc #endif + [Theory] + [MemberData(nameof(IccTestDataProfiles.ProfileValidityTestData), MemberType = typeof(IccTestDataProfiles))] + public void CheckIsValid_WithProfiles_ReturnsValidity(byte[] data, bool expected) + { + var profile = new IccProfile(data); + + bool result = profile.CheckIsValid(); + + Assert.Equal(expected, result); + } } } diff --git a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataProfiles.cs b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataProfiles.cs index a5f0ce3fd..586bb818d 100644 --- a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataProfiles.cs +++ b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataProfiles.cs @@ -132,10 +132,42 @@ namespace SixLabors.ImageSharp.Tests IccTestDataTagDataEntry.Unknown_Val }); + public static byte[] Header_Corrupt1_Array = + { + 0x81, 0xB1, 0x81, 0xE4, 0x82, 0x16, 0x82, 0x49, 0x82, 0x7B, 0x82, 0xAD, 0x82, 0xDF, 0x83, 0x11, + 0x83, 0x43, 0x83, 0x75, 0x83, 0xA7, 0x83, 0xD8, 0x84, 0x0A, 0x84, 0x3B, 0x84, 0x6C, 0x84, 0x9E, + 0x84, 0xCF, 0x85, 0x00, 0x85, 0x31, 0x85, 0x62, 0x85, 0x93, 0x85, 0xC3, 0x85, 0xF4, 0x86, 0x24, + 0x86, 0x55, 0x86, 0x85, 0x86, 0xB5, 0x86, 0xE6, 0x87, 0x16, 0x87, 0x46, 0x87, 0x76, 0x87, 0xA5, + 0x87, 0xD5, 0x88, 0x05, 0x88, 0x34, 0x88, 0x64, 0x88, 0x93, 0x88, 0xC3, 0x88, 0xF2, 0x89, 0x21, + 0x89, 0x50, 0x89, 0x7F, 0x89, 0xAE, 0x89, 0xDD, 0x8A, 0x0C, 0x8A, 0x3B, 0x8A, 0x69, 0x8A, 0x98, + 0x8A, 0xC6, 0x8A, 0xF5, 0x8B, 0x23, 0x8B, 0x51, 0x8B, 0x7F, 0x8B, 0xAE, 0x8B, 0xDC, 0x8C, 0x09, + 0x8C, 0x37, 0x8C, 0x65, 0x8C, 0x93, 0x8C, 0xC1, 0x8C, 0xEE, 0x8D, 0x1C, 0x8D, 0x49, 0x8D, 0x76, + }; + + public static byte[] Header_Corrupt2_Array = + { + 0x23, 0x74, 0x6D, 0x6D, 0xB1, 0xBC, 0x28, 0xB2, 0x6D, 0x0B, 0xA3, 0x9C, 0x2D, 0x60, 0x6C, 0xB4, + 0x96, 0xF2, 0x31, 0x88, 0x6C, 0x67, 0x8B, 0xA9, 0x35, 0x31, 0x6C, 0x24, 0x81, 0xAE, 0x38, 0x64, + 0x6B, 0xE9, 0x78, 0xEC, 0x3B, 0x28, 0x6B, 0xB7, 0x71, 0x4F, 0x3D, 0x87, 0x6B, 0x8C, 0x6A, 0xC3, + 0x3F, 0x87, 0x6B, 0x68, 0x65, 0x33, 0x41, 0x30, 0x6B, 0x4A, 0x60, 0x8C, 0x42, 0x8C, 0x6B, 0x32, + 0x5C, 0xB8, 0x43, 0xA2, 0x6B, 0x1F, 0x59, 0xA4, 0x44, 0x79, 0x6B, 0x10, 0x57, 0x3B, 0x45, 0x1A, + 0x6B, 0x05, 0x55, 0x68, 0x45, 0x8D, 0x6A, 0xFE, 0x54, 0x15, 0x45, 0xDA, 0x6A, 0xF9, 0x53, 0x2A, + 0x46, 0x16, 0x6A, 0xF5, 0x52, 0x74, 0x46, 0x27, 0x6A, 0xF4, 0x52, 0x43, 0x46, 0x27, 0x6A, 0xF4, + 0x52, 0x43, 0x46, 0x27, 0x6A, 0xF4, 0x52, 0x43, 0x46, 0x27, 0x6A, 0xF4, 0x52, 0x43, 0x46, 0x27, + }; + + public static object[][] ProfileIdTestData = { new object[] { Header_Random_Array, Header_Random_Id_Value }, new object[] { Profile_Random_Array, Profile_Random_Id_Value }, }; + + public static object[][] ProfileValidityTestData = + { + new object[] { Header_Corrupt1_Array, false }, + new object[] { Header_Corrupt2_Array, false }, + new object[] { Header_Random_Array, true }, + }; } } From 74219459890d0e9f67fbdb3e90291fff45757446 Mon Sep 17 00:00:00 2001 From: Anton Firsov Date: Tue, 22 May 2018 17:06:13 +0200 Subject: [PATCH 5/8] Making net471 the first target again, hope it will fix travis --- tests/ImageSharp.Tests/ImageSharp.Tests.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj index 806ac9174..e00f3ed71 100644 --- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj +++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj @@ -1,6 +1,6 @@  - netcoreapp2.1;netcoreapp2.0;net471;net47;net462 + net471;netcoreapp2.0;netcoreapp2.1;net47;net462 True 7.2 full @@ -52,4 +52,4 @@ - \ No newline at end of file + From 72c55484eb886c3450bbeb590621a5674e0d42ef Mon Sep 17 00:00:00 2001 From: Johannes Bildstein Date: Tue, 22 May 2018 17:38:43 +0200 Subject: [PATCH 6/8] int ToByteArray, use buffer if available instead of parsing and writing the profile --- .../MetaData/Profiles/ICC/IccProfile.cs | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/ImageSharp/MetaData/Profiles/ICC/IccProfile.cs b/src/ImageSharp/MetaData/Profiles/ICC/IccProfile.cs index ee4e9ce1d..52b8e43da 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/IccProfile.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/IccProfile.cs @@ -52,17 +52,12 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// by making a copy from another ICC profile. /// /// The other ICC profile, where the clone should be made from. - /// is null.> + /// is null.> public IccProfile(IccProfile other) { Guard.NotNull(other, nameof(other)); - // TODO: Do we need to copy anything else? - if (other.data != null) - { - this.data = new byte[other.data.Length]; - Buffer.BlockCopy(other.data, 0, this.data, 0, other.data.Length); - } + this.data = other.ToByteArray(); } /// @@ -185,8 +180,17 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// The public byte[] ToByteArray() { - var writer = new IccWriter(); - return writer.Write(this); + if (this.data != null) + { + byte[] copy = new byte[this.data.Length]; + Buffer.BlockCopy(this.data, 0, copy, 0, copy.Length); + return copy; + } + else + { + var writer = new IccWriter(); + return writer.Write(this); + } } private void InitializeHeader() From 800ee0985fb09eced70b74b41d3bd9d2e5afc95d Mon Sep 17 00:00:00 2001 From: Johannes Bildstein Date: Tue, 22 May 2018 22:32:05 +0200 Subject: [PATCH 7/8] add a few guards around reading ICC profile data --- .../Profiles/ICC/DataReader/IccDataReader.cs | 10 +++- .../MetaData/Profiles/ICC/IccReader.cs | 47 ++++++++++++++----- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.cs index c4a6a9039..d6df9e666 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; using System.Text; namespace SixLabors.ImageSharp.MetaData.Profiles.Icc @@ -11,7 +10,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// internal sealed partial class IccDataReader { - private static readonly bool IsLittleEndian = BitConverter.IsLittleEndian; private static readonly Encoding AsciiEncoding = Encoding.GetEncoding("ASCII"); /// @@ -34,6 +32,14 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc this.data = data; } + /// + /// Gets the length in bytes of the raw data + /// + public int DataLength + { + get { return this.data.Length; } + } + /// /// Sets the reading position to the given value /// diff --git a/src/ImageSharp/MetaData/Profiles/ICC/IccReader.cs b/src/ImageSharp/MetaData/Profiles/ICC/IccReader.cs index ca7c73620..f6ed9325a 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/IccReader.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/IccReader.cs @@ -84,27 +84,36 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc private IccTagDataEntry[] ReadTagData(IccDataReader reader) { IccTagTableEntry[] tagTable = this.ReadTagTable(reader); - var entries = new IccTagDataEntry[tagTable.Length]; + var entries = new List(tagTable.Length); var store = new Dictionary(); - for (int i = 0; i < tagTable.Length; i++) + + foreach (IccTagTableEntry tag in tagTable) { IccTagDataEntry entry; - uint offset = tagTable[i].Offset; - if (store.ContainsKey(offset)) + if (store.ContainsKey(tag.Offset)) { - entry = store[offset]; + entry = store[tag.Offset]; } else { - entry = reader.ReadTagDataEntry(tagTable[i]); - store.Add(offset, entry); + try + { + entry = reader.ReadTagDataEntry(tag); + } + catch + { + // Ignore tags that could not be read + continue; + } + + store.Add(tag.Offset, entry); } - entry.TagSignature = tagTable[i].Signature; - entries[i] = entry; + entry.TagSignature = tag.Signature; + entries.Add(entry); } - return entries; + return entries.ToArray(); } private IccTagTableEntry[] ReadTagTable(IccDataReader reader) @@ -112,17 +121,29 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc reader.SetIndex(128); // An ICC header is 128 bytes long uint tagCount = reader.ReadUInt32(); - var table = new IccTagTableEntry[tagCount]; + // Prevent creating huge arrays because of corrupt profiles. + // A normal profile usually has 5-15 entries + if (tagCount > 100) + { + return new IccTagTableEntry[0]; + } + + var table = new List((int)tagCount); for (int i = 0; i < tagCount; i++) { uint tagSignature = reader.ReadUInt32(); uint tagOffset = reader.ReadUInt32(); uint tagSize = reader.ReadUInt32(); - table[i] = new IccTagTableEntry((IccProfileTag)tagSignature, tagOffset, tagSize); + + // Exclude entries that have nonsense values and could cause exceptions further on + if (tagOffset < reader.DataLength && tagSize < reader.DataLength - 128) + { + table.Add(new IccTagTableEntry((IccProfileTag)tagSignature, tagOffset, tagSize)); + } } - return table; + return table.ToArray(); } } } From df7fa403bbb00e3fc03cd7c27a5282857d686fef Mon Sep 17 00:00:00 2001 From: Johannes Bildstein Date: Wed, 23 May 2018 13:22:28 +0200 Subject: [PATCH 8/8] move ICC validity check to InitDerivedMetaDataProperties --- .../Jpeg/GolangPort/GolangJpegDecoderCore.cs | 10 +++++----- .../Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs | 20 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/GolangJpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/GolangJpegDecoderCore.cs index 0ee704c9a..86f97d224 100644 --- a/src/ImageSharp/Formats/Jpeg/GolangPort/GolangJpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/GolangPort/GolangJpegDecoderCore.cs @@ -413,11 +413,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort } this.InitDerivedMetaDataProperties(); - - if (this.MetaData.IccProfile?.CheckIsValid() == false) - { - this.MetaData.IccProfile = null; - } } /// @@ -455,6 +450,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort this.MetaData.VerticalResolution = verticalValue; } } + + if (this.MetaData.IccProfile?.CheckIsValid() == false) + { + this.MetaData.IccProfile = null; + } } /// diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs index 24968fd35..752e72dd2 100644 --- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs @@ -196,7 +196,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort where TPixel : struct, IPixel { this.ParseStream(stream); - this.AssignResolution(); + this.InitDerivedMetaDataProperties(); return this.PostProcessIntoImage(); } @@ -207,7 +207,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort public IImageInfo Identify(Stream stream) { this.ParseStream(stream, true); - this.AssignResolution(); + this.InitDerivedMetaDataProperties(); return new ImageInfo(new PixelTypeInfo(this.BitsPerPixel), this.ImageWidth, this.ImageHeight, this.MetaData); } @@ -266,7 +266,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort { // It's highly unlikely that APPn related data will be found after the SOS marker // We should have gathered everything we need by now. - break; + return; } case JpegConstants.Markers.DHT: @@ -345,11 +345,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort // Read on. fileMarker = FindNextFileMarker(this.markerBuffer, this.InputStream); } - - if (this.MetaData.IccProfile?.CheckIsValid() == false) - { - this.MetaData.IccProfile = null; - } } /// @@ -400,9 +395,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort } /// - /// Assigns the horizontal and vertical resolution to the image if it has a JFIF header or EXIF metadata. + /// Assigns derived metadata properties to , eg. horizontal and vertical resolution if it has a JFIF header. /// - private void AssignResolution() + private void InitDerivedMetaDataProperties() { if (this.jFif.XDensity > 0 && this.jFif.YDensity > 0) { @@ -425,6 +420,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort this.MetaData.VerticalResolution = verticalValue; } } + + if (this.MetaData.IccProfile?.CheckIsValid() == false) + { + this.MetaData.IccProfile = null; + } } ///