-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
Brief description of your issue
winget-cli/src/AppInstallerRepositoryCore/Microsoft/PredefinedInstalledSourceFactory.cpp
Line 363 in 6096b5e
| static CachedInstalledIndex s_installedIndex; |
When connecting to a composite catalog consisting of a package catalog reference and CompositeSearchBehavior::RemotePackagesFromAllCatalogs, GetCachedInstalledIndex() is eventually called as the source is opened, leading to a CachedInstalledIndex static object being created. However, CachedInstalledIndex contains an event revoker, which contains a weak reference to a Windows::ApplicationModel::PackageCatalog object, which does not live in WindowsPackageManager.dll, but Windows.ApplicationModel.dll, a system DLL.
If the application calls CoUninitialize for the last time, COM unloads Windows.ApplicationModel.dll, leaving the weak reference pointing to a destroyed object in an unloaded DLL. The static variable eventually gets destroyed on process exit, causing the event revoker to attempt to resolve the weak reference, causing an access violation.
(Essentially, this is what Raymond Chen warned against - the object the weak reference refers to is not implemented n the same DLL as the weak reference.)
Steps to reproduce
- Create a
PackageManagerobject. - Create a composite package catalog with a package catalog reference and
CompositeSearchBehavior::RemotePackagesFromAllCatalogs. - Connect to the catalog. The static variable has now been initialized.
- Call
CoUninitialize.Windows.ApplicationModel.dllwill be unloaded, which can be verified bysxe ud:Windows_ApplicationModelin WinDbg. - Exit the process. An access violation will occur in
winrt::weak_ref<winrt::Windows::ApplicationModel::IPackageCatalog::get:
ZIP file containing a reproducer
Expected behavior
The application will cleanly shut down with no access violation.
Actual behavior
An access violation occurs on process exit:
00 WindowsPackageManager!winrt::weak_ref<winrt::Windows::ApplicationModel::IPackageCatalog>::get
01 WindowsPackageManager!winrt::impl::event_revoker<winrt::Windows::ApplicationModel::IPackageCatalog,&winrt::impl::abi<winrt::Windows::ApplicationModel::IPackageCatalog,void>::type::`vcall'{60}'>::{dtor}
02 WindowsPackageManager!`AppInstaller::Repository::Microsoft::`anonymous namespace'::PredefinedInstalledSourceReference::GetCachedInstalledIndex'::`2'::`dynamic atexit destructor for 's_installedIndex''
03 ucrtbase!<lambda_f03950bc5685219e0bcd2087efbe011e>::operator()
04 ucrtbase!__crt_seh_guarded_call<int>::operator()<<lambda_69a2805e680e0e292e8ba93315fe43a8>,<lambda_f03950bc5685219e0bcd2087efbe011e> &,<lambda_03fcd07e894ec930e3f35da366ca99d6> >
05 ucrtbase!_execute_onexit_table
06 WindowsPackageManager!__scrt_dllmain_uninitialize_c
07 WindowsPackageManager!dllmain_crt_process_detach
08 WindowsPackageManager!dllmain_crt_dispatch
09 WindowsPackageManager!dllmain_dispatch
0a WindowsPackageManager!_DllMainCRTStartup
0b ntdll!LdrxCallInitRoutine
0c ntdll!LdrpCallInitRoutine
0d ntdll!LdrShutdownProcess
0e ntdll!RtlExitUserProcess
0f KERNEL32!ExitProcessImplementation
Environment
Microsoft.WindowsPackageManager.InProcCom.1.10.340 from NuGet