Skip to content

Commit

Permalink
Harden ParseEmbeddedStatement
Browse files Browse the repository at this point in the history
The consumers of ParseEmbeddedStatement depend on it having a non-null return.  Yet it directly returns the result of ParseStatementCore which can validly return null values in error conditions.  In the case that does happen return an empty statement with a diagnostic.
  • Loading branch information
jaredpar committed Sep 20, 2016
1 parent ce98080 commit d689f37
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 1 deletion.
11 changes: 10 additions & 1 deletion src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
Expand Up @@ -7457,10 +7457,19 @@ private StatementSyntax ParseEmbeddedStatement(bool complexCheck)
statement = this.ParseStatementCore();
}

// The consumers of embedded statements are expecting to receive a non-null statement yet there are
// several error conditions that can lead ParseStatementCore to return null. When that occurs
// create an empty error Statement and return it to the caller.
if (statement == null)
{
Debug.Assert(CurrentToken.Kind != SyntaxKind.SemicolonToken);
statement = SyntaxFactory.EmptyStatement(EatToken(SyntaxKind.SemicolonToken));
}

// An "embedded" statement is simply a statement that is not a labelled
// statement or a declaration statement. Parse a normal statement and post-
// check for the error case.
switch (statement?.Kind)
switch (statement.Kind)
{
case SyntaxKind.LabeledStatement:
case SyntaxKind.LocalDeclarationStatement:
Expand Down
34 changes: 34 additions & 0 deletions src/Compilers/CSharp/Test/Syntax/Parsing/StatementParsingTests.cs
Expand Up @@ -2623,6 +2623,40 @@ static void Test(int arg1, (byte, byte) arg2)
Assert.Equal(false, tree.GetRoot().ContainsDiagnostics);
}

[Fact]
[WorkItem(684860, "https://devdiv.visualstudio.com/DevDiv/_workitems/edit/266237")]
public void DevDiv266237()
{
var source = @"
class Program
{
static void Go()
{
using (var p = new P
{
}
protected override void M()
{
}
}
";

var tree = SyntaxFactory.ParseSyntaxTree(source, options: TestOptions.Regular);
tree.GetDiagnostics(tree.GetRoot()).Verify(
// (9,10): error CS1026: ) expected
// }
CSharpTestBase.Diagnostic(ErrorCode.ERR_CloseParenExpected, "").WithLocation(9, 10),
// (9,10): error CS1002: ; expected
// }
CSharpTestBase.Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(9, 10),
// (9,10): error CS1513: } expected
// }
CSharpTestBase.Diagnostic(ErrorCode.ERR_RbraceExpected, "").WithLocation(9, 10));
}

private sealed class TokenAndTriviaWalker : CSharpSyntaxWalker
{
public int Tokens;
Expand Down

0 comments on commit d689f37

Please sign in to comment.