-
-
Notifications
You must be signed in to change notification settings - Fork 853
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handle EOF in Jpeg bit reader when data is bad to prevent DOS attack. #2516
Changes from all commits
008c417
e686680
62aaa4d
51de859
dc018fa
c129720
1499213
e96f1fe
1bb07cb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,7 +50,7 @@ public static void IterateRows<T>( | |
int width = rectangle.Width; | ||
int height = rectangle.Height; | ||
|
||
int maxSteps = DivideCeil(width * height, parallelSettings.MinimumPixelsProcessedPerTask); | ||
int maxSteps = DivideCeil(width * (long)height, parallelSettings.MinimumPixelsProcessedPerTask); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've kept it in for simplicities sake but added tests. |
||
int numOfSteps = Math.Min(parallelSettings.MaxDegreeOfParallelism, maxSteps); | ||
|
||
// Avoid TPL overhead in this trivial case: | ||
|
@@ -115,7 +115,7 @@ public static void IterateRows<T, TBuffer>( | |
int width = rectangle.Width; | ||
int height = rectangle.Height; | ||
|
||
int maxSteps = DivideCeil(width * height, parallelSettings.MinimumPixelsProcessedPerTask); | ||
int maxSteps = DivideCeil(width * (long)height, parallelSettings.MinimumPixelsProcessedPerTask); | ||
int numOfSteps = Math.Min(parallelSettings.MaxDegreeOfParallelism, maxSteps); | ||
MemoryAllocator allocator = parallelSettings.MemoryAllocator; | ||
int bufferLength = Unsafe.AsRef(operation).GetRequiredBufferLength(rectangle); | ||
|
@@ -180,7 +180,7 @@ public static void IterateRowIntervals<T>( | |
int width = rectangle.Width; | ||
int height = rectangle.Height; | ||
|
||
int maxSteps = DivideCeil(width * height, parallelSettings.MinimumPixelsProcessedPerTask); | ||
int maxSteps = DivideCeil(width * (long)height, parallelSettings.MinimumPixelsProcessedPerTask); | ||
int numOfSteps = Math.Min(parallelSettings.MaxDegreeOfParallelism, maxSteps); | ||
|
||
// Avoid TPL overhead in this trivial case: | ||
|
@@ -242,7 +242,7 @@ public static void IterateRowIntervals<T, TBuffer>( | |
int width = rectangle.Width; | ||
int height = rectangle.Height; | ||
|
||
int maxSteps = DivideCeil(width * height, parallelSettings.MinimumPixelsProcessedPerTask); | ||
int maxSteps = DivideCeil(width * (long)height, parallelSettings.MinimumPixelsProcessedPerTask); | ||
int numOfSteps = Math.Min(parallelSettings.MaxDegreeOfParallelism, maxSteps); | ||
MemoryAllocator allocator = parallelSettings.MemoryAllocator; | ||
int bufferLength = Unsafe.AsRef(operation).GetRequiredBufferLength(rectangle); | ||
|
@@ -270,7 +270,7 @@ public static void IterateRowIntervals<T, TBuffer>( | |
} | ||
|
||
[MethodImpl(InliningOptions.ShortMethod)] | ||
private static int DivideCeil(int dividend, int divisor) => 1 + ((dividend - 1) / divisor); | ||
private static int DivideCeil(long dividend, int divisor) => (int)Math.Min(1 + ((dividend - 1) / divisor), int.MaxValue); | ||
|
||
private static void ValidateRectangle(Rectangle rectangle) | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -212,7 +212,12 @@ public bool FindNextMarker() | |
private int ReadStream() | ||
{ | ||
int value = this.badData ? 0 : this.stream.ReadByte(); | ||
if (value == -1) | ||
|
||
// We've encountered the end of the file stream which means there's no EOI marker or the marker has been read | ||
// during decoding of the SOS marker. | ||
// When reading individual bits 'badData' simply means we have hit a marker, When data is '0' and the stream is exhausted | ||
// we know we have hit the EOI and completed decoding the scan buffer. | ||
if (value == -1 || (this.badData && this.data == 0 && this.stream.Position >= this.stream.Length)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you describe the stuff behind There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
{ | ||
// We've encountered the end of the file stream which means there's no EOI marker | ||
// in the image or the SOS marker has the wrong dimensions set. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -314,4 +314,21 @@ public void Issue2315_DecodeWorks<TPixel>(TestImageProvider<TPixel> provider) | |
image.DebugSave(provider); | ||
image.CompareToOriginal(provider); | ||
} | ||
|
||
[Theory] | ||
[WithFile(TestImages.Jpeg.Issues.HangBadScan, PixelTypes.L8)] | ||
public void DecodeHang<TPixel>(TestImageProvider<TPixel> provider) | ||
where TPixel : unmanaged, IPixel<TPixel> | ||
{ | ||
if (TestEnvironment.IsWindows && | ||
TestEnvironment.RunsOnCI) | ||
{ | ||
// Windows CI runs consistently fail with OOM. | ||
return; | ||
} | ||
|
||
using Image<TPixel> image = provider.GetImage(JpegDecoder.Instance); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's no way to test this without actually decoding the image so I've tried to use as little memory as possible. |
||
Assert.Equal(65503, image.Width); | ||
Assert.Equal(65503, image.Height); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Allow the trigger of the build for PRs against release branches.