[PATCH v21 0/3] MR9632: sxs: avoid uninitialised len_name length
The `redirect_data->clrdata_len` [is unset in /dlls/ntdll/actctx.c#L4411-4412](https://gitlab.winehq.org/wine/wine/-/blob/master/dlls/ntdll/actctx.c?ref_ty...) when using registration-free COM in C# NET code. Program.cs ```C# //... Guid guid = Guid.Parse("COM clsid"); Type type = Type.GetTypeFromCLSID(guid, true); var instance = Activator.CreateInstance(type)); //... ``` App.manifest ```xml <assembly> <file name="ExampleCOM.dll"> <comClass description="ExampleCOM" progid="ExampleCOM" clsid="{COM clsid}" threadingModel="Free"/> </file> </assembly> ``` The above C# code gets this error on its second line. ```Shell System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. ``` This is because `len_name` is uninitialized when calling `memcpy(ret_strings, ptr_name, len_name);` in `SxsLookupClrGuid`, which is fixed in this MR. -- v21: add testlib https://gitlab.winehq.org/wine/wine/-/merge_requests/9632
From: Hans Chen <hxchennz@gmail.com> --- dlls/sxs/sxs.c | 30 ++++++++++++++++++----------- dlls/sxs/tests/comtest_exe.manifest | 1 + dlls/sxs/tests/sxs.c | 10 +++++----- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/dlls/sxs/sxs.c b/dlls/sxs/sxs.c index 150a49a322f..2b89bf369f0 100644 --- a/dlls/sxs/sxs.c +++ b/dlls/sxs/sxs.c @@ -97,7 +97,7 @@ BOOL WINAPI SxsLookupClrGuid(DWORD flags, GUID *clsid, HANDLE actctx, void *buff ACTCTX_SECTION_KEYED_DATA guid_info = { sizeof(ACTCTX_SECTION_KEYED_DATA) }; ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *assembly_info = NULL; SIZE_T bytes_assembly_info; - unsigned int len_version = 0, len_name, len_identity; + unsigned int len_version = 0, len_name = 0, len_identity = 0; const void *ptr_name, *ptr_version, *ptr_identity; SXS_GUID_INFORMATION_CLR *ret = buffer; BOOL retval = FALSE; @@ -160,12 +160,15 @@ BOOL WINAPI SxsLookupClrGuid(DWORD flags, GUID *clsid, HANDLE actctx, void *buff const struct comclassredirect_data *redirect_data = guid_info.lpData; const struct clrclass_data *class_data; - class_data = (void *)((char *)redirect_data + redirect_data->clrdata_offset); - ptr_name = (char *)class_data + class_data->name_offset; - ptr_version = (char *)class_data + class_data->version_offset; - len_name = class_data->name_len + sizeof(WCHAR); - if (class_data->version_len) - len_version = class_data->version_len + sizeof(WCHAR); + if(redirect_data->clrdata_len) + { + class_data = (void *)((char *)redirect_data + redirect_data->clrdata_offset); + ptr_name = (char *)class_data + class_data->name_offset; + ptr_version = (char *)class_data + class_data->version_offset; + len_name = class_data->name_len + sizeof(WCHAR); + if (class_data->version_len) + len_version = class_data->version_len + sizeof(WCHAR); + } } else { @@ -199,10 +202,15 @@ BOOL WINAPI SxsLookupClrGuid(DWORD flags, GUID *clsid, HANDLE actctx, void *buff ret->pcwszAssemblyIdentity = (WCHAR *)ret_strings; ret_strings += len_identity; - memcpy(ret_strings, ptr_name, len_name); - ret->pcwszTypeName = (WCHAR *)ret_strings; - ret_strings += len_name; - + if(len_name > 0) + { + memcpy(ret_strings, ptr_name, len_name); + ret->pcwszTypeName = (WCHAR *)ret_strings; + ret_strings += len_name; + } + else + ret->pcwszTypeName = NULL; + if (len_version > 0) { memcpy(ret_strings, ptr_version, len_version); diff --git a/dlls/sxs/tests/comtest_exe.manifest b/dlls/sxs/tests/comtest_exe.manifest index bc9ce4c0457..fda42a4597e 100644 --- a/dlls/sxs/tests/comtest_exe.manifest +++ b/dlls/sxs/tests/comtest_exe.manifest @@ -8,4 +8,5 @@ type="win32"/> </dependentAssembly> </dependency> + </assembly> diff --git a/dlls/sxs/tests/sxs.c b/dlls/sxs/tests/sxs.c index 9bcb85c69aa..d9e70722010 100644 --- a/dlls/sxs/tests/sxs.c +++ b/dlls/sxs/tests/sxs.c @@ -260,13 +260,13 @@ static void test_SxsLookupClrGuid(void) START_TEST(sxs) { - char **argv; - int argc = winetest_get_mainargs(&argv); - if (argc > 2) - { + // char **argv; + // int argc = winetest_get_mainargs(&argv); + // if (argc > 2) + // { prepare_and_run_test(); return; - } + // } test_SxsLookupClrGuid(); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9632
From: Hans Chen <hxchennz@gmail.com> --- dlls/sxs/tests/comtest_exe.manifest | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/dlls/sxs/tests/comtest_exe.manifest b/dlls/sxs/tests/comtest_exe.manifest index fda42a4597e..08c364f598e 100644 --- a/dlls/sxs/tests/comtest_exe.manifest +++ b/dlls/sxs/tests/comtest_exe.manifest @@ -8,5 +8,11 @@ type="win32"/> </dependentAssembly> </dependency> - + <file name="testlib.dll"> + <comClass + clsid="{12345678-1234-5678-1234-111122223333}" + progid="testlib.libClass" + threadingModel="Free" + /> + </file> </assembly> -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9632
From: Hans Chen <hxchennz@gmail.com> --- dlls/sxs/tests/Makefile.in | 2 ++ dlls/sxs/tests/sxs.c | 14 ++++++++++++++ dlls/sxs/tests/testlib.c | 38 +++++++++++++++++++++++++++++++++++++ dlls/sxs/tests/testlib.spec | 1 + 4 files changed, 55 insertions(+) create mode 100644 dlls/sxs/tests/testlib.c create mode 100644 dlls/sxs/tests/testlib.spec diff --git a/dlls/sxs/tests/Makefile.in b/dlls/sxs/tests/Makefile.in index 9c93f16da66..3c492b2d2ed 100644 --- a/dlls/sxs/tests/Makefile.in +++ b/dlls/sxs/tests/Makefile.in @@ -6,4 +6,6 @@ SOURCES = \ interfaces.idl \ name.c \ resource.rc \ + testlib.c \ + testlib.spec \ sxs.c diff --git a/dlls/sxs/tests/sxs.c b/dlls/sxs/tests/sxs.c index d9e70722010..75b67fcf25e 100644 --- a/dlls/sxs/tests/sxs.c +++ b/dlls/sxs/tests/sxs.c @@ -38,6 +38,8 @@ #define SXS_GUID_INFORMATION_CLR_FLAG_IS_SURROGATE 0x00000001 #define SXS_GUID_INFORMATION_CLR_FLAG_IS_CLASS 0x00000002 +DEFINE_GUID(CLSID_TestLibClass, 0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33); + typedef struct _SXS_GUID_INFORMATION_CLR { DWORD cbSize; @@ -147,6 +149,18 @@ static void run_test(void) ret = SxsLookupClrGuid(SXS_LOOKUP_CLR_GUID_FIND_ANY, (GUID *)&CLSID_SurrogateTest, NULL, NULL, 0, &buffer_size); ok(!ret, "Unexpected return value %d.\n", ret); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Got %ld\n", GetLastError()); + + info = malloc(buffer_size); + SetLastError(0xdeadbeef); + ret = SxsLookupClrGuid(SXS_LOOKUP_CLR_GUID_FIND_ANY, (GUID*)&CLSID_TestLibClass, NULL, info, buffer_size, &buffer_size); + ok(ret == TRUE, "Got %d\n", ret); + ok(GetLastError() == 0, "Got %ld\n", GetLastError()); + ok(info->dwFlags == SXS_GUID_INFORMATION_CLR_FLAG_IS_CLASS, "Got %ld\n", info->dwFlags); + ok(!lstrcmpW(info->pcwszTypeName, NULL), "Unexpected typename %s.\n", wine_dbgstr_w(info->pcwszTypeName)); + ok(!lstrcmpW(info->pcwszRuntimeVersion, NULL), "Unexpected runtime version %s.\n", + wine_dbgstr_w(info->pcwszRuntimeVersion)); + + free(info); } static void prepare_and_run_test(void) diff --git a/dlls/sxs/tests/testlib.c b/dlls/sxs/tests/testlib.c new file mode 100644 index 00000000000..a8b1c2e3b21 --- /dev/null +++ b/dlls/sxs/tests/testlib.c @@ -0,0 +1,38 @@ +/* + * Test library + * + * Copyright 2019 Nikolay Sivov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#if 0 +#pragma makedep testdll +#endif + +#include <stdio.h> +#include <windows.h> +#include <initguid.h> + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(sxs); +DEFINE_GUID(IID_CoTest, 0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33); + +HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void **obj) +{ + FIXME("clsid %s, riid %s, out %p stub!\n", debugstr_guid(clsid), debugstr_guid(riid), obj); + return CLASS_E_CLASSNOTAVAILABLE; +} diff --git a/dlls/sxs/tests/testlib.spec b/dlls/sxs/tests/testlib.spec new file mode 100644 index 00000000000..8737274e9c6 --- /dev/null +++ b/dlls/sxs/tests/testlib.spec @@ -0,0 +1 @@ +@ stdcall DllGetClassObject(ptr ptr ptr) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9632
participants (2)
-
Hans Chen -
Hans Chen (@hans.chen)