Skip to content

Commit d2ebbe0

Browse files
authored
Merge pull request #7469 from hvitved/csharp/promote-adhoc-consistency-checks
C#: Promote existing ad-hoc consistency checks to consistency queries
2 parents 533fc7a + a1bbe58 commit d2ebbe0

File tree

24 files changed

+156
-157
lines changed

24 files changed

+156
-157
lines changed

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaImplCommon.qll

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,4 +659,15 @@ module Consistency {
659659
not phiHasInputFromBlock(_, def, _) and
660660
not uncertainWriteDefinitionInput(_, def)
661661
}
662+
663+
query predicate notDominatedByDef(RelevantDefinition def, SourceVariable v, BasicBlock bb, int i) {
664+
exists(BasicBlock bbDef, int iDef | def.definesAt(v, bbDef, iDef) |
665+
ssaDefReachesReadWithinBlock(v, def, bb, i) and
666+
(bb != bbDef or i < iDef)
667+
or
668+
ssaDefReachesRead(v, def, bb, i) and
669+
not ssaDefReachesReadWithinBlock(v, def, bb, i) and
670+
not def.definesAt(v, getImmediateBasicBlockDominator*(bb), _)
671+
)
672+
}
662673
}

csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,7 @@ protected override void ExtractInitializers(TextWriter trapFile)
113113

114114
trapFile.expr_call(init, target);
115115

116-
var child = 0;
117-
foreach (var arg in initializer.ArgumentList.Arguments)
118-
{
119-
Expression.Create(Context, arg.Expression, init, child++);
120-
}
116+
init.PopulateArguments(trapFile, initializer.ArgumentList, 0);
121117
}
122118

123119
private ConstructorDeclarationSyntax? Syntax

csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using Semmle.Extraction.CSharp.Entities.Expressions;
55
using Semmle.Extraction.Kinds;
66
using System;
7+
using System.Collections.Generic;
78
using System.IO;
89
using System.Linq;
910

@@ -324,7 +325,12 @@ public void MakeConditional(TextWriter trapFile)
324325

325326
public void PopulateArguments(TextWriter trapFile, BaseArgumentListSyntax args, int child)
326327
{
327-
foreach (var arg in args.Arguments)
328+
PopulateArguments(trapFile, args.Arguments, child);
329+
}
330+
331+
public void PopulateArguments(TextWriter trapFile, IEnumerable<ArgumentSyntax> args, int child)
332+
{
333+
foreach (var arg in args)
328334
PopulateArgument(trapFile, arg, child++);
329335
}
330336

csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Initializer.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,7 @@ protected override void PopulateExpression(TextWriter trapFile)
105105
if (assignment.Left is ImplicitElementAccessSyntax iea)
106106
{
107107
// An array/indexer initializer of the form `[...] = ...`
108-
109-
var indexChild = 0;
110-
foreach (var arg in iea.ArgumentList.Arguments)
111-
{
112-
Expression.Create(Context, arg.Expression, access, indexChild++);
113-
}
108+
access.PopulateArguments(trapFile, iea.ArgumentList.Arguments, 0);
114109
}
115110
}
116111
else

csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Tuple.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,7 @@ private Tuple(ExpressionNodeInfo info) : base(info.SetKind(ExprKind.TUPLE))
1515

