[PATCH 0/1] 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); //... ``` 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. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9632
From: Hans Chen <hxchennz(a)gmail.com> --- dlls/sxs/sxs.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 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); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9632
This needs a test I think. For example, isn't clrdata_len == 0 case the same as ERROR_NOT_FOUND for when section does not exist at all. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9632#note_124280
@nsivov `clrdata` represents additional fields only for `clrClass` from component manifest file, which is for [.NET Framework-Based COM Component](https://learn.microsoft.com/en-us/dotnet/framework/interop/configure-net-fra...). The example code in this MR description is about calling COM dll from .NET application, so it uses `comClass` not `clrClass` in application manifest file. Besides, the [official doc](https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema) shows only `clrClass` has a name field, but `comClass` doesn't. And on [/dlls/ntdll/actctx.c line 4412](https://gitlab.winehq.org/wine/wine/-/blob/4dfbf077cf708e4bbffa8e086d78d6652...), `clrdata_offset` is set to zero if the name field is not set. [/dlls/ntdll/actctx.c line 4433](https://gitlab.winehq.org/wine/wine/-/blob/4dfbf077cf708e4bbffa8e086d78d6652...) checks `clrdata_offset` first, then set [/dlls/ntdll/actctx.c line 4449](https://gitlab.winehq.org/wine/wine/-/blob/4dfbf077cf708e4bbffa8e086d78d6652...) `clrdata_len`. So `clrdata_len` doesn't mean `ERROR_NOT_FOUND`. I've tested my .NET application working locally. I'm not sure how to add .NET C# code to the test pipeline here. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9632#note_124286
On Mon Dec 1 10:15:42 2025 +0000, Hans Chen wrote:
@nsivov `clrdata` represents additional fields only for `clrClass` from component manifest file, which is for [.NET Framework-Based COM Component](https://learn.microsoft.com/en-us/dotnet/framework/interop/configure-net-fra...). The example code in this MR description is about calling COM dll from .NET application, so it uses `comClass` not `clrClass` in application manifest file. Besides, the [official doc](https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-file-schema) shows only `clrClass` has a name field, but `comClass` doesn't. And on [/dlls/ntdll/actctx.c line 4412](https://gitlab.winehq.org/wine/wine/-/blob/4dfbf077cf708e4bbffa8e086d78d6652...), `clrdata_offset` is set to zero if the name field is not set. [/dlls/ntdll/actctx.c line 4433](https://gitlab.winehq.org/wine/wine/-/blob/4dfbf077cf708e4bbffa8e086d78d6652...) checks `clrdata_offset` first, then set [/dlls/ntdll/actctx.c line 4449](https://gitlab.winehq.org/wine/wine/-/blob/4dfbf077cf708e4bbffa8e086d78d6652...) `clrdata_len`. So `clrdata_len` doesn't mean `ERROR_NOT_FOUND`. I've tested my .NET application working locally. I'm not sure how to add .NET C# code to the test pipeline here. You don't need C# code for that, tests are in sxs/tests/.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/9632#note_124289
participants (3)
-
Hans Chen -
Hans Chen (@hans.chen) -
Nikolay Sivov (@nsivov)