C#: Limit ancestor traversal for 'if' and 'elif' lookup

This commit is contained in:
Tamas Vajk
2021-01-26 16:32:05 +01:00
parent 2b7cc15757
commit a5dec5b4aa
3 changed files with 19 additions and 27 deletions

View File

@@ -534,7 +534,7 @@ namespace Semmle.Extraction.CSharp.Entities
return Expression.ValueAsString(c.Value);
}
if (TryGetBoolValueInsideIfDirective(out var val))
if (TryGetBoolValueFromLiteral(out var val))
{
return Expression.ValueAsString(val);
}
@@ -604,30 +604,18 @@ namespace Semmle.Extraction.CSharp.Entities
public NullableFlowState FlowState => TypeInfo.Nullability.FlowState;
public bool IsInsideIfDirective()
{
return Node.Ancestors().Any(a => a is ElifDirectiveTriviaSyntax || a is IfDirectiveTriviaSyntax);
}
public bool TryGetBoolValueInsideIfDirective(out bool val)
private bool TryGetBoolValueFromLiteral(out bool val)
{
var isTrue = Node.IsKind(SyntaxKind.TrueLiteralExpression);
var isFalse = Node.IsKind(SyntaxKind.FalseLiteralExpression);
if (!isTrue && !isFalse)
{
val = false;
return false;
}
if (!IsInsideIfDirective())
{
val = false;
return false;
}
val = isTrue;
return true;
return isTrue || isFalse;
}
public bool IsBoolLiteral()
{
return TryGetBoolValueFromLiteral(out var _);
}
}
}

View File

@@ -25,7 +25,8 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
return ExprKind.NULL_LITERAL;
}
if (info.TryGetBoolValueInsideIfDirective(out var _))
// short circuit bool literals, because they have no type in `#if A = true`
if (info.IsBoolLiteral())
{
return ExprKind.BOOL_LITERAL;
}

View File

@@ -27,15 +27,13 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
if (target == null)
{
if (info.IsInsideIfDirective())
if (IsInsideIfDirective(info.Node))
{
return DefineSymbol.Create(info);
}
else
{
info.Context.ModelError(info.Node, "Failed to resolve name");
return new Unknown(info);
}
info.Context.ModelError(info.Node, "Failed to resolve name");
return new Unknown(info);
}
// There is a very strange bug in Microsoft.CodeAnalysis whereby
@@ -72,5 +70,10 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
throw new InternalError(info.Node, $"Unhandled identifier kind '{target.Kind}'");
}
}
private static bool IsInsideIfDirective(ExpressionSyntax node)
{
return node.Ancestors().Any(a => a is ElifDirectiveTriviaSyntax || a is IfDirectiveTriviaSyntax);
}
}
}