1616
protected override void PopulateExpression(TextWriter trapFile)
1717
{
18-
var child = 0;
19-
foreach (var argument in Syntax.Arguments.Select(a => a.Expression))
20-
{
21-
Expression.Create(Context, argument, this, child++);
22-
}
18+
PopulateArguments(trapFile, Syntax.Arguments, 0);
2319
}
2420
}
2521
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import csharp
2+
3+
query predicate missingLocation(Element e) {
4+
(
5+
e instanceof Declaration or
6+
e instanceof Expr or
7+
e instanceof Stmt
8+
) and
9+
not e instanceof ImplicitAccessorParameter and
10+
not e instanceof NullType and
11+
not e instanceof Parameter and // Bug in Roslyn - params occasionally lack locations
12+
not e.(Operator).getDeclaringType() instanceof IntType and // Roslyn quirk
13+
not e instanceof Constructor and
14+
not e instanceof ArrayType and
15+
not e instanceof UnknownType and
16+
not e instanceof ArglistType and
17+
not exists(TupleType t | e = t or e = t.getAField()) and
18+
not exists(e.getLocation())
19+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import csharp
2+
3+
query predicate missingUnbound(ConstructedGeneric g) { not exists(g.getUnboundGeneric()) }
4+
5+
query predicate missingArgs(ConstructedGeneric g) { g.getNumberOfTypeArguments() = 0 }
6+
7+
query predicate inconsistentArgCount(ConstructedGeneric g) {
8+
g.getUnboundGeneric().getNumberOfTypeParameters() != g.getNumberOfTypeArguments()
9+
}

csharp/ql/consistency-queries/SsaConsistency.ql

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import csharp
22
import semmle.code.csharp.dataflow.internal.SsaImplCommon::Consistency
3+
import Ssa
34

45
class MyRelevantDefinition extends RelevantDefinition, Ssa::Definition {
56
override predicate hasLocationInfo(
@@ -8,3 +9,18 @@ class MyRelevantDefinition extends RelevantDefinition, Ssa::Definition {
89
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
910
}
1011
}
12+
13+
query predicate localDeclWithSsaDef(LocalVariableDeclExpr d) {
14+
// Local variables in C# must be initialized before every use, so uninitialized
15+
// local variables should not have an SSA definition, as that would imply that
16+
// the declaration is live (can reach a use without passing through a definition)
17+
exists(ExplicitDefinition def |
18+
d = def.getADefinition().(AssignableDefinitions::LocalVariableDefinition).getDeclaration()
19+
|
20+
not d = any(ForeachStmt fs).getVariableDeclExpr() and
21+
not d = any(SpecificCatchClause scc).getVariableDeclExpr() and
22+
not d.getVariable().getType() instanceof Struct and
23+
not d instanceof PatternExpr and
24+
not d.getVariable().isCaptured()
25+
)
26+
}

csharp/ql/lib/semmle/code/cil/internal/SsaImplCommon.qll

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,4 +659,15 @@ module Consistency {
659659
not phiHasInputFromBlock(_, def, _) and
660660
not uncertainWriteDefinitionInput(_, def)
661661
}
662+
663+
query predicate notDominatedByDef(RelevantDefinition def, SourceVariable v, BasicBlock bb, int i) {
664+
exists(BasicBlock bbDef, int iDef | def.definesAt(v, bbDef, iDef) |
665+
ssaDefReachesReadWithinBlock(v, def, bb, i) and
666+
(bb != bbDef or i < iDef)
667+
or
668+
ssaDefReachesRead(v, def, bb, i) and
669+
not ssaDefReachesReadWithinBlock(v, def, bb, i) and
670+
not def.definesAt(v, getImmediateBasicBlockDominator*(bb), _)
671+
)
672+
}
662673
}

csharp/ql/lib/semmle/code/csharp/commons/ConsistencyChecks.qll

Lines changed: 0 additions & 102 deletions
This file was deleted.

csharp/ql/lib/semmle/code/csharp/controlflow/internal/pressa/SsaImplCommon.qll

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,4 +659,15 @@ module Consistency {
659659
not phiHasInputFromBlock(_, def, _) and
660660
not uncertainWriteDefinitionInput(_, def)
661661
}
662+
663+
query predicate notDominatedByDef(RelevantDefinition def, SourceVariable v, BasicBlock bb, int i) {
664+
exists(BasicBlock bbDef, int iDef | def.definesAt(v, bbDef, iDef) |
665+
ssaDefReachesReadWithinBlock(v, def, bb, i) and
666+
(bb != bbDef or i < iDef)
667+
or
668+
ssaDefReachesRead(v, def, bb, i) and
669+
not ssaDefReachesReadWithinBlock(v, def, bb, i) and
670+
not def.definesAt(v, getImmediateBasicBlockDominator*(bb), _)
671+
)
672+
}
662673
}

csharp/ql/lib/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,4 +659,15 @@ module Consistency {
659659
not phiHasInputFromBlock(_, def, _) and
660660
not uncertainWriteDefinitionInput(_, def)
661661
}
662+
663+
query predicate notDominatedByDef(RelevantDefinition def, SourceVariable v, BasicBlock bb, int i) {
664+
exists(BasicBlock bbDef, int iDef | def.definesAt(v, bbDef, iDef) |
665+
ssaDefReachesReadWithinBlock(v, def, bb, i) and
666+
(bb != bbDef or i < iDef)
667+
or
668+
ssaDefReachesRead(v, def, bb, i) and
669+
not ssaDefReachesReadWithinBlock(v, def, bb, i) and
670+
not def.definesAt(v, getImmediateBasicBlockDominator*(bb), _)
671+
)
672+
}
662673
}

csharp/ql/lib/semmle/code/csharp/dataflow/internal/basessa/SsaImplCommon.qll

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,4 +659,15 @@ module Consistency {
659659
not phiHasInputFromBlock(_, def, _) and
660660
not uncertainWriteDefinitionInput(_, def)
661661
}
662+
663+
query predicate notDominatedByDef(RelevantDefinition def, SourceVariable v, BasicBlock bb, int i) {
664+
exists(BasicBlock bbDef, int iDef | def.definesAt(v, bbDef, iDef) |
665+
ssaDefReachesReadWithinBlock(v, def, bb, i) and
666+
(bb != bbDef or i < iDef)
667+
or
668+
ssaDefReachesRead(v, def, bb, i) and
669+
not ssaDefReachesReadWithinBlock(v, def, bb, i) and
670+
not def.definesAt(v, getImmediateBasicBlockDominator*(bb), _)
671+
)
672+
}
662673
}

csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,12 @@ private predicate hasChildPattern(ControlFlowElement pm, Expr child) {
316316
child = mid.getChildExpr(0) or
317317
child = mid.getChildExpr(1)
318318
)
319+
or
320+
exists(Expr mid |
321+
hasChildPattern(pm, mid) and
322+
mid instanceof @tuple_expr and
323+
child = mid.getAChildExpr()
324+
)
319325
}
320326

