Browse Source

Boundary checking before box allocation

pull/2633/head
Ynse Hoornenborg 3 years ago
parent
commit
193fd94af1
  1. 28
      src/ImageSharp/Formats/Heic/HeicDecoderCore.cs

28
src/ImageSharp/Formats/Heic/HeicDecoderCore.cs

@ -65,14 +65,15 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals
while (stream.Position < stream.Length) while (stream.Position < stream.Length)
{ {
long length = this.ReadBoxHeader(stream, out Heic4CharCode boxType); long boxLength = this.ReadBoxHeader(stream, out Heic4CharCode boxType);
EnsureBoxBoundary(boxLength, stream);
switch (boxType) switch (boxType)
{ {
case Heic4CharCode.meta: case Heic4CharCode.meta:
this.ParseMetadata(stream, length); this.ParseMetadata(stream, boxLength);
break; break;
case Heic4CharCode.mdat: case Heic4CharCode.mdat:
this.ParseMediaData(stream, length); this.ParseMediaData(stream, boxLength);
break; break;
default: default:
throw new ImageFormatException($"Unknown box type of '{Enum.GetName(boxType)}'"); throw new ImageFormatException($"Unknown box type of '{Enum.GetName(boxType)}'");
@ -100,15 +101,16 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals
while (stream.Position < stream.Length) while (stream.Position < stream.Length)
{ {
long length = this.ReadBoxHeader(stream, out Heic4CharCode boxType); long boxLength = this.ReadBoxHeader(stream, out Heic4CharCode boxType);
EnsureBoxBoundary(boxLength, stream);
switch (boxType) switch (boxType)
{ {
case Heic4CharCode.meta: case Heic4CharCode.meta:
this.ParseMetadata(stream, length); this.ParseMetadata(stream, boxLength);
break; break;
default: default:
// Silently skip all other box types. // Silently skip all other box types.
SkipBox(stream, length); SkipBox(stream, boxLength);
break; break;
} }
} }
@ -175,6 +177,7 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals
while (stream.Position < endPosition) while (stream.Position < endPosition)
{ {
long length = this.ReadBoxHeader(stream, out Heic4CharCode boxType); long length = this.ReadBoxHeader(stream, out Heic4CharCode boxType);
EnsureBoxBoundary(length, boxLength);
switch (boxType) switch (boxType)
{ {
case Heic4CharCode.iprp: case Heic4CharCode.iprp:
@ -348,6 +351,7 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals
while (stream.Position < endBoxPosition) while (stream.Position < endBoxPosition)
{ {
long containerLength = this.ReadBoxHeader(stream, out Heic4CharCode containerType); long containerLength = this.ReadBoxHeader(stream, out Heic4CharCode containerType);
EnsureBoxBoundary(containerLength, boxLength);
if (containerType == Heic4CharCode.ipco) if (containerType == Heic4CharCode.ipco)
{ {
// Parse Item Property Container, which is just an array of property boxes. // Parse Item Property Container, which is just an array of property boxes.
@ -372,6 +376,7 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals
while (stream.Position < endPosition) while (stream.Position < endPosition)
{ {
int itemLength = (int)this.ReadBoxHeader(stream, out Heic4CharCode itemType); int itemLength = (int)this.ReadBoxHeader(stream, out Heic4CharCode itemType);
EnsureBoxBoundary(itemLength, boxLength);
Span<byte> buffer = this.ReadIntoBuffer(stream, itemLength); Span<byte> buffer = this.ReadIntoBuffer(stream, itemLength);
switch (itemType) switch (itemType)
{ {
@ -568,6 +573,17 @@ internal sealed class HeicDecoderCore : IImageDecoderInternals
} }
} }
private static void EnsureBoxBoundary(long boxLength, Stream stream)
=> EnsureBoxBoundary(boxLength, stream.Length - stream.Position);
private static void EnsureBoxBoundary(long boxLength, long parentLength)
{
if (boxLength > parentLength)
{
throw new ImageFormatException("Box size beyond boundary");
}
}
private HeicItem? FindItemById(uint itemId) private HeicItem? FindItemById(uint itemId)
=> this.items.FirstOrDefault(item => item.Id == itemId); => this.items.FirstOrDefault(item => item.Id == itemId);

Loading…
Cancel
Save