@@ -1395,7 +1395,7 @@ private void ReadCompressedTextChunk(ImageMetadata baseMetadata, PngMetadata met
1395
1395
1396
1396
ReadOnlySpan < byte > compressedData = data [ ( zeroIndex + 2 ) ..] ;
1397
1397
1398
- if ( this . TryUncompressTextData ( compressedData , PngConstants . Encoding , out string ? uncompressed )
1398
+ if ( this . TryDecompressTextData ( compressedData , PngConstants . Encoding , out string ? uncompressed )
1399
1399
&& ! TryReadTextChunkMetadata ( baseMetadata , name , uncompressed ) )
1400
1400
{
1401
1401
metadata . TextData . Add ( new PngTextData ( name , uncompressed , string . Empty , string . Empty ) ) ;
@@ -1539,19 +1539,19 @@ private void ReadColorProfileChunk(ImageMetadata metadata, ReadOnlySpan<byte> da
1539
1539
1540
1540
ReadOnlySpan < byte > compressedData = data [ ( zeroIndex + 2 ) ..] ;
1541
1541
1542
- if ( this . TryUncompressZlibData ( compressedData , out byte [ ] iccpProfileBytes ) )
1542
+ if ( this . TryDecompressZlibData ( compressedData , out byte [ ] iccpProfileBytes ) )
1543
1543
{
1544
1544
metadata . IccProfile = new IccProfile ( iccpProfileBytes ) ;
1545
1545
}
1546
1546
}
1547
1547
1548
1548
/// <summary>
1549
- /// Tries to un-compress zlib compressed data.
1549
+ /// Tries to decompress zlib compressed data.
1550
1550
/// </summary>
1551
1551
/// <param name="compressedData">The compressed data.</param>
1552
1552
/// <param name="uncompressedBytesArray">The uncompressed bytes array.</param>
1553
1553
/// <returns>True, if de-compressing was successful.</returns>
1554
- private unsafe bool TryUncompressZlibData ( ReadOnlySpan < byte > compressedData , out byte [ ] uncompressedBytesArray )
1554
+ private unsafe bool TryDecompressZlibData ( ReadOnlySpan < byte > compressedData , out byte [ ] uncompressedBytesArray )
1555
1555
{
1556
1556
fixed ( byte * compressedDataBase = compressedData )
1557
1557
{
@@ -1688,7 +1688,7 @@ private void ReadInternationalTextChunk(ImageMetadata metadata, ReadOnlySpan<byt
1688
1688
{
1689
1689
ReadOnlySpan < byte > compressedData = data [ dataStartIdx ..] ;
1690
1690
1691
- if ( this . TryUncompressTextData ( compressedData , PngConstants . TranslatedEncoding , out string ? uncompressed ) )
1691
+ if ( this . TryDecompressTextData ( compressedData , PngConstants . TranslatedEncoding , out string ? uncompressed ) )
1692
1692
{
1693
1693
pngMetadata . TextData . Add ( new PngTextData ( keyword , uncompressed , language , translatedKeyword ) ) ;
1694
1694
}
@@ -1711,9 +1711,9 @@ private void ReadInternationalTextChunk(ImageMetadata metadata, ReadOnlySpan<byt
1711
1711
/// <param name="encoding">The string encoding to use.</param>
1712
1712
/// <param name="value">The uncompressed value.</param>
1713
1713
/// <returns>The <see cref="bool"/>.</returns>
1714
- private bool TryUncompressTextData ( ReadOnlySpan < byte > compressedData , Encoding encoding , [ NotNullWhen ( true ) ] out string ? value )
1714
+ private bool TryDecompressTextData ( ReadOnlySpan < byte > compressedData , Encoding encoding , [ NotNullWhen ( true ) ] out string ? value )
1715
1715
{
1716
- if ( this . TryUncompressZlibData ( compressedData , out byte [ ] uncompressedData ) )
1716
+ if ( this . TryDecompressZlibData ( compressedData , out byte [ ] uncompressedData ) )
1717
1717
{
1718
1718
value = encoding . GetString ( uncompressedData ) ;
1719
1719
return true ;
@@ -1736,7 +1736,11 @@ private int ReadNextDataChunk()
1736
1736
1737
1737
Span < byte > buffer = stackalloc byte [ 20 ] ;
1738
1738
1739
- _ = this . currentStream . Read ( buffer , 0 , 4 ) ;
1739
+ int length = this . currentStream . Read ( buffer , 0 , 4 ) ;
1740
+ if ( length == 0 )
1741
+ {
1742
+ return 0 ;
1743
+ }
1740
1744
1741
1745
if ( this . TryReadChunk ( buffer , out PngChunk chunk ) )
1742
1746
{
@@ -1765,7 +1769,11 @@ private int ReadNextFrameDataChunk()
1765
1769
1766
1770
Span < byte > buffer = stackalloc byte [ 20 ] ;
1767
1771
1768
- _ = this . currentStream . Read ( buffer , 0 , 4 ) ;
1772
+ int length = this . currentStream . Read ( buffer , 0 , 4 ) ;
1773
+ if ( length == 0 )
1774
+ {
1775
+ return 0 ;
1776
+ }
1769
1777
1770
1778
if ( this . TryReadChunk ( buffer , out PngChunk chunk ) )
1771
1779
{
@@ -1802,8 +1810,9 @@ private bool TryReadChunk(Span<byte> buffer, out PngChunk chunk)
1802
1810
return true ;
1803
1811
}
1804
1812
1805
- if ( this . currentStream . Position == this . currentStream . Length )
1813
+ if ( this . currentStream . Position >= this . currentStream . Length - 1 )
1806
1814
{
1815
+ // IEND
1807
1816
chunk = default ;
1808
1817
return false ;
1809
1818
}
@@ -1820,6 +1829,7 @@ private bool TryReadChunk(Span<byte> buffer, out PngChunk chunk)
1820
1829
// Not a valid chunk so try again until we reach a known chunk.
1821
1830
if ( ! this . TryReadChunkLength ( buffer , out length ) )
1822
1831
{
1832
+ // IEND
1823
1833
chunk = default ;
1824
1834
return false ;
1825
1835
}
@@ -1832,10 +1842,11 @@ private bool TryReadChunk(Span<byte> buffer, out PngChunk chunk)
1832
1842
if ( this . colorMetadataOnly && type != PngChunkType . Header && type != PngChunkType . Transparency && type != PngChunkType . Palette )
1833
1843
{
1834
1844
chunk = new PngChunk ( length , type ) ;
1835
-
1836
1845
return true ;
1837
1846
}
1838
1847
1848
+ // A chunk might report a length that exceeds the length of the stream.
1849
+ // Take the minimum of the two values to ensure we don't read past the end of the stream.
1839
1850
long position = this . currentStream . Position ;
1840
1851
chunk = new PngChunk (
1841
1852
length : ( int ) Math . Min ( length , this . currentStream . Length - position ) ,
0 commit comments