winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 86fda9f51fcd98b98ea4d7216edc4d057d221093
parent 2f344f090bce1dd633d2a655f61d5b5c16a702f0
Author: yao-msft <50888816+yao-msft@users.noreply.github.com>
Date:   Tue, 18 Mar 2025 17:29:25 -0700

Fix DynamicProcessor crash when working on individual units without a set (#5304)

Added unit test. Manually validated as well.
Diffstat:
Msrc/AppInstallerCLICore/ConfigurationDynamicRuntimeFactory.cpp | 63+++++++++++++++++++++++++++++++++++++--------------------------
Msrc/Microsoft.Management.Configuration.UnitTests/Tests/ConfigurationMixedElevationTests.cs | 30++++++++++++++++++++++++++++++
2 files changed, 67 insertions(+), 26 deletions(-)

diff --git a/src/AppInstallerCLICore/ConfigurationDynamicRuntimeFactory.cpp b/src/AppInstallerCLICore/ConfigurationDynamicRuntimeFactory.cpp @@ -163,9 +163,12 @@ namespace AppInstaller::CLI::ConfigurationRemoting m_dynamicFactory(std::move(dynamicFactory)), m_configurationSet(configurationSet) { #ifndef AICLI_DISABLE_TEST_HOOKS - m_enableTestMode = GetConfigurationSetMetadataOverride(m_configurationSet, EnableTestModeTestGuid); - m_enableRestrictedIntegrityLevel = GetConfigurationSetMetadataOverride(m_configurationSet, EnableRestrictedIntegrityLevelTestGuid); - m_forceHighIntegrityLevelUnits = GetConfigurationSetMetadataOverride(m_configurationSet, ForceHighIntegrityLevelUnitsTestGuid); + if (m_configurationSet) + { + m_enableTestMode = GetConfigurationSetMetadataOverride(m_configurationSet, EnableTestModeTestGuid); + m_enableRestrictedIntegrityLevel = GetConfigurationSetMetadataOverride(m_configurationSet, EnableRestrictedIntegrityLevelTestGuid); + m_forceHighIntegrityLevelUnits = GetConfigurationSetMetadataOverride(m_configurationSet, ForceHighIntegrityLevelUnitsTestGuid); + } m_currentIntegrityLevel = m_enableTestMode ? Security::IntegrityLevel::Medium : Security::GetEffectiveIntegrityLevel(); #else @@ -173,32 +176,36 @@ namespace AppInstaller::CLI::ConfigurationRemoting #endif m_setIntegrityLevel = m_currentIntegrityLevel; - m_setIntegrityLevel = SecurityContextToIntegrityLevel(m_configurationSet.Environment().Context()); - // Check for multiple integrity level requirements - bool multipleIntegrityLevels = false; - bool higherIntegrityLevelsThanCurrent = false; - for (const auto& environment : m_configurationSet.GetUnitEnvironments()) + if (m_configurationSet) { - auto integrityLevel = SecurityContextToIntegrityLevel(environment.Context()); - if (integrityLevel != m_currentIntegrityLevel) - { - multipleIntegrityLevels = true; + m_setIntegrityLevel = SecurityContextToIntegrityLevel(m_configurationSet.Environment().Context()); - if (ToIntegral(m_currentIntegrityLevel) < ToIntegral(integrityLevel)) + // Check for multiple integrity level requirements + bool multipleIntegrityLevels = false; + bool higherIntegrityLevelsThanCurrent = false; + for (const auto& environment : m_configurationSet.GetUnitEnvironments()) + { + auto integrityLevel = SecurityContextToIntegrityLevel(environment.Context()); + if (integrityLevel != m_currentIntegrityLevel) { - higherIntegrityLevelsThanCurrent = true; - break; + multipleIntegrityLevels = true; + + if (ToIntegral(m_currentIntegrityLevel) < ToIntegral(integrityLevel)) + { + higherIntegrityLevelsThanCurrent = true; + break; + } } } - } - // Prevent supplied parameters from crossing integrity levels - for (const auto& parameter : m_configurationSet.Parameters()) - { - if (parameter.ProvidedValue() != nullptr) + // Prevent supplied parameters from crossing integrity levels + for (const auto& parameter : m_configurationSet.Parameters()) { - THROW_HR_IF(WINGET_CONFIG_ERROR_PARAMETER_INTEGRITY_BOUNDARY, higherIntegrityLevelsThanCurrent || (multipleIntegrityLevels && parameter.IsSecure())); + if (parameter.ProvidedValue() != nullptr) + { + THROW_HR_IF(WINGET_CONFIG_ERROR_PARAMETER_INTEGRITY_BOUNDARY, higherIntegrityLevelsThanCurrent || (multipleIntegrityLevels && parameter.IsSecure())); + } } } @@ -219,13 +226,16 @@ namespace AppInstaller::CLI::ConfigurationRemoting std::call_once(m_createUnitSetProcessorsOnce, [&]() { - for (const auto& environment : m_configurationSet.GetUnitEnvironments()) + if (m_configurationSet) { - Security::IntegrityLevel requiredIntegrityLevel = SecurityContextToIntegrityLevel(environment.Context()); - - if (m_setProcessors.find(requiredIntegrityLevel) == m_setProcessors.end()) + for (const auto& environment : m_configurationSet.GetUnitEnvironments()) { - CreateSetProcessorForIntegrityLevel(requiredIntegrityLevel); + Security::IntegrityLevel requiredIntegrityLevel = SecurityContextToIntegrityLevel(environment.Context()); + + if (m_setProcessors.find(requiredIntegrityLevel) == m_setProcessors.end()) + { + CreateSetProcessorForIntegrityLevel(requiredIntegrityLevel); + } } } }); @@ -240,6 +250,7 @@ namespace AppInstaller::CLI::ConfigurationRemoting auto itr = m_setProcessors.find(requiredIntegrityLevel); if (itr == m_setProcessors.end()) { + THROW_WIN32_IF_MSG(ERROR_NOT_SUPPORTED, !m_configurationSet, "Using configuration unit integrity level other than current level without a configuration set is not supported."); itr = CreateSetProcessorForIntegrityLevel(requiredIntegrityLevel); } diff --git a/src/Microsoft.Management.Configuration.UnitTests/Tests/ConfigurationMixedElevationTests.cs b/src/Microsoft.Management.Configuration.UnitTests/Tests/ConfigurationMixedElevationTests.cs @@ -269,5 +269,35 @@ namespace Microsoft.Management.Configuration.UnitTests.Tests // Once they are implemented, swap to the appropriate error mechanism for the parameter integrity boundary. Assert.Throws<NotImplementedException>(() => processor.ApplySet(configurationSet, ApplyConfigurationSetFlags.None)); } + + /// <summary> + /// Verifies that DynamicFactoryProcessors do not break on empty set when working with only units. + /// </summary> + /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns> + [Fact] + public async Task CreateDynamicFactoryProcessorsWithEmptyConfigurationSet() + { + string resourceName = "E2ETestResourcePID"; + string moduleName = "xE2ETestResource"; + Version version = new Version("0.0.0.1"); + + string tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + Directory.CreateDirectory(tempDirectory); + + ConfigurationUnit unit = this.ConfigurationUnit(); + unit.Metadata.Add("version", version.ToString()); + unit.Metadata.Add("module", moduleName); + unit.Settings.Add("directoryPath", tempDirectory); + unit.Type = resourceName; + unit.Intent = ConfigurationUnitIntent.Inform; + + IConfigurationSetProcessorFactory dynamicFactory = await this.fixture.ConfigurationStatics.CreateConfigurationSetProcessorFactoryAsync(Helpers.Constants.DynamicRuntimeHandlerIdentifier); + + ConfigurationProcessor processor = this.CreateConfigurationProcessorWithDiagnostics(dynamicFactory); + + var result = await processor.GetUnitSettingsAsync(unit); + + Assert.NotNull(result); + } } }