Skip to content

Commit f61f235

Browse files
committed
Fix: escape MSBuild special characters in MsBuildArgument with unit test
1 parent 8b14cbb commit f61f235

File tree

2 files changed

+45
-2
lines changed

2 files changed

+45
-2
lines changed

src/BenchmarkDotNet/Jobs/Argument.cs

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
24
using JetBrains.Annotations;
35

46
namespace BenchmarkDotNet.Jobs
57
{
6-
public abstract class Argument: IEquatable<Argument>
8+
public abstract class Argument : IEquatable<Argument>
79
{
810
[PublicAPI] public string TextRepresentation { get; }
911

@@ -47,6 +49,40 @@ public MonoArgument(string value) : base(value)
4749
[PublicAPI]
4850
public class MsBuildArgument : Argument
4951
{
50-
public MsBuildArgument(string value) : base(value) { }
52+
private static readonly Dictionary<char, string> MsBuildEscapes = new ()
53+
{
54+
{ '%', "%25" },
55+
{ '$', "%24" },
56+
{ '@', "%40" },
57+
{ '\'', "%27" },
58+
{ '(', "%28" },
59+
{ ')', "%29" },
60+
{ ';', "%3B" },
61+
{ '?', "%3F" },
62+
{ '*', "%2A" }
63+
};
64+
65+
private static string EscapeMsBuildSpecialChars(string value)
66+
{
67+
if (string.IsNullOrEmpty(value))
68+
return value;
69+
var sb = new StringBuilder(value.Length);
70+
71+
foreach (char c in value)
72+
{
73+
if (MsBuildEscapes.TryGetValue(c, out string escaped))
74+
{
75+
sb.Append(escaped);
76+
}
77+
else
78+
{
79+
sb.Append(c);
80+
}
81+
}
82+
83+
return sb.ToString();
84+
}
85+
86+
public MsBuildArgument(string value) : base(EscapeMsBuildSpecialChars(value)) { }
5187
}
5288
}

tests/BenchmarkDotNet.IntegrationTests.ManualRunning/MsBuildArgumentTests.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ public void MultipleProcessesAreBuiltWithCorrectProperties()
4343
CanExecute<PropertyDefine>(config);
4444
}
4545

46+
[Fact]
47+
public void EscapesSemicolonInDefineConstants()
48+
{
49+
var arg = new MsBuildArgument("/p:DefineConstants=TEST1;TEST2");
50+
Assert.Equal("/p:DefineConstants=TEST1%3BTEST2", arg.ToString());
51+
}
52+
4653
public class PropertyDefine
4754
{
4855
private const bool customPropWasSet =

0 commit comments

Comments
 (0)