Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,9 @@
<data name="Argument_EncodingConversionOverflowChars" xml:space="preserve">
<value>The output char buffer is too small to contain the decoded characters, encoding '{0}' fallback '{1}'.</value>
</data>
<data name="Argument_NullCharInArgument" xml:space="preserve">
<value>Process argument cannot contain a null character.</value>
</data>
<data name="Argument_NullCharInEnvVar" xml:space="preserve">
<value>Environment variable cannot contain a null character.</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -449,15 +449,29 @@ internal void ThrowIfInvalid(out bool anyRedirection, out SafeHandle[]? inherite
{
throw new InvalidOperationException(SR.ArgumentAndArgumentListInitialized);
}

// Per .NET's published security baselines, process arguments are trusted, and callers are responsible
// for their contents. The checks below are purely hygienic and should not be misconstrued as a primary
// security mitigation.
if (Arguments.Contains('\0'))
{
throw new ArgumentException(SR.Argument_NullCharInArgument, nameof(Arguments));
}

if (HasArgumentList)
{
int argumentCount = ArgumentList.Count;
for (int i = 0; i < argumentCount; i++)
{
if (ArgumentList[i] is null)
string? argument = ArgumentList[i];
if (argument is null)
{
throw new ArgumentNullException($"ArgumentList[{i}]");
}
else if (argument.Contains('\0'))
{
throw new ArgumentException(SR.Argument_NullCharInArgument, $"ArgumentList[{i}]");
}
}
}

Expand Down
21 changes: 21 additions & 0 deletions src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2637,6 +2637,27 @@ public void ArgumentListArgumentNullThrowsOnStart()
AssertExtensions.Throws<ArgumentNullException>("ArgumentList[0]", () => testProcess.Start());
}

[Fact]
public void ArgumentsContainingNullThrowsOnStart()
{
ProcessStartInfo psi = new ProcessStartInfo("unused")
{
Arguments = "argument\0suffix"
};

AssertExtensions.Throws<ArgumentException>("Arguments", () => Process.Start(psi));
}

[Fact]
public void ArgumentListArgumentContainingNullThrowsOnStart()
{
ProcessStartInfo psi = new ProcessStartInfo("unused");
psi.ArgumentList.Add("valid");
psi.ArgumentList.Add("argument\0suffix");

AssertExtensions.Throws<ArgumentException>("ArgumentList[1]", () => Process.Start(psi));
}

[ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
[PlatformSpecific(TestPlatforms.Windows)]
public void StartProcessWithSameArgumentList()
Expand Down
Loading