https://bugs.winehq.org/show_bug.cgi?id=37842
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |dotnet, download Status|UNCONFIRMED |NEW URL| |http://free-dl.ptc.com/inst | |all/pim_installmgr_mathcad. | |exe CC| |focht@gmx.net Component|-unknown |ole32 Summary|Mathcad Prime 3.0 crashes |PTC Mathcad Prime 3.0 (.NET |when trying to calculate a |4.0 app) crashes when using |result |copy paste or trying to | |calculate a result (OLE | |clipboard must take MTA | |into account) Ever confirmed|0 |1
--- Comment #1 from Anastasius Focht focht@gmx.net --- Hello folks,
confirming.
Managed backtraces:
--- snip --- ... Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. at MS.Win32.UnsafeNativeMethods.OleGetClipboard(IDataObject& data) at System.Windows.OleServicesContext.OleGetClipboard(IDataObject& dataObject) at System.Windows.Clipboard.GetDataObjectInternal() at System.Windows.Clipboard.GetDataInternal(String format) at System.Windows.Clipboard.GetText(TextDataFormat format) at Ptc.WpfClipboard.GetText() at Ptc.EquationEditor.Equation.EquationModel.l() at Ptc.EquationEditor.Equation.EquationModel.ac.v() at a1.v() at Ptc.EquationEditor.Equation.EquationModel.CanPaste(Boolean& canPaste) at Ptc.Controls.Internal.VisualMathRegionNode.FireCanPaste(Object sender, CanExecuteRoutedEventArgs e) ... at DevComponents.WpfRibbon.ButtonDropDown.UpdateCanExecute() ... at System.Windows.Application.RunDispatcher(Object ignore) at System.Windows.Application.RunInternal(Window window) at System.Windows.Application.Run(Window window) at Spirit.App.Main()
Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. at MS.Win32.UnsafeNativeMethods.OleGetClipboard(IDataObject& data) at System.Windows.OleServicesContext.OleGetClipboard(IDataObject& dataObject) at System.Windows.Clipboard.GetDataObjectInternal() at System.Windows.Documents.TextEditorCopyPaste.OnQueryStatusPaste(Object target, CanExecuteRoutedEventArgs args) at System.Windows.Input.CommandBinding.OnCanExecute(Object sender, CanExecuteRoutedEventArgs e) at System.Windows.Input.CommandManager.FindCommandBinding(CommandBindingCollection commandBindings, Object sender, RoutedEventArgs e, ICommand command, Boolean execute) at System.Windows.Input.CommandManager.FindCommandBinding(Object sender, RoutedEventArgs e, ICommand command, Boolean execute) at System.Windows.Input.CommandManager.OnCanExecute(Object sender, CanExecuteRoutedEventArgs e) ... --- snip ---
Trace log:
--- snip --- $ pwd /home/focht/.wine/drive_c/Program Files/PTC/Mathcad Prime 3.0
$ WINEDEBUG=+tid,+seh,+relay,+ole,+variant,+clipboard wine ./MathcadPrime.exe
log.txt 2>&1
... 002a:Call ole32.OleGetClipboard(0033e104) ret=057bfd89 002a:trace:ole:OleGetClipboard (0x33e104) 002a:Call user32.GetClipboardSequenceNumber() ret=f6d1450a 002a:trace:clipboard:GetClipboardSequenceNumber returning 7 002a:Ret user32.GetClipboardSequenceNumber() retval=00000007 ret=f6d1450a 002a:Call ntdll.RtlAllocateHeap(00110000,00000000,00000010) ret=f6d132e5 002a:Ret ntdll.RtlAllocateHeap() retval=076ba090 ret=f6d132e5 002a:trace:ole:snapshot_AddRef (0x76ba090)->(count=0) 002a:Ret ole32.OleGetClipboard() retval=00000000 ret=057bfd89 002a:trace:ole:snapshot_QueryInterface (0x76ba090)->(IID:{00000000-0000-0000-c000-000000000046}, 0x33dba0) 002a:trace:ole:snapshot_AddRef (0x76ba090)->(count=1) ... 002a:trace:ole:snapshot_Release (0x76ba090)->(count=3) ... 002a:trace:ole:snapshot_GetData (0x76ba090, 0x33e09c {cf 000d ptd (nil) aspect 1 lindex -1 tymed 1}, 0x33e014) 002a:Call user32.OpenClipboard(00000000) ret=f6d126af 002a:trace:clipboard:OpenClipboard ((nil)) ... 002a:trace:clipboard:OpenClipboard returning 1 002a:Ret user32.OpenClipboard() retval=00000001 ret=f6d126af ... 002a:Call ole32.OleGetClipboard(0033e104) ret=057bfd89 002a:trace:ole:OleGetClipboard (0x33e104) 002a:Call user32.GetClipboardSequenceNumber() ret=f6d1450a 002a:trace:clipboard:GetClipboardSequenceNumber returning 7 002a:Ret user32.GetClipboardSequenceNumber() retval=00000007 ret=f6d1450a 002a:trace:seh:raise_exception code=c0000005 flags=0 addr=0x76ba090 ip=076ba090 tid=002a 002a:trace:seh:raise_exception info[0]=00000008 002a:trace:seh:raise_exception info[1]=076ba090 002a:trace:seh:raise_exception eax=076ba090 ebx=f6e42000 ecx=00000000 edx=076ba090 esi=0033e090 edi=0033e094 002a:trace:seh:raise_exception ebp=0033e078 esp=0033e00c cs=0023 ds=002b es=002b fs=0063 gs=006b flags=00210206 002a:trace:seh:call_vectored_handlers calling handler at 0x791f5a7c code=c0000005 flags=0 002a:Call KERNEL32.GetLastError() ret=791f5aa7 002a:Ret KERNEL32.GetLastError() retval=00000000 ret=791f5aa7 002a:trace:seh:call_vectored_handlers handler at 0x791f5a7c returned 0 --- snip ---
Best to reproduce by just pasting external text data into the workspace of the app.
At the point of the crash the latest snapshot object is not longer an 'IDataObject' (vtable no longer valid). The sequence member incidentally matches hence the code tries to return the current snapshot without generating a new one. Either the dereferencing of vtable (what ought to be 'IDataObject') or the following 'IDataObject->AddRef' causes the crash.
I initially made the mistake of filtering the huge relay log per thread because there is lots of interleaving/parallel code executions on multiple threads (with inter-thread sync), making the API call flow very hard to follow.
This usually works well - but in this case the habit hides the culprit. The clipboard/OLE functionality is managed across different threads.
Another log, now filtered for the 'IDataObject' instance in question, with additional custom trace message added:
--- snip --- ... 002c:Ret ntdll.RtlAllocateHeap() retval=07953428 ret=f6d5b2e5 002c:trace:ole:OleGetClipboard *** creating latest_snapshot: seq_no=13, ptr=0x7953428 002c:trace:ole:snapshot_AddRef (0x7953428)->(count=0) 002c:trace:ole:OleGetClipboard *** returning: seq_no=13, *obj=0x7953428 002c:trace:ole:snapshot_QueryInterface (0x7953428)->(IID:{00000000-0000-0000-c000-000000000046}, 0x33dcac) 002c:trace:ole:snapshot_AddRef (0x7953428)->(count=1) 002c:trace:ole:snapshot_QueryInterface (0x7953428)->(IID:{c3fcc19e-a970-11d2-8b5a-00a0c9b7c9c4}, 0x33dc28) 002c:trace:ole:snapshot_QueryInterface (0x7953428)->(IID:{b196b283-bab4-101a-b69c-00aa00341d07}, 0x33db04) 002c:trace:ole:snapshot_AddRef (0x7953428)->(count=2) 002c:trace:ole:snapshot_QueryInterface (0x7953428)->(IID:{00000003-0000-0000-c000-000000000046}, 0x33da4c) 002c:trace:ole:snapshot_AddRef (0x7953428)->(count=3) 002c:trace:ole:snapshot_QueryInterface (0x7953428)->(IID:{00000144-0000-0000-c000-000000000046}, 0x33db10) 002c:trace:ole:snapshot_Release (0x7953428)->(count=4) 002c:trace:ole:snapshot_Release (0x7953428)->(count=3) 002c:trace:ole:snapshot_AddRef (0x7953428)->(count=2) 002c:trace:ole:snapshot_QueryInterface (0x7953428)->(IID:{0000010e-0000-0000-c000-000000000046}, 0x33df10) 002c:trace:ole:snapshot_AddRef (0x7953428)->(count=3) 002c:trace:ole:snapshot_Release (0x7953428)->(count=4) 002c:trace:ole:snapshot_Release (0x7953428)->(count=3) 002c:trace:ole:snapshot_Release (0x7953428)->(count=2) 002c:trace:ole:snapshot_AddRef (0x7953428)->(count=1) 002c:trace:ole:snapshot_QueryInterface (0x7953428)->(IID:{fe4ff803-496e-3a49-af00-13b2cc182476}, 0x33dfdc) 002c:trace:ole:snapshot_Release (0x7953428)->(count=2) 002c:trace:ole:snapshot_AddRef (0x7953428)->(count=1) 002c:trace:ole:snapshot_QueryInterface (0x7953428)->(IID:{0000010e-0000-0000-c000-000000000046}, 0x33df68) 002c:trace:ole:snapshot_AddRef (0x7953428)->(count=2) 002c:trace:ole:snapshot_Release (0x7953428)->(count=3) 002c:trace:ole:snapshot_AddRef (0x7953428)->(count=2) 002c:fixme:ole:snapshot_QueryGetData (0x7953428, 0x33e1a8 {cf c066 ptd (nil) aspect 1 lindex -1 tymed 75}) 002c:trace:ole:snapshot_Release (0x7953428)->(count=3) 002c:fixme:ole:snapshot_QueryGetData (0x7953428, 0x33e1c4 {cf c074 ptd (nil) aspect 1 lindex -1 tymed 75}) 002c:fixme:ole:snapshot_QueryGetData (0x7953428, 0x33e1c4 {cf c065 ptd (nil) aspect 1 lindex -1 tymed 75}) 002c:fixme:ole:snapshot_QueryGetData (0x7953428, 0x33e1c4 {cf c008 ptd (nil) aspect 1 lindex -1 tymed 75}) 002c:fixme:ole:snapshot_QueryGetData (0x7953428, 0x33e1c4 {cf 000d ptd (nil) aspect 1 lindex -1 tymed 75}) 002c:trace:ole:OleGetClipboard *** clipbrd=0x712e9a0, clipbrd->latest_snapshot=0x7953428 002c:trace:ole:snapshot_AddRef (0x7953428)->(count=2) 002c:trace:ole:OleGetClipboard *** returning: seq_no=13, *obj=0x7953428 002c:trace:ole:snapshot_QueryInterface (0x7953428)->(IID:{00000000-0000-0000-c000-000000000046}, 0x33dcac) 002c:trace:ole:snapshot_AddRef (0x7953428)->(count=3) 002c:trace:ole:snapshot_Release (0x7953428)->(count=4) 002c:trace:ole:snapshot_AddRef (0x7953428)->(count=3) 002c:trace:ole:snapshot_Release (0x7953428)->(count=4) 002c:trace:ole:snapshot_Release (0x7953428)->(count=3) 002c:trace:ole:snapshot_AddRef (0x7953428)->(count=2) 002c:trace:ole:snapshot_QueryInterface (0x7953428)->(IID:{fe4ff803-496e-3a49-af00-13b2cc182476}, 0x33dfdc) 002c:trace:ole:snapshot_Release (0x7953428)->(count=3) 002c:fixme:ole:snapshot_QueryGetData (0x7953428, 0x33e1a8 {cf c066 ptd (nil) aspect 1 lindex -1 tymed 75}) 002c:fixme:ole:snapshot_QueryGetData (0x7953428, 0x33e1c4 {cf c074 ptd (nil) aspect 1 lindex -1 tymed 75}) 002c:fixme:ole:snapshot_QueryGetData (0x7953428, 0x33e1c4 {cf c065 ptd (nil) aspect 1 lindex -1 tymed 75}) 002c:fixme:ole:snapshot_QueryGetData (0x7953428, 0x33e1c4 {cf c008 ptd (nil) aspect 1 lindex -1 tymed 75}) 002c:fixme:ole:snapshot_QueryGetData (0x7953428, 0x33e1c4 {cf 000d ptd (nil) aspect 1 lindex -1 tymed 75}) 0040:trace:ole:snapshot_Release (0x7953428)->(count=2) 0040:trace:ole:snapshot_Release (0x7953428)->(count=1) 0040:Call ntdll.RtlFreeHeap(00110000,00000000,07953428) ret=f6d59bba 0043:Ret ntdll.RtlAllocateHeap() retval=07953428 ret=550013f7 ... 0043:Ret ntdll.RtlAllocateHeap() retval=07953428 ret=550013f7 0043:Call ntdll.RtlFreeHeap(00110000,00000000,07953428) ret=55003bde 002c:trace:ole:OleGetClipboard *** clipbrd=0x712e9a0, clipbrd->latest_snapshot=0x7953428 --- snip ---
What is happens is that 'IDataObject' instances are channelled across .NET threads and finally released after use - but not from the originating thread.
http://source.winehq.org/git/wine.git/blob/ec8602a8125bd3838948d32747217ed79...
--- snip --- 1031 static ULONG WINAPI snapshot_Release(IDataObject *iface) 1032 { 1033 snapshot *This = impl_from_IDataObject(iface); 1034 ULONG ref; 1035 1036 TRACE("(%p)->(count=%u)\n", This, This->ref); 1037 1038 ref = InterlockedDecrement(&This->ref); 1039 1040 if (ref == 0) 1041 { 1042 ole_clipbrd *clipbrd; 1043 HRESULT hr = get_ole_clipbrd(&clipbrd); 1044 1045 if(This->data) IDataObject_Release(This->data); 1046 1047 if(SUCCEEDED(hr) && clipbrd->latest_snapshot == This) 1048 clipbrd->latest_snapshot = NULL; 1049 HeapFree(GetProcessHeap(), 0, This); 1050 } 1051 1052 return ref; 1053 } --- snip ---
Source: http://source.winehq.org/git/wine.git/blob/ec8602a8125bd3838948d32747217ed79...
--- snip --- 180 static inline HRESULT get_ole_clipbrd(ole_clipbrd **clipbrd) 181 { 182 struct oletls *info = COM_CurrentInfo(); 183 *clipbrd = NULL; 184 185 if(!info->ole_inits) 186 return CO_E_NOTINITIALIZED; 187 *clipbrd = theOleClipboard; 188 189 return S_OK; 190 } --- snip ---
This code won't work if the calling (secondary) thread is in an MTA.
Wine's static 'clipbrd->latest_snapshot' instance which holds the latest (active) snapshot is never reset while the heap block, formerly an 'IDataObject' gets reused several times for multiple things, leading to later crash.
I tested a small fix, taking MTA into account and it prevents the crash. It might fix other OLE clipboard related bugs that exhibit a crash, too.
$ sha1sum pim_installmgr_mathcad.exe d05daf8d3ab70ad10da076bce28411ee7d643a58 pim_installmgr_mathcad.exe
$ du -sh pim_installmgr_mathcad.exe 18M pim_installmgr_mathcad.exe
$ wine --version wine-1.7.33-117-g6bab173
Regards