Skip to content
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

Merged
merged 5 commits into from
May 19, 2020
Merged

Fix DataObject.GetData issues #3039

merged 5 commits into from
May 19, 2020

Conversation

weltkante
Copy link
Contributor

@weltkante weltkante commented Apr 5, 2020

Fixes #3025
Contributes to #1268

Proposed changes

  • use ReleaseStgMedium for ownership handling as suggested by win32 docs
  • do not assume third party implementations of IDataObject.GetData return the medium which was asked for (Office sometimes ignores the medium the caller asks for and always returns the medium it happens to be using internally). Since Windows/OLE does not pose constraints on what the DataObject source returns WinForms needs to be robust and handle this case instead of crashing the whole process.
  • clean up dead code related to metafiles, most code supporting them is already gone

Customer Impact

  • no more crashing when asking Office for "EnhancedMetafile"

Regression?

  • Yes (earlier Desktop Framework versions which still supported metafiles did not crash; latest Desktop Framework however also crashes the whole process)

Risk

  • low
    • For the scenario crashing the process there is no risk, (almost) nothing is worse than crashing the process
    • Metafile support was already removed and did not work anyways. Removing dead code related to metafiles should not be a problem since it was not possible to retrieve them.

Test methodology

Microsoft Reviewers: Open in CodeFlow

@weltkante weltkante requested a review from a team as a code owner April 5, 2020 14:42
@ghost ghost assigned weltkante Apr 5, 2020
Copy link
Contributor Author

@weltkante weltkante left a 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.

@weltkante
Copy link
Contributor Author

weltkante commented Apr 5, 2020

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).

@@ -1414,6 +1416,10 @@ private object GetDataFromOleHGLOBAL(string format, out bool done)
catch
Copy link
Contributor

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?

Copy link
Contributor Author

@weltkante weltkante Apr 6, 2020

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.

Copy link
Contributor Author

@weltkante weltkante left a 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

// 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));
Copy link
Contributor Author

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.

@weltkante weltkante changed the title WIP: fix DataObject.GetData issues Fix DataObject.GetData issues Apr 7, 2020
@weltkante
Copy link
Contributor Author

weltkante commented Apr 7, 2020

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.

@merriemcgaw merriemcgaw requested a review from JeremyKuhne April 16, 2020 23:59
@RussKie RussKie added the waiting-review This item is waiting on review by one or more members of team label Apr 17, 2020
Copy link
Member

@RussKie RussKie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤯 👍

@RussKie RussKie closed this May 7, 2020
@RussKie RussKie reopened this May 7, 2020
@JeremyKuhne
Copy link
Member

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.

@RussKie
Copy link
Member

RussKie commented May 12, 2020

@weltkante could you please resolve the MC.

@RussKie RussKie added the 📭 waiting-author-feedback The team requires more information from the author label May 12, 2020
@JeremyKuhne
Copy link
Member

To be clear- I'm ok with this modulo a sanity check after the conflict resolution.

@ghost ghost removed the 📭 waiting-author-feedback The team requires more information from the author label May 13, 2020
@weltkante
Copy link
Contributor Author

weltkante commented May 13, 2020

rebased, original is here for comparison purposes; unless I messed up the rebase there are no additional changes except moving diffs into separated files

@RussKie RussKie removed the waiting-review This item is waiting on review by one or more members of team label May 19, 2020
@RussKie RussKie merged commit 1d17041 into dotnet:master May 19, 2020
@ghost ghost added this to the 5.0 Preview6 milestone May 19, 2020
@RussKie
Copy link
Member

RussKie commented May 19, 2020

Thank you

@weltkante weltkante deleted the DataObject branch July 12, 2020 17:42
@ghost ghost locked as resolved and limited conversation to collaborators Feb 1, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Fatal error. Internal CLR error. (0x80131506) when DataObject.GetData(EnhancedMetaFile)
5 participants