Browse Source

More early returns and renaming

pull/2589/head
James Jackson-South 3 years ago
parent
commit
091cb1eabc
  1. 33
      src/ImageSharp/Formats/Png/PngDecoderCore.cs
  2. 4
      tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs

33
src/ImageSharp/Formats/Png/PngDecoderCore.cs

@ -1395,7 +1395,7 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
ReadOnlySpan<byte> compressedData = data[(zeroIndex + 2)..]; ReadOnlySpan<byte> compressedData = data[(zeroIndex + 2)..];
if (this.TryUncompressTextData(compressedData, PngConstants.Encoding, out string? uncompressed) if (this.TryDecompressTextData(compressedData, PngConstants.Encoding, out string? uncompressed)
&& !TryReadTextChunkMetadata(baseMetadata, name, uncompressed)) && !TryReadTextChunkMetadata(baseMetadata, name, uncompressed))
{ {
metadata.TextData.Add(new PngTextData(name, uncompressed, string.Empty, string.Empty)); metadata.TextData.Add(new PngTextData(name, uncompressed, string.Empty, string.Empty));
@ -1539,19 +1539,19 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
ReadOnlySpan<byte> compressedData = data[(zeroIndex + 2)..]; ReadOnlySpan<byte> compressedData = data[(zeroIndex + 2)..];
if (this.TryUncompressZlibData(compressedData, out byte[] iccpProfileBytes)) if (this.TryDecompressZlibData(compressedData, out byte[] iccpProfileBytes))
{ {
metadata.IccProfile = new IccProfile(iccpProfileBytes); metadata.IccProfile = new IccProfile(iccpProfileBytes);
} }
} }
/// <summary> /// <summary>
/// Tries to un-compress zlib compressed data. /// Tries to decompress zlib compressed data.
/// </summary> /// </summary>
/// <param name="compressedData">The compressed data.</param> /// <param name="compressedData">The compressed data.</param>
/// <param name="uncompressedBytesArray">The uncompressed bytes array.</param> /// <param name="uncompressedBytesArray">The uncompressed bytes array.</param>
/// <returns>True, if de-compressing was successful.</returns> /// <returns>True, if de-compressing was successful.</returns>
private unsafe bool TryUncompressZlibData(ReadOnlySpan<byte> compressedData, out byte[] uncompressedBytesArray) private unsafe bool TryDecompressZlibData(ReadOnlySpan<byte> compressedData, out byte[] uncompressedBytesArray)
{ {
fixed (byte* compressedDataBase = compressedData) fixed (byte* compressedDataBase = compressedData)
{ {
@ -1688,7 +1688,7 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
{ {
ReadOnlySpan<byte> compressedData = data[dataStartIdx..]; ReadOnlySpan<byte> compressedData = data[dataStartIdx..];
if (this.TryUncompressTextData(compressedData, PngConstants.TranslatedEncoding, out string? uncompressed)) if (this.TryDecompressTextData(compressedData, PngConstants.TranslatedEncoding, out string? uncompressed))
{ {
pngMetadata.TextData.Add(new PngTextData(keyword, uncompressed, language, translatedKeyword)); pngMetadata.TextData.Add(new PngTextData(keyword, uncompressed, language, translatedKeyword));
} }
@ -1711,9 +1711,9 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
/// <param name="encoding">The string encoding to use.</param> /// <param name="encoding">The string encoding to use.</param>
/// <param name="value">The uncompressed value.</param> /// <param name="value">The uncompressed value.</param>
/// <returns>The <see cref="bool"/>.</returns> /// <returns>The <see cref="bool"/>.</returns>
private bool TryUncompressTextData(ReadOnlySpan<byte> compressedData, Encoding encoding, [NotNullWhen(true)] out string? value) private bool TryDecompressTextData(ReadOnlySpan<byte> compressedData, Encoding encoding, [NotNullWhen(true)] out string? value)
{ {
if (this.TryUncompressZlibData(compressedData, out byte[] uncompressedData)) if (this.TryDecompressZlibData(compressedData, out byte[] uncompressedData))
{ {
value = encoding.GetString(uncompressedData); value = encoding.GetString(uncompressedData);
return true; return true;
@ -1736,7 +1736,11 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
Span<byte> buffer = stackalloc byte[20]; Span<byte> buffer = stackalloc byte[20];
_ = this.currentStream.Read(buffer, 0, 4); int length = this.currentStream.Read(buffer, 0, 4);
if (length == 0)
{
return 0;
}
if (this.TryReadChunk(buffer, out PngChunk chunk)) if (this.TryReadChunk(buffer, out PngChunk chunk))
{ {
@ -1765,7 +1769,11 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
Span<byte> buffer = stackalloc byte[20]; Span<byte> buffer = stackalloc byte[20];
_ = this.currentStream.Read(buffer, 0, 4); int length = this.currentStream.Read(buffer, 0, 4);
if (length == 0)
{
return 0;
}
if (this.TryReadChunk(buffer, out PngChunk chunk)) if (this.TryReadChunk(buffer, out PngChunk chunk))
{ {
@ -1802,8 +1810,9 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
return true; return true;
} }
if (this.currentStream.Position == this.currentStream.Length) if (this.currentStream.Position >= this.currentStream.Length - 1)
{ {
// IEND
chunk = default; chunk = default;
return false; return false;
} }
@ -1820,6 +1829,7 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
// Not a valid chunk so try again until we reach a known chunk. // Not a valid chunk so try again until we reach a known chunk.
if (!this.TryReadChunkLength(buffer, out length)) if (!this.TryReadChunkLength(buffer, out length))
{ {
// IEND
chunk = default; chunk = default;
return false; return false;
} }
@ -1832,10 +1842,11 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
if (this.colorMetadataOnly && type != PngChunkType.Header && type != PngChunkType.Transparency && type != PngChunkType.Palette) if (this.colorMetadataOnly && type != PngChunkType.Header && type != PngChunkType.Transparency && type != PngChunkType.Palette)
{ {
chunk = new PngChunk(length, type); chunk = new PngChunk(length, type);
return true; return true;
} }
// A chunk might report a length that exceeds the length of the stream.
// Take the minimum of the two values to ensure we don't read past the end of the stream.
long position = this.currentStream.Position; long position = this.currentStream.Position;
chunk = new PngChunk( chunk = new PngChunk(
length: (int)Math.Min(length, this.currentStream.Length - position), length: (int)Math.Min(length, this.currentStream.Length - position),

4
tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs

@ -661,8 +661,8 @@ public partial class PngDecoderTests
PngDecoderOptions options = new() { PngCrcChunkHandling = PngCrcChunkHandling.IgnoreData }; PngDecoderOptions options = new() { PngCrcChunkHandling = PngCrcChunkHandling.IgnoreData };
using EofHitCounter eofHitCounter = EofHitCounter.RunDecoder(TestImages.Png.Bad.FlagOfGermany0000016446, decoder, options); using EofHitCounter eofHitCounter = EofHitCounter.RunDecoder(TestImages.Png.Bad.FlagOfGermany0000016446, decoder, options);
// TODO: Undo this. // TODO: Try to reduce this to 1.
Assert.True(eofHitCounter.EofHitCount <= 6); Assert.True(eofHitCounter.EofHitCount <= 3);
Assert.Equal(new Size(200, 120), eofHitCounter.Image.Size); Assert.Equal(new Size(200, 120), eofHitCounter.Image.Size);
} }
} }

Loading…
Cancel
Save