Skip to content

Commit 1a82574

Browse files
authored
Treat [NullString]::Value as the string type when resolving methods (PowerShell#18080)
1 parent f56c4ea commit 1a82574

File tree

3 files changed

+78
-23
lines changed

3 files changed

+78
-23
lines changed

src/System.Management.Automation/engine/CoreAdapter.cs

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -833,7 +833,7 @@ private static Type GetArgumentType(object argument, bool isByRefParameter)
833833
return GetArgumentType(PSObject.Base(psref.Value), isByRefParameter: false);
834834
}
835835

836-
return argument.GetType();
836+
return GetObjectType(argument, debase: false);
837837
}
838838

839839
internal static ConversionRank GetArgumentConversionRank(object argument, Type parameterType, bool isByRef, bool allowCastingToByRefLikeType)
@@ -1670,18 +1670,21 @@ private static MethodInformation FindBestMethodImpl(
16701670

16711671
internal static Type EffectiveArgumentType(object arg)
16721672
{
1673-
if (arg != null)
1673+
arg = PSObject.Base(arg);
1674+
if (arg is null)
16741675
{
1675-
arg = PSObject.Base(arg);
1676-
object[] argAsArray = arg as object[];
1677-
if (argAsArray != null && argAsArray.Length > 0 && PSObject.Base(argAsArray[0]) != null)
1676+
return typeof(LanguagePrimitives.Null);
1677+
}
1678+
1679+
if (arg is object[] array && array.Length > 0)
1680+
{
1681+
Type firstType = GetObjectType(array[0], debase: true);
1682+
if (firstType is not null)
16781683
{
1679-
Type firstType = PSObject.Base(argAsArray[0]).GetType();
16801684
bool allSameType = true;
1681-
1682-
for (int j = 1; j < argAsArray.Length; ++j)
1685+
for (int j = 1; j < array.Length; ++j)
16831686
{
1684-
if (argAsArray[j] == null || firstType != PSObject.Base(argAsArray[j]).GetType())
1687+
if (firstType != GetObjectType(array[j], debase: true))
16851688
{
16861689
allSameType = false;
16871690
break;
@@ -1693,13 +1696,19 @@ internal static Type EffectiveArgumentType(object arg)
16931696
return firstType.MakeArrayType();
16941697
}
16951698
}
1696-
1697-
return arg.GetType();
16981699
}
1699-
else
1700+
1701+
return GetObjectType(arg, debase: false);
1702+
}
1703+
1704+
internal static Type GetObjectType(object obj, bool debase)
1705+
{
1706+
if (debase)
17001707
{
1701-
return typeof(LanguagePrimitives.Null);
1708+
obj = PSObject.Base(obj);
17021709
}
1710+
1711+
return obj == NullString.Value ? typeof(string) : obj?.GetType();
17031712
}
17041713

17051714
internal static void SetReferences(object[] arguments, MethodInformation methodInformation, object[] originalArguments)

src/System.Management.Automation/engine/runtime/Binding/Binders.cs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7349,11 +7349,15 @@ internal static bool IsHomogenousArray<T>(object[] args)
73497349
return false;
73507350
}
73517351

7352-
return args.All(element =>
7353-
{
7354-
var obj = PSObject.Base(element);
7355-
return obj != null && obj.GetType().Equals(typeof(T));
7356-
});
7352+
foreach (object element in args)
7353+
{
7354+
if (Adapter.GetObjectType(element, debase: true) != typeof(T))
7355+
{
7356+
return false;
7357+
}
7358+
}
7359+
7360+
return true;
73577361
}
73587362

73597363
internal static bool IsHeterogeneousArray(object[] args)
@@ -7381,11 +7385,15 @@ internal static bool IsHeterogeneousArray(object[] args)
73817385
return true;
73827386
}
73837387

7384-
return args.Skip(1).Any(element =>
7385-
{
7386-
var obj = PSObject.Base(element);
7387-
return obj == null || !firstType.Equals(obj.GetType());
7388-
});
7388+
for (int i = 1; i < args.Length; i++)
7389+
{
7390+
if (Adapter.GetObjectType(args[i], debase: true) != firstType)
7391+
{
7392+
return true;
7393+
}
7394+
}
7395+
7396+
return false;
73897397
}
73907398

73917399
internal static object InvokeAdaptedMember(object obj, string methodName, object[] args)

test/powershell/Language/Scripting/Scripting.Followup.Tests.ps1

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,42 @@ Describe "Scripting.Followup.Tests" -Tags "CI" {
9090

9191
TestFunc2 | Should -Be @("1", "2")
9292
}
93+
94+
It "'[NullString]::Value' should be treated as string type when resolving .NET method" {
95+
$testType = 'NullStringTest' -as [type]
96+
if (-not $testType) {
97+
Add-Type -TypeDefinition @'
98+
using System;
99+
public class NullStringTest {
100+
public static string Test(bool argument)
101+
{
102+
return "bool";
103+
}
104+
105+
public static string Test(string argument)
106+
{
107+
return "string";
108+
}
109+
110+
public static string Get<T>(T argument)
111+
{
112+
string ret = typeof(T).FullName;
113+
if (argument is string[] array)
114+
{
115+
if (array[1] == null)
116+
{
117+
return ret + "; 2nd element is NULL";
118+
}
119+
}
120+
121+
return ret;
122+
}
123+
}
124+
'@
125+
}
126+
127+
[NullStringTest]::Test([NullString]::Value) | Should -BeExactly 'string'
128+
[NullStringTest]::Get([NullString]::Value) | Should -BeExactly 'System.String'
129+
[NullStringTest]::Get(@('foo', [NullString]::Value, 'bar')) | Should -BeExactly 'System.String[]; 2nd element is NULL'
130+
}
93131
}

0 commit comments

Comments
 (0)