@@ -34,12 +34,17 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
3434 private readonly Configuration configuration ;
3535
3636 /// <summary>
37- /// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
37+ /// Whether the metadata should be ignored when the image is being decoded.
38+ /// </summary>
39+ private readonly uint maxFrames ;
40+
41+ /// <summary>
42+ /// Whether the metadata should be ignored when the image is being decoded.
3843 /// </summary>
3944 private readonly bool skipMetadata ;
4045
4146 /// <summary>
42- /// Gets or sets a value indicating whether to read the IHDR and tRNS chunks only.
47+ /// Whether to read the IHDR and tRNS chunks only.
4348 /// </summary>
4449 private readonly bool colorMetadataOnly ;
4550
@@ -61,7 +66,7 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
6166 /// <summary>
6267 /// The png animation control.
6368 /// </summary>
64- private AnimationControl ? animationControl ;
69+ private AnimationControl animationControl ;
6570
6671 /// <summary>
6772 /// The number of bytes per pixel.
@@ -116,6 +121,7 @@ public PngDecoderCore(DecoderOptions options)
116121 {
117122 this . Options = options ;
118123 this . configuration = options . Configuration ;
124+ this . maxFrames = options . MaxFrames ;
119125 this . skipMetadata = options . SkipMetadata ;
120126 this . memoryAllocator = this . configuration . MemoryAllocator ;
121127 }
@@ -124,6 +130,7 @@ internal PngDecoderCore(DecoderOptions options, bool colorMetadataOnly)
124130 {
125131 this . Options = options ;
126132 this . colorMetadataOnly = colorMetadataOnly ;
133+ this . maxFrames = options . MaxFrames ;
127134 this . skipMetadata = true ;
128135 this . configuration = options . Configuration ;
129136 this . memoryAllocator = this . configuration . MemoryAllocator ;
@@ -139,6 +146,7 @@ internal PngDecoderCore(DecoderOptions options, bool colorMetadataOnly)
139146 public Image < TPixel > Decode < TPixel > ( BufferedReadStream stream , CancellationToken cancellationToken )
140147 where TPixel : unmanaged, IPixel < TPixel >
141148 {
149+ uint frameCount = 0 ;
142150 ImageMetadata metadata = new ( ) ;
143151 PngMetadata pngMetadata = metadata . GetPngMetadata ( ) ;
144152 this . currentStream = stream ;
@@ -174,10 +182,21 @@ public Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken
174182 ReadGammaChunk ( pngMetadata , chunk . Data . GetSpan ( ) ) ;
175183 break ;
176184 case PngChunkType . FrameControl :
185+ ++ frameCount ;
186+ if ( frameCount == this . maxFrames )
187+ {
188+ break ;
189+ }
190+
177191 currentFrame = null ;
178192 lastFrameControl = this . ReadFrameControlChunk ( chunk . Data . GetSpan ( ) ) ;
179193 break ;
180194 case PngChunkType . FrameData :
195+ if ( frameCount == this . maxFrames )
196+ {
197+ break ;
198+ }
199+
181200 if ( image is null )
182201 {
183202 PngThrowHelper . ThrowMissingDefaultData ( ) ;
@@ -290,6 +309,7 @@ public Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken
290309 /// <inheritdoc/>
291310 public ImageInfo Identify ( BufferedReadStream stream , CancellationToken cancellationToken )
292311 {
312+ uint frameCount = 0 ;
293313 ImageMetadata metadata = new ( ) ;
294314 PngMetadata pngMetadata = metadata . GetPngMetadata ( ) ;
295315 this . currentStream = stream ;
@@ -331,9 +351,20 @@ public ImageInfo Identify(BufferedReadStream stream, CancellationToken cancellat
331351 ReadGammaChunk ( pngMetadata , chunk . Data . GetSpan ( ) ) ;
332352 break ;
333353 case PngChunkType . FrameControl :
354+ ++ frameCount ;
355+ if ( frameCount == this . maxFrames )
356+ {
357+ break ;
358+ }
359+
334360 lastFrameControl = this . ReadFrameControlChunk ( chunk . Data . GetSpan ( ) ) ;
335361 break ;
336362 case PngChunkType . FrameData :
363+ if ( frameCount == this . maxFrames )
364+ {
365+ break ;
366+ }
367+
337368 if ( this . colorMetadataOnly )
338369 {
339370 goto EOF ;
0 commit comments