-
Notifications
You must be signed in to change notification settings - Fork 991
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
Fix DataObject.GetData issues #3039
Conversation
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.
I didn't do any code style cleanup to not distract from how the ownership/release logic changed. Adding some pre-resolved comments to explain whats happening. Any other place which released something was replaced by ReleaseStgMedium
.
Note that the previous code did not respect punkForRelease
and released stuff even if it didn't own it. I can only conclude that punkForRelease
is not used by most applications, otherwise Clipboard support would have been totally broken in Desktop Framework probably since its initial release.
src/System.Windows.Forms/src/System/Windows/Forms/DataObject.cs
Outdated
Show resolved
Hide resolved
src/System.Windows.Forms/src/System/Windows/Forms/DataObject.cs
Outdated
Show resolved
Hide resolved
src/System.Windows.Forms/src/System/Windows/Forms/DataObject.cs
Outdated
Show resolved
Hide resolved
src/System.Windows.Forms/src/System/Windows/Forms/DataObject.cs
Outdated
Show resolved
Hide resolved
src/System.Windows.Forms/src/System/Windows/Forms/DataObject.cs
Outdated
Show resolved
Hide resolved
Not sure why tests are failing, I don't think the AxHost/IPictureDisp test has anything to do with DataObject, and for the other CI failure I don't even see what failed (or don't know where to look). |
src/System.Windows.Forms/src/System/Windows/Forms/DataObject.cs
Outdated
Show resolved
Hide resolved
@@ -1414,6 +1416,10 @@ private object GetDataFromOleHGLOBAL(string format, out bool done) | |||
catch |
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.
should we have these catch-all blocks?
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.
Unfortunately its required here for two reasons:
- GetDataFromHGLOBAL reports failure via exception, but you don't know which exception it is. It does complex dispatching and some branches can execute arbitrary user code while deserializing a serialized object (not for the builtin formats, but custom formats still support arbitrary serialized objects). Failure to deserialize shouldn't throw and needs to return null, it is actually a pretty common scenario not being able to resolve an assembly from a 3rd party process.
- For the interop calls, while you could be more specific, you really want to catch all HRESULT-based exceptions, but some HRESULT-based exceptions get translated. So being specific requires a lot of research to cover exactly the set of HRESULT-exceptions that can get translated.
If you want to improve this you have to
- move the deserialization try-catch to where its really needed (i.e. where the deserialization happens)
- make it TryGetDataFromHGLOBAL so it can report failures without throwing arbitrary exceptions
- stop using IDataObject from corefx, make your own declaration which returns HRESULT explicitely so it doesn't get translated to a thrown exception when you don't want it to
Certainly not something I'd want to be doing in a bugfix PR. If you think its worth to improve the locality of the catch-all to just the deserialization (can't get rid of it there) we should create a separate issue.
src/System.Windows.Forms/src/System/Windows/Forms/DataObject.cs
Outdated
Show resolved
Hide resolved
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.
Added unit test which repros the faulting scenario without having to copy/paste a metafile from Office
src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataObjectTests.cs
Outdated
Show resolved
Hide resolved
// even when asked for a stream. This used to crash the process when DataObject interpreted the | ||
// handle as a pointer to a COM IStream without checking the storage medium it retrieved. | ||
|
||
Assert.Null(data.GetData(DataFormats.EnhancedMetafile)); |
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.
This will crash the runtime without the fix, is the CI unit test infrastructure up to the task to detect crashing as test failures? When running the test inside VS without fix it is not detected as test failure, it just looks like the test never ran even though I explicitly told it to run the test.
Since the remaining changes for #1268 are supposed to go into a separate PR I think this is now ready. Diff is slightly easier to read when ignoring whitespace changes due to try/finally indentation. |
src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataObjectTests.cs
Outdated
Show resolved
Hide resolved
src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataObjectTests.cs
Outdated
Show resolved
Hide resolved
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.
🤯 👍
src/System.Windows.Forms.Primitives/src/Interop/Ole32/Interop.ReleaseStgMedium.cs
Show resolved
Hide resolved
src/System.Windows.Forms/src/System/Windows/Forms/DataObject.cs
Outdated
Show resolved
Hide resolved
src/System.Windows.Forms/src/System/Windows/Forms/DataObject.cs
Outdated
Show resolved
Hide resolved
src/System.Windows.Forms.Primitives/src/Interop/Ole32/Interop.ReleaseStgMedium.cs
Outdated
Show resolved
Hide resolved
Looks good. I'd love to see this code thoroughly cleaned up in the future. There are efficiency issues and we're not being particularly robust/safe. |
@weltkante could you please resolve the MC. |
To be clear- I'm ok with this modulo a sanity check after the conflict resolution. |
rebased, original is here for comparison purposes; unless I messed up the rebase there are no additional changes except moving diffs into separated files |
Thank you |
Fixes #3025
Contributes to #1268
Proposed changes
Customer Impact
Regression?
Risk
Test methodology
Microsoft Reviewers: Open in CodeFlow