https://bugs.winehq.org/show_bug.cgi?id=52819
--- Comment #1 from Zeb Figura z.figura12@gmail.com --- Created attachment 72260 --> https://bugs.winehq.org/attachment.cgi?id=72260 HACK: oleaut32: Work around a double free.
The application is broken. It calls the following method typelib-marshalled:
HRESULT Write( [in] unsigned char ucAddress, [in] unsigned char ucFunctionCode, [in] VARIANT vData, [in] unsigned char ucExpectedDataCount, [in] long lCookie);
It calls the method remotely with a VT_ARRAY variant parameter, and the stub calls VariantClear() on that parameter. This results in a double free when the RPC runtime subsequently tries to free the variant again.
Because the variant is passed by value, we have to copy it from the unmarshaling buffer onto the stack, so the fact that VariantClear() clears the VT doesn't prevent the double free. It's possible that the program even blits the variant again; I can't immediately tell.
Most likely the old typelib marshaller got away with this because the subsequent memory corruption just happened not to immediately touch anything critical.
I don't see a good way to fix this. The attached hack will help obviously, but that's not suitable for upstream. We can't reliably avoid memory corruption from a double free, and we can't avoid blitting the variant either. The only possible ideas I have are:
[1] It's possible that call isn't supposed to happen at all. I see the following in +ole after the offending call:
0020:011c:trace:ole:create_errorinfo_SetSource 02FE2E4C, L"MGComDrv.ComDriver.1". 0020:011c:trace:ole:create_errorinfo_SetDescription 02FE2E4C, L"CSerialPort::Write: Open must be called before Write".
which suggests that the call to Write() [or the error return? it seems to return S_OK, though...] is invalid and might be triggered by a bug in Wine.
[2] The RPC happens within a single process, which is odd. It's possible that we shouldn't be marshalling anything.