321327
/**
@@ -420,13 +426,10 @@ class TypeAccessPatternExpr extends TypePatternExpr, TypeAccess {
420426
override string getAPrimaryQlClass() { result = "TypeAccessPatternExpr" }
421427
}
422428

423-
/** A pattern that may bind a variable, for example `string s` in `x is string s`. */
424-
class BindingPatternExpr extends PatternExpr {
425-
BindingPatternExpr() {
426-
this instanceof LocalVariableDeclExpr or
427-
this instanceof @recursive_pattern_expr
428-
}
429+
private class TBindingPatternExpr = @local_var_decl_expr or @recursive_pattern_expr;
429430

431+
/** A pattern that may bind a variable, for example `string s` in `x is string s`. */
432+
class BindingPatternExpr extends PatternExpr, TBindingPatternExpr {
430433
/**
431434
* Gets the local variable declaration of this pattern, if any. For example,
432435
* `string s` in `string { Length: 5 } s`.

csharp/ql/test/library-tests/arguments/argumentType.expected

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,21 @@
2424
| arguments.cs:45:35:45:38 | null | 0 |
2525
| arguments.cs:55:21:55:21 | 1 | 0 |
2626
| arguments.cs:55:24:55:24 | 2 | 0 |
27+
| arguments.cs:56:10:56:13 | access to property Prop | 0 |
28+
| arguments.cs:56:16:56:25 | access to indexer | 0 |
2729
| arguments.cs:56:21:56:21 | 3 | 0 |
2830
| arguments.cs:56:24:56:24 | 4 | 0 |
31+
| arguments.cs:56:31:56:31 | 5 | 0 |
32+
| arguments.cs:56:34:56:34 | 6 | 0 |
2933
| arguments.cs:59:14:59:14 | 8 | 0 |
3034
| arguments.cs:59:17:59:17 | 9 | 0 |
3135
| arguments.cs:60:14:60:15 | 10 | 0 |
3236
| arguments.cs:60:14:60:15 | 10 | 0 |
3337
| arguments.cs:60:18:60:19 | 11 | 0 |
3438
| arguments.cs:60:18:60:19 | 11 | 0 |
39+
| arguments.cs:61:22:61:23 | 13 | 0 |
40+
| arguments.cs:61:26:61:27 | 14 | 0 |
41+
| arguments.cs:62:10:62:13 | access to property Prop | 0 |
42+
| arguments.cs:62:16:62:27 | access to indexer | 0 |
3543
| arguments.cs:62:21:62:22 | 15 | 0 |
3644
| arguments.cs:62:25:62:26 | 16 | 0 |

csharp/ql/test/library-tests/csharp7.3/PrintAst.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ csharp73.cs:
102102
# 46| 1: [IntLiteral] 5
103103
# 49| 5: [InstanceConstructor] ExpressionVariables
104104
# 49| 3: [ConstructorInitializer] call to constructor ExpressionVariables
105-
# 49| 0: [LocalVariableDeclExpr] Int32 x
105+
# 49| 0: [LocalVariableAccess,LocalVariableDeclExpr] Int32 x
106106
# 50| 4: [BlockStmt] {...}
107107
# 51| 0: [ExprStmt] ...;
108108
# 51| 0: [MethodCall] call to method WriteLine

csharp/ql/test/library-tests/csharp8/PrintAst.expected

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -932,8 +932,8 @@ patterns.cs:
932932
# 58| 10: [BreakStmt] break;
933933
# 59| 11: [CaseStmt] case ...:
934934
# 59| 0: [TupleExpr] (..., ...)
935-
# 59| 0: [LocalVariableDeclExpr] Int32 x
936-
# 59| 1: [LocalVariableDeclExpr] Int32 y
935+
# 59| 0: [VariablePatternExpr] Int32 x
936+
# 59| 1: [VariablePatternExpr] Int32 y
937937
# 60| 12: [BreakStmt] break;
938938
# 61| 13: [DefaultCase] default:
939939
# 62| 14: [BreakStmt] break;
@@ -1159,8 +1159,8 @@ patterns.cs:
11591159
# 130| 2: [IntLiteral] 2
11601160
# 131| 3: [SwitchCaseExpr] ... => ...
11611161
# 131| 0: [TupleExpr] (..., ...)
1162-
# 131| 0: [LocalVariableDeclExpr] Int32 x
1163-
# 131| 1: [DiscardExpr] _
1162+
# 131| 0: [VariablePatternExpr] Int32 x
1163+
# 131| 1: [DiscardPatternExpr] _
11641164
# 131| 2: [IntLiteral] 3
11651165
# 134| 2: [TryStmt] try {...} ...
11661166
# 135| 0: [BlockStmt] {...}

csharp/ql/test/library-tests/dataflow/ssa/SsaConsistency.expected

Whitespace-only changes.

csharp/ql/test/library-tests/dataflow/ssa/SsaConsistency.ql

Lines changed: 0 additions & 6 deletions
This file was deleted.

0 commit comments

Comments
 (0)