Skip to content

Commit 7bc729a

Browse files
committed
Merge master into next.
2 parents 18eb60b + 936094d commit 7bc729a

File tree

16 files changed

+173
-39
lines changed

16 files changed

+173
-39
lines changed

change-notes/1.20/analysis-csharp.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
## Changes to code extraction
1919

20+
* Initializers of `stackalloc` arrays are now extracted.
21+
2022
## Changes to QL libraries
2123

2224
## Changes to the autobuilder

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

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -9,55 +9,35 @@ abstract class ArrayCreation<SyntaxNode> : Expression<SyntaxNode> where SyntaxNo
99
protected ArrayCreation(ExpressionNodeInfo info) : base(info) { }
1010
}
1111

12-
class StackAllocArrayCreation : ArrayCreation<StackAllocArrayCreationExpressionSyntax>
12+
abstract class ExplicitArrayCreation<SyntaxNode> : ArrayCreation<SyntaxNode> where SyntaxNode : ExpressionSyntax
1313
{
14-
StackAllocArrayCreation(ExpressionNodeInfo info) : base(info.SetKind(ExprKind.ARRAY_CREATION)) { }
14+
protected ExplicitArrayCreation(ExpressionNodeInfo info) : base(info.SetKind(ExprKind.ARRAY_CREATION)) { }
1515

16-
public static Expression Create(ExpressionNodeInfo info) => new StackAllocArrayCreation(info).TryPopulate();
16+
protected abstract ArrayTypeSyntax TypeSyntax { get; }
17+
18+
public abstract InitializerExpressionSyntax Initializer { get; }
1719

1820
protected override void Populate()
1921
{
20-
var arrayType = Syntax.Type as ArrayTypeSyntax;
21-
22-
if (arrayType == null)
23-
{
24-
cx.ModelError(Syntax, "Unexpected array type");
25-
return;
26-
}
27-
2822
var child = 0;
23+
var explicitlySized = false;
2924

30-
foreach (var rank in arrayType.RankSpecifiers.SelectMany(rs => rs.Sizes))
25+
if (TypeSyntax is null)
3126
{
32-
Create(cx, rank, this, child++);
27+
cx.ModelError(Syntax, "Array has unexpected type syntax");
3328
}
3429

35-
cx.Emit(Tuples.explicitly_sized_array_creation(this));
36-
}
37-
}
38-
39-
class ExplicitArrayCreation : ArrayCreation<ArrayCreationExpressionSyntax>
40-
{
41-
ExplicitArrayCreation(ExpressionNodeInfo info) : base(info.SetKind(ExprKind.ARRAY_CREATION)) { }
42-
43-
public static Expression Create(ExpressionNodeInfo info) => new ExplicitArrayCreation(info).TryPopulate();
44-
45-
protected override void Populate()
46-
{
47-
var child = 0;
48-
bool explicitlySized = false;
49-
50-
foreach (var rank in Syntax.Type.RankSpecifiers.SelectMany(rs => rs.Sizes))
30+
foreach (var rank in TypeSyntax.RankSpecifiers.SelectMany(rs => rs.Sizes))
5131
{
5232
if (rank is OmittedArraySizeExpressionSyntax)
5333
{
5434
// Create an expression which simulates the explicit size of the array
5535

56-
if (Syntax.Initializer != null)
36+
if (!(Initializer is null))
5737
{
5838
// An implicitly-sized array must have an initializer.
5939
// Guard it just in case.
60-
var size = Syntax.Initializer.Expressions.Count;
40+
var size = Initializer.Expressions.Count;
6141

6242
var info = new ExpressionInfo(
6343
cx,
@@ -79,16 +59,38 @@ protected override void Populate()
7959
}
8060
child++;
8161
}
82-
if (Syntax.Initializer != null)
62+
if (!(Initializer is null))
8363
{
84-
ArrayInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, -1));
64+
ArrayInitializer.Create(new ExpressionNodeInfo(cx, Initializer, this, -1));
8565
}
8666

8767
if (explicitlySized)
8868
cx.Emit(Tuples.explicitly_sized_array_creation(this));
8969
}
9070
}
9171

