mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
Extract #if directives
This commit is contained in:
@@ -529,7 +529,17 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
get
|
||||
{
|
||||
var c = Model.GetConstantValue(Node);
|
||||
return c.HasValue ? Expression.ValueAsString(c.Value) : null;
|
||||
if (c.HasValue)
|
||||
{
|
||||
return Expression.ValueAsString(c.Value);
|
||||
}
|
||||
|
||||
if (TryGetBoolValueInsideIfDirective(out var val))
|
||||
{
|
||||
return Expression.ValueAsString(val);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -593,5 +603,31 @@ 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Semmle.Extraction.Kinds;
|
||||
using System.IO;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
{
|
||||
internal class DefineSymbol : Expression<IdentifierNameSyntax>
|
||||
{
|
||||
private DefineSymbol(ExpressionNodeInfo info) : base(info.SetKind(ExprKind.DEFINE_SYMBOL)) { }
|
||||
|
||||
public static Expression Create(ExpressionNodeInfo info) => new DefineSymbol(info).TryPopulate();
|
||||
|
||||
protected override void PopulateExpression(TextWriter trapFile)
|
||||
{
|
||||
trapFile.directive_define_symbols(this, Syntax.Identifier.Text);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,11 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
return ExprKind.NULL_LITERAL;
|
||||
}
|
||||
|
||||
if (info.TryGetBoolValueInsideIfDirective(out var _))
|
||||
{
|
||||
return ExprKind.BOOL_LITERAL;
|
||||
}
|
||||
|
||||
var type = info.Type?.Symbol;
|
||||
return GetExprKind(type, info.Node, info.Context);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using System.Linq;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
@@ -26,8 +27,15 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
|
||||
if (target == null)
|
||||
{
|
||||
info.Context.ModelError(info.Node, "Failed to resolve name");
|
||||
return new Unknown(info);
|
||||
if (info.IsInsideIfDirective())
|
||||
{
|
||||
return DefineSymbol.Create(info);
|
||||
}
|
||||
else
|
||||
{
|
||||
info.Context.ModelError(info.Node, "Failed to resolve name");
|
||||
return new Unknown(info);
|
||||
}
|
||||
}
|
||||
|
||||
// There is a very strange bug in Microsoft.CodeAnalysis whereby
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using System.IO;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.Entities
|
||||
{
|
||||
internal class ElifDirective : PreprocessorDirective<ElifDirectiveTriviaSyntax>, IIfSiblingDirective, IExpressionParentEntity
|
||||
{
|
||||
public ElifDirective(Context cx, ElifDirectiveTriviaSyntax trivia)
|
||||
: base(cx, trivia)
|
||||
{
|
||||
}
|
||||
|
||||
public bool IsTopLevelParent => true;
|
||||
|
||||
protected override void PopulatePreprocessor(TextWriter trapFile)
|
||||
{
|
||||
trapFile.directive_elifs(this, trivia.BranchTaken, trivia.ConditionValue);
|
||||
|
||||
Expression.Create(cx, trivia.Condition, this, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using System.IO;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.Entities
|
||||
{
|
||||
internal class ElseDirective : PreprocessorDirective<ElseDirectiveTriviaSyntax>, IIfSiblingDirective
|
||||
{
|
||||
public ElseDirective(Context cx, ElseDirectiveTriviaSyntax trivia)
|
||||
: base(cx, trivia)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void PopulatePreprocessor(TextWriter trapFile)
|
||||
{
|
||||
trapFile.directive_elses(this, trivia.BranchTaken);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using System.IO;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.Entities
|
||||
{
|
||||
internal class EndIfDirective : PreprocessorDirective<EndIfDirectiveTriviaSyntax>
|
||||
{
|
||||
public EndIfDirective(Context cx, EndIfDirectiveTriviaSyntax trivia)
|
||||
: base(cx, trivia)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void PopulatePreprocessor(TextWriter trapFile)
|
||||
{
|
||||
trapFile.directive_endifs(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
namespace Semmle.Extraction.CSharp.Entities
|
||||
{
|
||||
internal interface IIfSiblingDirective { }
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.Entities
|
||||
{
|
||||
internal class IfDirective : PreprocessorDirective<IfDirectiveTriviaSyntax>, IExpressionParentEntity
|
||||
{
|
||||
private readonly List<IIfSiblingDirective> branches = new List<IIfSiblingDirective>();
|
||||
|
||||
public IfDirective(Context cx, IfDirectiveTriviaSyntax trivia)
|
||||
: base(cx, trivia)
|
||||
{
|
||||
}
|
||||
|
||||
public bool IsTopLevelParent => true;
|
||||
|
||||
protected override void PopulatePreprocessor(TextWriter trapFile)
|
||||
{
|
||||
trapFile.directive_ifs(this, trivia.BranchTaken, trivia.ConditionValue);
|
||||
|
||||
Expression.Create(cx, trivia.Condition, this, 0);
|
||||
}
|
||||
|
||||
internal void Add(IIfSiblingDirective branch)
|
||||
{
|
||||
branches.Add(branch);
|
||||
}
|
||||
|
||||
internal void WriteBranches(EndIfDirective endif)
|
||||
{
|
||||
cx.TrapWriter.Writer.directive_if_endif(this, endif);
|
||||
var siblings = 0;
|
||||
foreach (var branch in branches)
|
||||
{
|
||||
cx.TrapWriter.Writer.directive_if_siblings(this, branch, siblings++);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.Entities
|
||||
|
||||
@@ -124,5 +124,7 @@ namespace Semmle.Extraction.Kinds
|
||||
AND_PATTERN = 127,
|
||||
OR_PATTERN = 128,
|
||||
FUNCTION_POINTER_INVOCATION = 129,
|
||||
|
||||
DEFINE_SYMBOL = 999
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,5 +75,52 @@ namespace Semmle.Extraction.CSharp.Populators
|
||||
var start = regionStarts.Pop();
|
||||
Entities.EndRegionDirective.WriteRegionBlock(cx, start, endregion);
|
||||
}
|
||||
|
||||
private readonly Stack<Entities.IfDirective> ifStarts = new Stack<Entities.IfDirective>();
|
||||
|
||||
public override void VisitIfDirectiveTrivia(IfDirectiveTriviaSyntax node)
|
||||
{
|
||||
var ifStart = new Entities.IfDirective(cx, node);
|
||||
ifStarts.Push(ifStart);
|
||||
}
|
||||
|
||||
public override void VisitEndIfDirectiveTrivia(EndIfDirectiveTriviaSyntax node)
|
||||
{
|
||||
var endif = new Entities.EndIfDirective(cx, node);
|
||||
if (ifStarts.Count == 0)
|
||||
{
|
||||
cx.ExtractionError("Couldn't find start if", null,
|
||||
Extraction.Entities.Location.Create(cx, node.GetLocation()), null, Util.Logging.Severity.Warning);
|
||||
return;
|
||||
}
|
||||
var start = ifStarts.Pop();
|
||||
start.WriteBranches(endif);
|
||||
}
|
||||
|
||||
public override void VisitElifDirectiveTrivia(ElifDirectiveTriviaSyntax node)
|
||||
{
|
||||
var elif = new Entities.ElifDirective(cx, node);
|
||||
if (ifStarts.Count == 0)
|
||||
{
|
||||
cx.ExtractionError("Couldn't find start if", null,
|
||||
Extraction.Entities.Location.Create(cx, node.GetLocation()), null, Util.Logging.Severity.Warning);
|
||||
return;
|
||||
}
|
||||
var start = ifStarts.Peek();
|
||||
start.Add(elif);
|
||||
}
|
||||
|
||||
public override void VisitElseDirectiveTrivia(ElseDirectiveTriviaSyntax node)
|
||||
{
|
||||
var elseDirective = new Entities.ElseDirective(cx, node);
|
||||
if (ifStarts.Count == 0)
|
||||
{
|
||||
cx.ExtractionError("Couldn't find start if", null,
|
||||
Extraction.Entities.Location.Create(cx, node.GetLocation()), null, Util.Logging.Severity.Warning);
|
||||
return;
|
||||
}
|
||||
var start = ifStarts.Peek();
|
||||
start.Add(elseDirective);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Semmle.Extraction.CommentProcessing;
|
||||
using Semmle.Extraction.CSharp.Entities;
|
||||
using Semmle.Extraction.CSharp.Entities.Expressions;
|
||||
using Semmle.Extraction.Entities;
|
||||
using Semmle.Extraction.Kinds;
|
||||
using Semmle.Util;
|
||||
@@ -670,5 +671,42 @@ namespace Semmle.Extraction.CSharp
|
||||
{
|
||||
trapFile.WriteTuple("regions", start, end);
|
||||
}
|
||||
|
||||
internal static void directive_ifs(this TextWriter trapFile, IfDirective directive, bool branchTaken, bool conditionValue)
|
||||
{
|
||||
trapFile.WriteTuple("directive_ifs", directive, branchTaken ? 1 : 0, conditionValue ? 1 : 0);
|
||||
}
|
||||
|
||||
internal static void directive_elifs(this TextWriter trapFile, ElifDirective directive, bool branchTaken, bool conditionValue)
|
||||
{
|
||||
trapFile.WriteTuple("directive_elifs", directive, branchTaken ? 1 : 0, conditionValue ? 1 : 0);
|
||||
}
|
||||
|
||||
internal static void directive_elses(this TextWriter trapFile, ElseDirective directive, bool branchTaken)
|
||||
{
|
||||
trapFile.WriteTuple("directive_elses", directive, branchTaken ? 1 : 0);
|
||||
}
|
||||
|
||||
internal static void directive_endifs(this TextWriter trapFile, EndIfDirective directive)
|
||||
{
|
||||
trapFile.WriteTuple("directive_endifs", directive);
|
||||
}
|
||||
|
||||
internal static void directive_if_endif(this TextWriter trapFile, IfDirective start, EndIfDirective end)
|
||||
{
|
||||
trapFile.WriteTuple("directive_if_endif", start, end);
|
||||
}
|
||||
|
||||
internal static void directive_if_siblings(this TextWriter trapFile, IfDirective start, IIfSiblingDirective siblingDirective, int index)
|
||||
{
|
||||
trapFile.WriteTuple("directive_if_siblings", start, siblingDirective, index);
|
||||
}
|
||||
|
||||
internal static void directive_define_symbols(this TextWriter trapFile, DefineSymbol symb, string name)
|
||||
{
|
||||
trapFile.WriteTuple("directive_define_symbols", symb, name);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user