Correct parsing of 'Format Version' header in sln files

Prior to this change the exception on line 138 could not
be thrown, as far as I can tell. The reason for this
is that`HeaderPrefix` contained a trailing space, and we
had verified that `line` (trimmed) started with
`HeaderPrefix`. Hence `line` must contain something more
than `HeaderPrefix` otherwise the tailing space would
have been removed, so the length of `line` could not be
less than or equal to the length of `HeaderPrefix`.

Added and changed tests to ensure that both exceptions
regarding `FormatVersion` are thrown.

Fixes #5978
This commit is contained in:
Mikkel Nylander Bundgaard 2017-05-14 20:53:34 +02:00
parent 58f709ec7e
commit 80b293d4a6
3 changed files with 34 additions and 9 deletions

View file

@ -17,7 +17,9 @@ namespace Microsoft.DotNet.Cli.Sln.Internal
public const string GlobalSectionNotClosedError = "Global section not closed";
public const string FileHeaderMissingError = "File header is missing";
public const string FileHeaderMissingVersionError = "File header is missing version";
public const string FileHeaderMissingError = "Expected file header not found";
public const string ProjectSectionNotClosedError = "Project section not closed";

View file

@ -120,7 +120,7 @@ namespace Microsoft.DotNet.Cli.Sln.Internal
private void Read(TextReader reader)
{
const string HeaderPrefix = "Microsoft Visual Studio Solution File, Format Version ";
const string HeaderPrefix = "Microsoft Visual Studio Solution File, Format Version";
string line;
int curLineNum = 0;
@ -137,10 +137,10 @@ namespace Microsoft.DotNet.Cli.Sln.Internal
{
throw new InvalidSolutionFormatException(
curLineNum,
LocalizableStrings.FileHeaderMissingError);
LocalizableStrings.FileHeaderMissingVersionError);
}
FormatVersion = line.Substring(HeaderPrefix.Length);
FormatVersion = line.Substring(HeaderPrefix.Length).Trim();
_prefixBlankLines = curLineNum - 1;
}
if (line.StartsWith("# ", StringComparison.Ordinal))
@ -199,9 +199,7 @@ namespace Microsoft.DotNet.Cli.Sln.Internal
}
if (FormatVersion == null)
{
throw new InvalidSolutionFormatException(
curLineNum,
LocalizableStrings.FileHeaderMissingError);
throw new InvalidSolutionFormatException(LocalizableStrings.FileHeaderMissingError);
}
}
@ -1167,6 +1165,11 @@ namespace Microsoft.DotNet.Cli.Sln.Internal
public class InvalidSolutionFormatException : Exception
{
public InvalidSolutionFormatException(string details)
: base(details)
{
}
public InvalidSolutionFormatException(int line, string details)
: base(string.Format(LocalizableStrings.ErrorMessageFormatString, line, details))
{

View file

@ -287,9 +287,29 @@ EndGlobal
.Should().Be(SolutionModified);
}
[Theory]
[InlineData("Microsoft Visual Studio Solution File, Format Version ", 1)]
[InlineData("First Line\nMicrosoft Visual Studio Solution File, Format Version ", 2)]
[InlineData("First Line\nMicrosoft Visual Studio Solution File, Format Version \nThird Line", 2)]
[InlineData("First Line\nSecondLine\nMicrosoft Visual Studio Solution File, Format Version \nFourth Line", 3)]
public void WhenGivenASolutionWithMissingHeaderVersionItThrows(string fileContents, int lineNum)
{
var tmpFile = Temp.CreateFile();
tmpFile.WriteAllText(fileContents);
Action action = () =>
{
SlnFile.Read(tmpFile.Path);
};
action.ShouldThrow<InvalidSolutionFormatException>()
.WithMessage($"Invalid format in line {lineNum}: File header is missing version");
}
[Theory]
[InlineData("Invalid Solution")]
[InlineData("Microsoft Visual Studio Solution File, Format Version ")]
[InlineData("Invalid Solution\nSpanning Multiple Lines")]
[InlineData("Microsoft Visual\nStudio Solution File,\nFormat Version ")]
public void WhenGivenASolutionWithMissingHeaderItThrows(string fileContents)
{
var tmpFile = Temp.CreateFile();
@ -301,7 +321,7 @@ EndGlobal
};
action.ShouldThrow<InvalidSolutionFormatException>()
.WithMessage("Invalid format in line 1: File header is missing");
.WithMessage("Expected file header not found");
}
[Fact]