[Bug 37842] PTC Mathcad Prime 3.0 (.NET 4.0 app) crashes when using copy paste or trying to calculate a result (OLE clipboard must take MTA into account)

wine-bugs at winehq.org wine-bugs at winehq.org
Sun Jan 4 15:39:47 CST 2015


https://bugs.winehq.org/show_bug.cgi?id=37842

Anastasius Focht <focht at 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 at 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 at 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/ec8602a8125bd3838948d32747217ed794ae4068:/dlls/ole32/clipboard.c#l1031

--- 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/ec8602a8125bd3838948d32747217ed794ae4068:/dlls/ole32/clipboard.c#l180

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

-- 
Do not reply to this email, post in Bugzilla using the
above URL to reply.
You are receiving this mail because:
You are watching all bug changes.



More information about the wine-bugs mailing list