From c7f9d54705f617e14a415346a2c8f7ce199091c7 Mon Sep 17 00:00:00 2001 From: Dmitry Pentin Date: Thu, 14 Apr 2022 14:01:01 +0300 Subject: [PATCH 1/5] Fixed string exif value corner case null ref exception --- .../Profiles/Exif/ExifEncodedStringHelpers.cs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs index 5fd613b1f..6e697029e 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs @@ -79,16 +79,8 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif return CharacterCodeBytesLength + count; } - public static unsafe int Write(Encoding encoding, string value, Span destination) - { - fixed (char* c = value) - { - fixed (byte* b = destination) - { - return encoding.GetBytes(c, value.Length, b, destination.Length); - } - } - } + public static unsafe int Write(Encoding encoding, string value, Span destination) => + encoding.GetBytes(value.AsSpan(), destination); private static bool TryDetect(ReadOnlySpan buffer, out CharacterCode code) { From 210945f93909ab903e08456ef51a964841127b43 Mon Sep 17 00:00:00 2001 From: Dmitry Pentin Date: Thu, 14 Apr 2022 15:01:54 +0300 Subject: [PATCH 2/5] Fixed compilation error for older frameworks --- .../Profiles/Exif/ExifEncodedStringHelpers.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs index 6e697029e..4dc7f8398 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs @@ -79,8 +79,20 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif return CharacterCodeBytesLength + count; } - public static unsafe int Write(Encoding encoding, string value, Span destination) => - encoding.GetBytes(value.AsSpan(), destination); + public static unsafe int Write(Encoding encoding, string value, Span destination) +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER || NET + => encoding.GetBytes(value.AsSpan(), destination); +#else + { + fixed (char* c = value) + { + fixed (byte* b = destination) + { + return encoding.GetBytes(c, value.Length, b, destination.Length); + } + } + } +#endif private static bool TryDetect(ReadOnlySpan buffer, out CharacterCode code) { From 55d01f231f840f3d57e997be43040e85fb3dc205 Mon Sep 17 00:00:00 2001 From: Dmitry Pentin Date: Thu, 14 Apr 2022 15:03:59 +0300 Subject: [PATCH 3/5] Added guard clause of empty exif strings --- .../Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs index 4dc7f8398..4ec9b3267 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs @@ -84,6 +84,11 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif => encoding.GetBytes(value.AsSpan(), destination); #else { + if (value.Length == 0) + { + return 0; + } + fixed (char* c = value) { fixed (byte* b = destination) From d1c6e5042900dbbe8668e82e3213764453506b76 Mon Sep 17 00:00:00 2001 From: Dmitry Pentin Date: Fri, 15 Apr 2022 12:08:58 +0300 Subject: [PATCH 4/5] Added test image --- .../Formats/Jpg/JpegDecoderTests.Images.cs | 1 + .../Formats/Jpg/JpegEncoderTests.Metadata.cs | 33 +++++++++++++++++++ .../Formats/Jpg/JpegEncoderTests.cs | 2 +- tests/ImageSharp.Tests/TestImages.cs | 1 + ...ssue2087-exif-null-reference-on-encode.jpg | 3 ++ 5 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.Metadata.cs create mode 100644 tests/Images/Input/Jpg/issues/Issue2087-exif-null-reference-on-encode.jpg diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs index 70cbc3af7..60439bc3d 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs @@ -33,6 +33,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg TestImages.Jpeg.Issues.ExifGetString750Load, TestImages.Jpeg.Issues.ExifGetString750Transform, TestImages.Jpeg.Issues.BadSubSampling1076, + TestImages.Jpeg.Issues.ValidExifArgumentNullExceptionOnEncode, // LibJpeg can open this despite the invalid density units. TestImages.Jpeg.Issues.Fuzz.ArgumentOutOfRangeException825B, diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.Metadata.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.Metadata.cs new file mode 100644 index 000000000..46ac23be1 --- /dev/null +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.Metadata.cs @@ -0,0 +1,33 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.IO; +using SixLabors.ImageSharp.Formats.Jpeg; +using SixLabors.ImageSharp.PixelFormats; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Formats.Jpg +{ + [Trait("Format", "Jpg")] + public partial class JpegEncoderTests + { + [Theory] + [WithFile(TestImages.Jpeg.Issues.ValidExifArgumentNullExceptionOnEncode, PixelTypes.Rgba32)] + public void Encode_WithValidExifProfile_DoesNotThrowException(TestImageProvider provider) + where TPixel : unmanaged, IPixel + { + Exception exception = Record.Exception(() => + { + var encoder = new JpegEncoder(); + var stream = new MemoryStream(); + + using Image image = provider.GetImage(JpegDecoder); + image.Save(stream, encoder); + }); + + Assert.Null(exception); + } + } +} diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs index 18eae9fbd..d860836e0 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs @@ -20,7 +20,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Jpg { [Trait("Format", "Jpg")] - public class JpegEncoderTests + public partial class JpegEncoderTests { private static JpegEncoder JpegEncoder => new(); diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 07aff6fc1..4ea740266 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -264,6 +264,7 @@ namespace SixLabors.ImageSharp.Tests public const string InvalidIptcTag = "Jpg/issues/Issue1942InvalidIptcTag.jpg"; public const string Issue2057App1Parsing = "Jpg/issues/Issue2057-App1Parsing.jpg"; public const string ExifNullArrayTag = "Jpg/issues/issue-2056-exif-null-array.jpg"; + public const string ValidExifArgumentNullExceptionOnEncode = "Jpg/issues/Issue2087-exif-null-reference-on-encode.jpg"; public static class Fuzz { diff --git a/tests/Images/Input/Jpg/issues/Issue2087-exif-null-reference-on-encode.jpg b/tests/Images/Input/Jpg/issues/Issue2087-exif-null-reference-on-encode.jpg new file mode 100644 index 000000000..e95ef7a73 --- /dev/null +++ b/tests/Images/Input/Jpg/issues/Issue2087-exif-null-reference-on-encode.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4d41a41180a3371d0c4a724b40a4c86f6f975dab6be9da96964a484818770394 +size 30715 From cde4a88c22d461375aabc4dd632dd96c154b88e5 Mon Sep 17 00:00:00 2001 From: Dmitry Pentin Date: Fri, 15 Apr 2022 12:13:57 +0300 Subject: [PATCH 5/5] Removed invalid image from test suite --- tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs | 1 - .../ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.Metadata.cs | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs index 60439bc3d..70cbc3af7 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs @@ -33,7 +33,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg TestImages.Jpeg.Issues.ExifGetString750Load, TestImages.Jpeg.Issues.ExifGetString750Transform, TestImages.Jpeg.Issues.BadSubSampling1076, - TestImages.Jpeg.Issues.ValidExifArgumentNullExceptionOnEncode, // LibJpeg can open this despite the invalid density units. TestImages.Jpeg.Issues.Fuzz.ArgumentOutOfRangeException825B, diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.Metadata.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.Metadata.cs index 46ac23be1..2bbce6cb1 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.Metadata.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.Metadata.cs @@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg public void Encode_WithValidExifProfile_DoesNotThrowException(TestImageProvider provider) where TPixel : unmanaged, IPixel { - Exception exception = Record.Exception(() => + Exception ex = Record.Exception(() => { var encoder = new JpegEncoder(); var stream = new MemoryStream(); @@ -27,7 +27,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg image.Save(stream, encoder); }); - Assert.Null(exception); + Assert.Null(ex); } } }