Skip to content

Commit 616293e

Browse files
robertcoltheartarturcic
authored andcommitted
fix: tighten parsing of label formats
1 parent 8847f7a commit 616293e

5 files changed

Lines changed: 36 additions & 22 deletions

File tree

src/GitVersion.Core.Tests/Formatting/LabelTokenizerTests.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ public class LabelTokenizerTests
3939
[TestCase("Prop ?? literal ?? ? fallback")]
4040
[TestCase("Prop ? fallback")]
4141
[TestCase("Prop ?? fall?back")]
42+
[TestCase("Prop ?? fallback ??")]
43+
[TestCase("Prop ?? fallback ?? ")]
4244
public void ParseTokens_MalformedIdentifiers_Throws(string input) => AssertThrows(input);
4345

4446
private static void AssertTokens(string input, string[] expected)

src/GitVersion.Core/Extensions/ConfigurationExtensions.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,10 @@ private static Dictionary<string, object> BuildLabelPlaceholders(string? regular
154154
if (!match.Success)
155155
return placeholders;
156156

157-
foreach (var groupName in regex.GetGroupNames().Skip(1))
157+
var namedGroups = regex.GetGroupNames()
158+
.Where(name => !int.TryParse(name, out _));
159+
160+
foreach (var groupName in namedGroups)
158161
{
159162
var groupValue = match.Groups[groupName].Value;
160163

src/GitVersion.Core/Formatting/LabelTokenizer.cs

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ internal class LabelTokenizer(string input)
99
public IEnumerable<LabelToken> ParseTokens()
1010
{
1111
var tokens = new List<LabelToken>();
12+
var separatedParsed = false;
1213

1314
SkipWhitespace();
1415

15-
while (index < input.Length)
16+
while (this.index < input.Length)
1617
{
1718
var identifier = ParseIdentifier();
1819

@@ -25,10 +26,16 @@ public IEnumerable<LabelToken> ParseTokens()
2526

2627
tokens.Add(ParseToken(identifier));
2728

28-
ParseSeparator();
29+
separatedParsed = ParseSeparator();
30+
2931
SkipWhitespace();
3032
}
3133

34+
if (separatedParsed)
35+
{
36+
throw new FormatException("Invalid format sequence, expected identifier after '??' separator");
37+
}
38+
3239
return tokens;
3340
}
3441

@@ -37,9 +44,9 @@ private static LabelToken ParseToken(string identifier)
3744
if (identifier.StartsWith("env:", StringComparison.OrdinalIgnoreCase))
3845
{
3946
var name = identifier[4..];
40-
var (environmentName, environemntFormat) = ParseKeyAndFormat(name);
47+
var (environmentName, environmentFormat) = ParseKeyAndFormat(name);
4148

42-
return new LabelToken(environmentName, LabelTokenType.Environment, environemntFormat);
49+
return new LabelToken(environmentName, LabelTokenType.Environment, environmentFormat);
4350
}
4451

4552
if (identifier.StartsWith('"') && identifier.EndsWith('"'))
@@ -79,9 +86,9 @@ private string ParseIdentifier()
7986
value.Append('"');
8087
}
8188

82-
while (index < input.Length)
89+
while (this.index < input.Length)
8390
{
84-
var c = input[index];
91+
var c = input[this.index];
8592

8693
if (!inQuotes && IsQuote())
8794
{
@@ -103,12 +110,12 @@ private string ParseIdentifier()
103110
if (IsEscapeQuote())
104111
{
105112
value.Append('"');
106-
index += 2;
113+
this.index += 2;
107114
}
108115
else
109116
{
110117
value.Append(c);
111-
index++;
118+
this.index++;
112119
}
113120
}
114121

@@ -120,48 +127,50 @@ private string ParseIdentifier()
120127
return value.ToString();
121128
}
122129

123-
private void ParseSeparator()
130+
private bool ParseSeparator()
124131
{
125132
var seen = 0;
126133

127134
while (this.index < input.Length && seen < 2)
128135
{
129-
if (input[index] != '?')
136+
if (input[this.index] != '?')
130137
{
131138
throw new FormatException("Expected '??' separator");
132139
}
133140

134141
seen++;
135-
index++;
142+
this.index++;
136143
}
144+
145+
return seen == 2;
137146
}
138147

139148
private void SkipWhitespace()
140149
{
141-
while (index < input.Length)
150+
while (this.index < input.Length)
142151
{
143-
if (!char.IsWhiteSpace(input[index]))
152+
if (!char.IsWhiteSpace(input[this.index]))
144153
{
145154
break;
146155
}
147156

148-
index++;
157+
this.index++;
149158
}
150159
}
151160

152161
private bool ParseQuote()
153162
{
154163
if (IsQuote())
155164
{
156-
index++;
165+
this.index++;
157166

158167
return true;
159168
}
160169

161170
return false;
162171
}
163172

164-
private bool IsQuote() => index < input.Length && input[index] == '"';
173+
private bool IsQuote() => this.index < input.Length && input[this.index] == '"';
165174

166-
private bool IsEscapeQuote() => this.index + 1 < input.Length && input[index] == '\\' && input[this.index + 1] == '"';
175+
private bool IsEscapeQuote() => this.index + 1 < input.Length && input[this.index] == '\\' && input[this.index + 1] == '"';
167176
}

src/GitVersion.Core/Formatting/StringFormatWithExtension.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,10 @@ private static string EvaluateMatch(string input, Func<string, string?> memberEv
9595
}
9696

9797
var value = token.Type == LabelTokenType.Environment
98-
? environment.GetEnvironmentVariable(token.Name)
98+
? environment.GetEnvironmentVariable(InputSanitizer.SanitizeEnvVarName(token.Name))
9999
: memberEvaluator(token.Name);
100100

101-
if (!string.IsNullOrEmpty(value) && !string.IsNullOrEmpty(token.Format))
101+
if (value is not null && !string.IsNullOrEmpty(token.Format))
102102
{
103103
if (ValueFormatter.Default.TryFormat(value, InputSanitizer.SanitizeFormat(token.Format), out var formatted))
104104
{
@@ -108,7 +108,7 @@ private static string EvaluateMatch(string input, Func<string, string?> memberEv
108108
return value;
109109
}
110110

111-
if (!string.IsNullOrEmpty(value))
111+
if (value is not null)
112112
{
113113
return value;
114114
}

src/GitVersion.Core/VersionCalculation/VariableProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public GitVersionVariables GetVariablesFor(
8484
formattedString = formatString.FormatWith(source, this.environment)
8585
.RegexReplace(RegexPatterns.Output.SanitizeAssemblyInfoRegexPattern, "-");
8686
}
87-
catch (ArgumentException exception)
87+
catch (Exception exception) when (exception is ArgumentException or FormatException)
8888
{
8989
throw new WarningException($"Unable to format {formatVarName}. Check your format string: {exception.Message}");
9090
}

0 commit comments

Comments
 (0)