提交 a7be3e0d 编写于 作者: M Matt Warren

Merge pull request #2814 from mattwar/Bug864402

Guard visitors against stack overflow exceptions
......@@ -25,7 +25,7 @@ internal partial class LanguageParser : SyntaxParser
// 2. A modified version of the parser was run on the Roslyn source base and the maximum depth
// discovered was 7. Having 20 as a minimum seems reasonable in that context
//
private const int MaxUncheckedRecursionDepth = 20;
internal const int MaxUncheckedRecursionDepth = 20;
// list pools - allocators for lists that are used to build sequences of nodes. The lists
// can be reused (hence pooled) since the syntax factory methods don't keep references to
......
......@@ -2522,6 +2522,7 @@ override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode.ReplaceTriviaInListCore(
override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode.SerializeTo(System.IO.Stream stream, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> void
override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode.SyntaxTreeCore.get -> Microsoft.CodeAnalysis.SyntaxTree
override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode.WriteTo(System.IO.TextWriter writer) -> void
override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(Microsoft.CodeAnalysis.SyntaxNode node) -> Microsoft.CodeAnalysis.SyntaxNode
override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitAccessorDeclaration(Microsoft.CodeAnalysis.CSharp.Syntax.AccessorDeclarationSyntax node) -> Microsoft.CodeAnalysis.SyntaxNode
override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitAccessorList(Microsoft.CodeAnalysis.CSharp.Syntax.AccessorListSyntax node) -> Microsoft.CodeAnalysis.SyntaxNode
override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitAliasQualifiedName(Microsoft.CodeAnalysis.CSharp.Syntax.AliasQualifiedNameSyntax node) -> Microsoft.CodeAnalysis.SyntaxNode
......@@ -2726,6 +2727,7 @@ override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree.OptionsCore.get -> Micro
override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree.TryGetRootCore(out Microsoft.CodeAnalysis.SyntaxNode root) -> bool
override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree.WithChangedText(Microsoft.CodeAnalysis.Text.SourceText newText) -> Microsoft.CodeAnalysis.SyntaxTree
override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxWalker.DefaultVisit(Microsoft.CodeAnalysis.SyntaxNode node) -> void
override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxWalker.Visit(Microsoft.CodeAnalysis.SyntaxNode node) -> void
override Microsoft.CodeAnalysis.CSharp.Conversion.Equals(object obj) -> bool
override Microsoft.CodeAnalysis.CSharp.Conversion.GetHashCode() -> int
override Microsoft.CodeAnalysis.CSharp.Conversion.ToString() -> string
......
......@@ -5,6 +5,7 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using System;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp
{
......@@ -26,6 +27,29 @@ public virtual bool VisitIntoStructuredTrivia
get { return _visitIntoStructuredTrivia; }
}
private int _recursionDepth;
public override SyntaxNode Visit(SyntaxNode node)
{
if (node != null)
{
_recursionDepth++;
if (_recursionDepth > Syntax.InternalSyntax.LanguageParser.MaxUncheckedRecursionDepth)
{
PortableShim.RuntimeHelpers.EnsureSufficientExecutionStack();
}
var result = ((CSharpSyntaxNode)node).Accept(this);
_recursionDepth--;
return result;
}
else
{
return null;
}
}
public virtual SyntaxToken VisitToken(SyntaxToken token)
{
// PERF: This is a hot method, so it has been written to minimize the following:
......
......@@ -3,6 +3,7 @@
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp
{
......
......@@ -4,6 +4,7 @@
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp
{
......@@ -20,6 +21,24 @@ protected CSharpSyntaxWalker(SyntaxWalkerDepth depth = SyntaxWalkerDepth.Node)
this.Depth = depth;
}
private int _recursionDepth;
public override void Visit(SyntaxNode node)
{
if (node != null)
{
_recursionDepth++;
if (_recursionDepth > Syntax.InternalSyntax.LanguageParser.MaxUncheckedRecursionDepth)
{
PortableShim.RuntimeHelpers.EnsureSufficientExecutionStack();
}
((CSharpSyntaxNode)node).Accept(this);
_recursionDepth--;
}
}
public override void DefaultVisit(SyntaxNode node)
{
var childCnt = node.ChildNodesAndTokens().Count;
......
......@@ -930,6 +930,7 @@
<Compile Include="Syntax\LambdaUtilities.vb" />
<Compile Include="Syntax\TypeBlockSyntax.vb" />
<Compile Include="Syntax\TypeStatementSyntax.vb" />
<Compile Include="Syntax\VisualBasicSyntaxVisitor.vb" />
<Compile Include="Syntax\VisualBasicWarningStateMap.vb" />
<Compile Include="Syntax\VisualBasicLineDirectiveMap.vb" />
<Compile Include="Syntax\VisualBasicSyntaxNode.vb" />
......@@ -1033,4 +1034,4 @@
<Import Project="..\..\..\..\build\VSL.Imports.Closed.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
</ImportGroup>
</Project>
</Project>
\ No newline at end of file
......@@ -50,7 +50,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
Try
_recursionDepth += 1
If _recursionDepth >= _maxUncheckedRecursionDepth Then
If _recursionDepth >= MaxUncheckedRecursionDepth Then
PortableShim.RuntimeHelpers.EnsureSufficientExecutionStack()
End If
......
......@@ -21,7 +21,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
End Enum
' Keep this value in sync with C# LanguageParser
Private Const _maxUncheckedRecursionDepth As Integer = 30
Friend Const MaxUncheckedRecursionDepth As Integer = 20
Private _allowLeadingMultilineTrivia As Boolean = True
Private _hadImplicitLineContinuation As Boolean = False
......@@ -856,7 +856,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
Try
_recursionDepth += 1
If _recursionDepth >= _maxUncheckedRecursionDepth Then
If _recursionDepth >= MaxUncheckedRecursionDepth Then
PortableShim.RuntimeHelpers.EnsureSufficientExecutionStack()
End If
......
......@@ -4437,6 +4437,7 @@ Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxNode.ReplaceTrivia
Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxNode.SerializeTo(stream As System.IO.Stream, cancellationToken As System.Threading.CancellationToken = Nothing) -> Void
Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxNode.SyntaxTreeCore() -> Microsoft.CodeAnalysis.SyntaxTree
Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxNode.WriteTo(writer As System.IO.TextWriter) -> Void
Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxRewriter.Visit(node As Microsoft.CodeAnalysis.SyntaxNode) -> Microsoft.CodeAnalysis.SyntaxNode
Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxRewriter.VisitAccessorBlock(node As Microsoft.CodeAnalysis.VisualBasic.Syntax.AccessorBlockSyntax) -> Microsoft.CodeAnalysis.SyntaxNode
Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxRewriter.VisitAccessorStatement(node As Microsoft.CodeAnalysis.VisualBasic.Syntax.AccessorStatementSyntax) -> Microsoft.CodeAnalysis.SyntaxNode
Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxRewriter.VisitAddRemoveHandlerStatement(node As Microsoft.CodeAnalysis.VisualBasic.Syntax.AddRemoveHandlerStatementSyntax) -> Microsoft.CodeAnalysis.SyntaxNode
......@@ -4696,6 +4697,7 @@ Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxTree.OptionsCore()
Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxTree.TryGetRootCore(ByRef root As Microsoft.CodeAnalysis.SyntaxNode) -> Boolean
Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxTree.WithChangedText(newText As Microsoft.CodeAnalysis.Text.SourceText) -> Microsoft.CodeAnalysis.SyntaxTree
Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxWalker.DefaultVisit(node As Microsoft.CodeAnalysis.SyntaxNode) -> Void
Overrides Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxWalker.Visit(node As Microsoft.CodeAnalysis.SyntaxNode) -> Void
ReadOnly Microsoft.CodeAnalysis.VisualBasic.AggregateClauseSymbolInfo.Select1 -> Microsoft.CodeAnalysis.SymbolInfo
ReadOnly Microsoft.CodeAnalysis.VisualBasic.AggregateClauseSymbolInfo.Select2 -> Microsoft.CodeAnalysis.SymbolInfo
ReadOnly Microsoft.CodeAnalysis.VisualBasic.CollectionRangeVariableSymbolInfo.AsClauseConversion -> Microsoft.CodeAnalysis.SymbolInfo
......@@ -29,6 +29,25 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Get
End Property
Private _recursionDepth As Integer
Public Overrides Function Visit(node As SyntaxNode) As SyntaxNode
If node IsNot Nothing Then
_recursionDepth += 1
If _recursionDepth > Syntax.InternalSyntax.Parser.MaxUncheckedRecursionDepth Then
PortableShim.RuntimeHelpers.EnsureSufficientExecutionStack()
End If
Dim result = DirectCast(node, VisualBasicSyntaxNode).Accept(Me)
_recursionDepth -= 1
Return result
Else
Return node
End If
End Function
Public Overridable Function VisitToken(token As SyntaxToken) As SyntaxToken
Dim leading = Me.VisitList(token.LeadingTrivia)
Dim trailing = Me.VisitList(token.TrailingTrivia)
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic
''' <summary>
''' Represents a <see cref="SyntaxNode"/> visitor that visits only the single SyntaxNode
''' passed into its <see cref="Visit(SyntaxNode)"/> method.
''' </summary>
Partial Public MustInherit Class VisualBasicSyntaxVisitor
Public Overridable Sub Visit(ByVal node As SyntaxNode)
If node IsNot Nothing Then
DirectCast(node, VisualBasicSyntaxNode).Accept(Me)
End If
End Sub
Public Overridable Sub DefaultVisit(ByVal node As SyntaxNode)
End Sub
End Class
''' <summary>
''' Represents a <see cref="SyntaxNode"/> visitor that visits only the single SyntaxNode
''' passed into its <see cref="Visit(SyntaxNode)"/> method and produces
''' a value of the type specified by the <typeparamref name="TResult"/> parameter.
''' </summary>
''' <typeparam name="TResult">
''' The type of the return value of this visitor's Visit method.
''' </typeparam>
Partial Public MustInherit Class VisualBasicSyntaxVisitor(Of TResult)
Public Overridable Function Visit(ByVal node As SyntaxNode) As TResult
If node IsNot Nothing Then
Return DirectCast(node, VisualBasicSyntaxNode).Accept(Me)
End If
Return Nothing
End Function
Public Overridable Function DefaultVisit(ByVal node As SyntaxNode) As TResult
Return Nothing
End Function
End Class
End Namespace
......@@ -18,6 +18,22 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Me.Depth = depth
End Sub
Private _recursionDepth As Integer
Public Overrides Sub Visit(node As SyntaxNode)
If node IsNot Nothing Then
_recursionDepth += 1
If _recursionDepth > Syntax.InternalSyntax.Parser.MaxUncheckedRecursionDepth Then
PortableShim.RuntimeHelpers.EnsureSufficientExecutionStack()
End If
DirectCast(node, VisualBasicSyntaxNode).Accept(Me)
_recursionDepth -= 1
End If
End Sub
Public Overrides Sub DefaultVisit(node As SyntaxNode)
Dim list = node.ChildNodesAndTokens()
Dim childCnt = list.Count
......@@ -70,22 +86,4 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End If
End Sub
End Class
''' <summary>
''' Represents a <see cref="SyntaxNode"/> visitor that visits only the single SyntaxNode
''' passed into its <see cref="Visit(SyntaxNode)"/> method.
''' </summary>
Partial Public MustInherit Class VisualBasicSyntaxVisitor
End Class
''' <summary>
''' Represents a <see cref="SyntaxNode"/> visitor that visits only the single SyntaxNode
''' passed into its <see cref="Visit(SyntaxNode)"/> method and produces
''' a value of the type specified by the <typeparamref name="TResult"/> parameter.
''' </summary>
''' <typeparam name="TResult">
''' The type of the return value this visitor's Visit method.
''' </typeparam>
Partial Public MustInherit Class VisualBasicSyntaxVisitor(Of TResult)
End Class
End Namespace
......@@ -1032,22 +1032,6 @@ Friend Class RedNodeWriter
Private Sub GenerateVisitorClass(withResult As Boolean)
_writer.WriteLine(" Public MustInherit Class {0}{1}", Ident(_parseTree.VisitorName), If(withResult, "(Of TResult)", ""))
' Basic Visit method that dispatches.
_writer.WriteLine(" Public Overridable {0} Visit(ByVal node As SyntaxNode){1}",
If(withResult, "Function", "Sub"),
If(withResult, " As TResult", ""))
_writer.WriteLine(" If node Is Nothing")
_writer.WriteLine(" Return{0}", If(withResult, " Nothing", ""))
_writer.WriteLine(" End If")
_writer.WriteLine("")
_writer.WriteLine(" {0}DirectCast(node, VisualBasicSyntaxNode).Accept(Me){1}", If(withResult, "Return ", ""), If(withResult, "", ": Return"))
_writer.WriteLine(" End {0}", If(withResult, "Function", "Sub"))
_writer.WriteLine(" Public Overridable {0} DefaultVisit(ByVal node As SyntaxNode){1}",
If(withResult, "Function", "Sub"),
If(withResult, " As TResult", ""))
_writer.WriteLine(" End {0}", If(withResult, "Function", "Sub"))
For Each nodeStructure In _parseTree.NodeStructures.Values
If Not nodeStructure.Abstract Then
GenerateVisitorMethod(nodeStructure, withResult)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册