72+
class NormalArrayCreation : ExplicitArrayCreation<ArrayCreationExpressionSyntax>
73+
{
74+
private NormalArrayCreation(ExpressionNodeInfo info) : base(info) { }
75+
76+
protected override ArrayTypeSyntax TypeSyntax => Syntax.Type;
77+
78+
public override InitializerExpressionSyntax Initializer => Syntax.Initializer;
79+
80+
public static Expression Create(ExpressionNodeInfo info) => new NormalArrayCreation(info).TryPopulate();
81+
}
82+
83+
class StackAllocArrayCreation : ExplicitArrayCreation<StackAllocArrayCreationExpressionSyntax>
84+
{
85+
StackAllocArrayCreation(ExpressionNodeInfo info) : base(info) { }
86+
87+
protected override ArrayTypeSyntax TypeSyntax => Syntax.Type as ArrayTypeSyntax;
88+
89+
public override InitializerExpressionSyntax Initializer => Syntax.Initializer;
90+
91+
public static Expression Create(ExpressionNodeInfo info) => new StackAllocArrayCreation(info).TryPopulate();
92+
}
93+
9294
class ImplicitArrayCreation : ArrayCreation<ImplicitArrayCreationExpressionSyntax>
9395
{
9496
ImplicitArrayCreation(ExpressionNodeInfo info) : base(info.SetKind(ExprKind.ARRAY_CREATION)) { }

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ internal static Expression Create(ExpressionNodeInfo info)
8686
return ExplicitObjectCreation.Create(info);
8787

8888
case SyntaxKind.ArrayCreationExpression:
89-
return ExplicitArrayCreation.Create(info);
89+
return NormalArrayCreation.Create(info);
9090

9191
case SyntaxKind.ObjectInitializerExpression:
9292
return ObjectInitializer.Create(info);
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
| csharp73.cs:9:20:9:49 | array creation of type Char* | 0 | csharp73.cs:9:20:9:49 | 2 |
2+
| csharp73.cs:10:20:10:45 | array creation of type Char* | 0 | csharp73.cs:10:36:10:36 | 1 |
3+
| csharp73.cs:11:20:11:37 | array creation of type Char[] | 0 | csharp73.cs:11:20:11:37 | 1 |
4+
| csharp73.cs:12:20:12:38 | array creation of type Char* | 0 | csharp73.cs:12:36:12:37 | 10 |
5+
| csharp73.cs:13:20:13:31 | array creation of type Char[] | 0 | csharp73.cs:13:29:13:30 | 10 |
6+
| csharp73.cs:21:23:21:33 | array creation of type Int32[] | 0 | csharp73.cs:21:31:21:32 | 10 |
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import csharp
2+
3+
from ArrayCreation creation, int i
4+
select creation, i, creation.getLengthArgument(i)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
| csharp73.cs:9:20:9:49 | array creation of type Char* | 0 | csharp73.cs:9:40:9:42 | x |
2+
| csharp73.cs:9:20:9:49 | array creation of type Char* | 1 | csharp73.cs:9:45:9:47 | y |
3+
| csharp73.cs:10:20:10:45 | array creation of type Char* | 0 | csharp73.cs:10:41:10:43 | x |
4+
| csharp73.cs:11:20:11:37 | array creation of type Char[] | 0 | csharp73.cs:11:33:11:35 | x |
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import csharp
2+
3+
from ArrayCreation array, int i
4+
select array, i, array.getInitializer().getElement(i)
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// semmle-extractor-options: /langversion:latest
2+
3+
using System;
4+
5+
class StackAllocs
6+
{
7+
unsafe void Fn()
8+
{
9+
var arr1 = stackalloc char[] { 'x', 'y' };
10+
var arr2 = stackalloc char[1] { 'x' };
11+
var arr3 = new char[] { 'x' };
12+
var arr4 = stackalloc char[10];
13+
var arr5 = new char[10];
14+
}
15+
}
16+
17+
class PinnedReference
18+
{
19+
unsafe void F()
20+
{
21+
Span<int> t = new int[10];
22+
// This line should compile and generate a call to t.GetPinnableReference()
23+
// fixed (int * p = t)
24+
{
25+
}
26+
}
27+
}
28+
29+
class UnmanagedConstraint<T> where T : unmanaged
30+
{
31+
}
32+
33+
class EnumConstraint<T> where T : System.Enum
34+
{
35+
}
36+
37+
class DelegateConstraint<T> where T : System.Delegate
38+
{
39+
}
40+
41+
class ExpressionVariables
42+
{
43+
ExpressionVariables(out int x)
44+
{
45+
x = 5;
46+
}
47+
48+
public ExpressionVariables() : this(out int x)
49+
{
50+
Console.WriteLine($"x is {x}");
51+
}
52+
}

javascript/ql/src/Statements/UselessConditional.ql

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,15 +109,26 @@ predicate whitelist(Expr e) {
109109

110110
/**
111111
* Holds if `e` is part of a conditional node `cond` that evaluates
112-
* `e` and checks its value for truthiness.
112+
* `e` and checks its value for truthiness, and the return value of `e`
113+
* is not used for anything other than this truthiness check.
113114
*/
114-
predicate isConditional(ASTNode cond, Expr e) {
115+
predicate isExplicitConditional(ASTNode cond, Expr e) {
115116
e = cond.(IfStmt).getCondition() or
116117
e = cond.(LoopStmt).getTest() or
117118
e = cond.(ConditionalExpr).getCondition() or
118-
e = cond.(LogicalBinaryExpr).getLeftOperand() or
119-
// Include `z` in `if (x && z)`.
120-
isConditional(_, cond) and e = cond.(Expr).getUnderlyingValue().(LogicalBinaryExpr).getRightOperand()
119+
isExplicitConditional(_, cond) and e = cond.(Expr).getUnderlyingValue().(LogicalBinaryExpr).getAnOperand()
120+
}
121+
122+
/**
123+
* Holds if `e` is part of a conditional node `cond` that evaluates
124+
* `e` and checks its value for truthiness.
125+
*
126+
* The return value of `e` may have other uses besides the truthiness check,
127+
* but if the truthiness check always goes one way, it still indicates an error.
128+
*/
129+
predicate isConditional(ASTNode cond, Expr e) {
130+
isExplicitConditional(cond, e) or
131+
e = cond.(LogicalBinaryExpr).getLeftOperand()
121132
}
122133

123134
from ASTNode cond, DataFlow::AnalyzedNode op, boolean cv, ASTNode sel, string msg

javascript/ql/src/semmle/javascript/dataflow/Configuration.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,7 @@ private predicate flowsTo(PathNode flowsource, DataFlow::Node source,
687687
* Holds if `nd` is reachable from a source under `cfg` along a path summarized by
688688
* `summary`.
689689
*/
690+
pragma[nomagic]
690691
private predicate reachableFromSource(DataFlow::Node nd, DataFlow::Configuration cfg,
691692
PathSummary summary) {
692693
exists (FlowLabel lbl |

0 commit comments

Comments
 (0)