Skip to content

Commit

Permalink
Guard against null or blank path components when adding to module p…
Browse files Browse the repository at this point in the history
…ath (#19922)
  • Loading branch information
stevenebutler committed Jul 31, 2023
1 parent 2c6777b commit 3710671
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 14 deletions.
32 changes: 18 additions & 14 deletions src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs
Expand Up @@ -967,7 +967,7 @@ internal static string GetPersonalModulePath()
#if UNIX
return Platform.SelectProductNameForDirectory(Platform.XDG_Type.USER_MODULES);
#else
string myDocumentsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string myDocumentsPath = InternalTestHooks.SetMyDocumentsSpecialFolderToBlank ? string.Empty : Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
return string.IsNullOrEmpty(myDocumentsPath) ? null : Path.Combine(myDocumentsPath, Utils.ModuleDirectory);
#endif
}
Expand Down Expand Up @@ -1259,26 +1259,30 @@ public static string GetModulePath(string currentProcessModulePath, string hklmM
// personalModulePath
// sharedModulePath
// systemModulePath
currentProcessModulePath = AddToPath(currentProcessModulePath, personalModulePathToUse, 0);
int insertIndex = currentProcessModulePath.IndexOf(Path.PathSeparator, PathContainsSubstring(currentProcessModulePath, personalModulePathToUse));
if (insertIndex != -1)
{
// advance past the path separator
insertIndex++;
}

currentProcessModulePath = AddToPath(currentProcessModulePath, sharedModulePath, insertIndex);
insertIndex = currentProcessModulePath.IndexOf(Path.PathSeparator, PathContainsSubstring(currentProcessModulePath, sharedModulePath));
int insertIndex = 0;

currentProcessModulePath = UpdatePath(currentProcessModulePath, personalModulePathToUse, ref insertIndex);
currentProcessModulePath = UpdatePath(currentProcessModulePath, sharedModulePath, ref insertIndex);
currentProcessModulePath = UpdatePath(currentProcessModulePath, systemModulePathToUse, ref insertIndex);
}

return currentProcessModulePath;
}

private static string UpdatePath(string path, string pathToAdd, ref int insertIndex)
{
if (!string.IsNullOrEmpty(pathToAdd))
{
path = AddToPath(path, pathToAdd, insertIndex);
insertIndex = path.IndexOf(Path.PathSeparator, PathContainsSubstring(path, pathToAdd));
if (insertIndex != -1)
{
// advance past the path separator
insertIndex++;
}

currentProcessModulePath = AddToPath(currentProcessModulePath, systemModulePathToUse, insertIndex);
}

return currentProcessModulePath;
return path;
}

/// <summary>
Expand Down
3 changes: 3 additions & 0 deletions src/System.Management.Automation/engine/Utils.cs
Expand Up @@ -1559,6 +1559,9 @@ public static class InternalTestHooks
internal static bool SetConsoleWidthToZero;
internal static bool SetConsoleHeightToZero;

// Simulate 'MyDocuments' returning empty string
internal static bool SetMyDocumentsSpecialFolderToBlank;

internal static bool SetDate;

// A location to test PSEdition compatibility functionality for Windows PowerShell modules with
Expand Down
18 changes: 18 additions & 0 deletions test/powershell/engine/Module/ModulePath.Tests.ps1
Expand Up @@ -247,3 +247,21 @@ Describe "ModuleIntrinsics.GetPSModulePath API tests" -tag @('CI', 'RequireAdmin
$currentModulePathElements | Should -Contain $mPath
}
}

Describe 'ModuleIntrinsics.GetModulePath environment interaction' -tag @('CI') {

It "GetModulePath does not crash when MyDocuments special folder is empty" {
try {
[System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('SetMyDocumentsSpecialFolderToBlank', $true)
[System.Management.Automation.ModuleIntrinsics]::GetModulePath($null, $null, $null)
}
finally {
[System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('SetMyDocumentsSpecialFolderToBlank', $false)
}
}

It "GetModulePath does not crash when MyDocuments special folder is not empty" {
[System.Management.Automation.ModuleIntrinsics]::GetModulePath($null, $null, $null)
}

}

0 comments on commit 3710671

Please sign in to comment.