-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Ensure ComManagedStream seekable wrapper stream has position of 0
#12953
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
Ensure ComManagedStream seekable wrapper stream has position of 0
#12953
Conversation
Until .NET 5, `ComManagedStream` (then `GPStream`) would wrap a non-seekable stream in a `MemoryStream` using the `MemoryStream(Byte[])` constructor. This results in a stream with a position of 0. dotnet/runtime commit 136527537e6 (Improve perfromance for loading from Stream on Windows (dotnet/corefx#31142), 2018-07-20) updated this logic to instead use `CopyTo` to populate the wrapping `MemoryStream`. This results in a stream with a non-zero position. It seems that this non-zero position causes some issues in downstream code when using `Image.FromStream` to load `.emf` and `.wmf` files, resulting in `LoadGdipImageFromStream` returning a status of 2 and thus an exception. Seek the wrapping `MemoryStream` back to the beginning after copying the source stream into it to prevent this exception. Fixes dotnet#12951
|
@dotnet-policy-service agree |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #12953 +/- ##
===================================================
+ Coverage 75.97906% 75.98329% +0.00422%
===================================================
Files 3265 3265
Lines 643272 643273 +1
Branches 47426 47426
===================================================
+ Hits 488752 488780 +28
+ Misses 150962 150935 -27
Partials 3558 3558
Flags with carried forward coverage won't be shown. Click here to find out more. |
|
I will note that it seems likely there are some other related issues at play here:
So this fix should likely be regarded as a partial fix to restore pre-.NET 5 behavior and address that regression, but it may make sense for someone to follow up with more investigation. |
|
Yeah, the image formats aside from .emf and .wmf seem to be seeking to the beginning unconditionally, which causes a problem if the stream is intentionally offset. So for example this code works:
But this code fails when it shouldn't:
Though fixing that won't be as easy as just not resetting the stream position for seekable streams, since it'd be a breaking change for callers. I guess same for making .emf and .wmf seek to the beginning, since that would break them from passing the second case above, even if it would make them behave consistently. I do wonder then, out of all the formats supported, which unconditionally seek to the start, and which don't. |
JeremyKuhne
left a comment
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.
Thanks for digging into this!
|
Marking as no merge temporarily as I try and write a test that repros the problem with WMF. Will address this today. |
…otnet#12953) Until .NET 5, `ComManagedStream` (then `GPStream`) would wrap a non-seekable stream in a `MemoryStream` using the `MemoryStream(Byte[])` constructor. This results in a stream with a position of 0. dotnet/runtime commit 136527537e6 (Improve perfromance for loading from Stream on Windows (dotnet/corefx#31142), 2018-07-20) updated this logic to instead use `CopyTo` to populate the wrapping `MemoryStream`. This results in a stream with a non-zero position. It seems that this non-zero position causes some issues in downstream code when using `Image.FromStream` to load `.emf` and `.wmf` files, resulting in `LoadGdipImageFromStream` returning a status of 2 and thus an exception. Seek the wrapping `MemoryStream` back to the beginning after copying the source stream into it to prevent this exception. Fixes dotnet#12951
This is a manual port of dotnet#12953. The code was refactored in .NET 9 so the fix needs manually applied.
…otnet#12953) Until .NET 5, `ComManagedStream` (then `GPStream`) would wrap a non-seekable stream in a `MemoryStream` using the `MemoryStream(Byte[])` constructor. This results in a stream with a position of 0. dotnet/runtime commit 136527537e6 (Improve perfromance for loading from Stream on Windows (dotnet/corefx#31142), 2018-07-20) updated this logic to instead use `CopyTo` to populate the wrapping `MemoryStream`. This results in a stream with a non-zero position. It seems that this non-zero position causes some issues in downstream code when using `Image.FromStream` to load `.emf` and `.wmf` files, resulting in `LoadGdipImageFromStream` returning a status of 2 and thus an exception. Seek the wrapping `MemoryStream` back to the beginning after copying the source stream into it to prevent this exception. Fixes dotnet#12951
This is a manual port of #12953. The code was refactored in .NET 9 so the fix needs manually applied. ###### Microsoft Reviewers: [Open in CodeFlow](https://microsoft.github.io/open-pr/?codeflow=https://github.com/dotnet/winforms/pull/12971)
#12970) …#12953) PORTS #12953 - DO NOT SQUASH Until .NET 5, `ComManagedStream` (then `GPStream`) would wrap a non-seekable stream in a `MemoryStream` using the `MemoryStream(Byte[])` constructor. This results in a stream with a position of 0. dotnet/runtime commit 136527537e6 (Improve perfromance for loading from Stream on Windows (dotnet/corefx#31142), 2018-07-20) updated this logic to instead use `CopyTo` to populate the wrapping `MemoryStream`. This results in a stream with a non-zero position. It seems that this non-zero position causes some issues in downstream code when using `Image.FromStream` to load `.emf` and `.wmf` files, resulting in `LoadGdipImageFromStream` returning a status of 2 and thus an exception. Seek the wrapping `MemoryStream` back to the beginning after copying the source stream into it to prevent this exception. ###### Microsoft Reviewers: [Open in CodeFlow](https://microsoft.github.io/open-pr/?codeflow=https://github.com/dotnet/winforms/pull/12970)
Fixes #12951
Proposed changes
ComManagedStreamwill ensure that the stream wrapping a non-seekable source stream has a position of 0 at the end of its constructor.Customer Impact
Image.FromStreamwith a non-seekable stream should no longer throw an exception when loading.emfand.wmfimages.Regression?
Risk
Test methodology
ComManagedStream.GetDataStream()has the expected state.Microsoft Reviewers: Open in CodeFlow