Skip to content

Commit 93e0bd9

Browse files
authored
Merge pull request #4126 from tamasvajk/feature/array-index
C#: Fix computed sizes for implicitly sized array creation
2 parents 6eca97b + 18c65e9 commit 93e0bd9

21 files changed

+557
-376
lines changed

change-notes/1.26/analysis-csharp.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ The following changes in version 1.26 affect C# analysis in all applications.
1919
## Changes to code extraction
2020

2121
* Partial method bodies are extracted. Previously, partial method bodies were skipped completely.
22+
* Inferring the lengths of implicitely sized arrays is fixed. Previously, multidimensional arrays were always extracted with the same length for
23+
each dimension. With the fix, the array sizes `2` and `1` are extracted for `new int[,]{{1},{2}}`. Previously `2` and `2` were extracted.
2224

2325
## Changes to libraries
2426

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

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Microsoft.CodeAnalysis;
2+
using Microsoft.CodeAnalysis.CSharp;
23
using Microsoft.CodeAnalysis.CSharp.Syntax;
34
using Semmle.Extraction.Kinds;
45
using System.IO;
@@ -21,46 +22,29 @@ protected ExplicitArrayCreation(ExpressionNodeInfo info) : base(info.SetKind(Exp
2122

2223
protected override void PopulateExpression(TextWriter trapFile)
2324
{
24-
var child = 0;
25+
2526
var explicitlySized = false;
2627

2728
if (TypeSyntax is null)
2829
{
2930
cx.ModelError(Syntax, "Array has unexpected type syntax");
3031
}
3132

32-
foreach (var rank in TypeSyntax.RankSpecifiers.SelectMany(rs => rs.Sizes))
33+
var firstLevelSizes = TypeSyntax.RankSpecifiers.First()?.Sizes ?? SyntaxFactory.SeparatedList<ExpressionSyntax>();
34+
35+
if (firstLevelSizes.OfType<ExpressionSyntax>().Any(s => s is OmittedArraySizeExpressionSyntax))
3336
{
34-
if (rank is OmittedArraySizeExpressionSyntax)
35-
{
36-
// Create an expression which simulates the explicit size of the array
37-
38-
if (!(Initializer is null))
39-
{
40-
// An implicitly-sized array must have an initializer.
41-
// Guard it just in case.
42-
var size = Initializer.Expressions.Count;
43-
44-
var info = new ExpressionInfo(
45-
cx,
46-
new AnnotatedType(Entities.Type.Create(cx, cx.Compilation.GetSpecialType(Microsoft.CodeAnalysis.SpecialType.System_Int32)), NullableAnnotation.None),
47-
Location,
48-
ExprKind.INT_LITERAL,
49-
this,
50-
child,
51-
true,
52-
size.ToString());
53-
54-
new Expression(info);
55-
}
56-
}
57-
else
37+
SetArraySizes(Initializer, firstLevelSizes.Count);
38+
}
39+
else
40+
{
41+
for (var sizeIndex = 0; sizeIndex < firstLevelSizes.Count; sizeIndex++)
5842
{
59-
Create(cx, rank, this, child);
60-
explicitlySized = true;
43+
Create(cx, firstLevelSizes[sizeIndex], this, sizeIndex);
6144
}
62-
child++;
45+
explicitlySized = true;
6346
}
47+
6448
if (!(Initializer is null))
6549
{
6650
ArrayInitializer.Create(new ExpressionNodeInfo(cx, Initializer, this, -1));
@@ -69,6 +53,31 @@ protected override void PopulateExpression(TextWriter trapFile)
6953
if (explicitlySized)
7054
trapFile.explicitly_sized_array_creation(this);
7155
}
56+
57+
private void SetArraySizes(InitializerExpressionSyntax initializer, int rank)
58+
{
59+
for (var level = 0; level < rank; level++)
60+
{
61+
if (initializer is null)
62+
{
63+
return;
64+
}
65+
66+
var info = new ExpressionInfo(
67+
cx,
68+
new AnnotatedType(Entities.Type.Create(cx, cx.Compilation.GetSpecialType(Microsoft.CodeAnalysis.SpecialType.System_Int32)), NullableAnnotation.None),
69+
Location,
70+
ExprKind.INT_LITERAL,
71+
this,
72+
level,
73+
true,
74+
initializer.Expressions.Count.ToString());
75+
76+
new Expression(info);
77+
78+
initializer = initializer.Expressions.FirstOrDefault() as InitializerExpressionSyntax;
79+
}
80+
}
7281
}
7382

7483
class NormalArrayCreation : ExplicitArrayCreation<ArrayCreationExpressionSyntax>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
| expressions.cs:443:33:443:66 | delegate(...) { ... } |
1+
| expressions.cs:455:33:455:66 | delegate(...) { ... } |
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
| expressions.cs:443:33:443:66 | delegate(...) { ... } | expressions.cs:443:47:443:47 | x |
1+
| expressions.cs:455:33:455:66 | delegate(...) { ... } | expressions.cs:455:47:455:47 | x |
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
| expressions.cs:443:33:443:66 | delegate(...) { ... } |
1+
| expressions.cs:455:33:455:66 | delegate(...) { ... } |
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
| expressions.cs:445:28:445:53 | delegate(...) { ... } | expressions.cs:445:28:445:53 | delegate(...) { ... } |
1+
| expressions.cs:457:28:457:53 | delegate(...) { ... } | expressions.cs:457:28:457:53 | delegate(...) { ... } |
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
| expressions.cs:445:28:445:53 | delegate(...) { ... } | expressions.cs:445:46:445:46 | access to local variable j |
1+
| expressions.cs:457:28:457:53 | delegate(...) { ... } | expressions.cs:457:46:457:46 | access to local variable j |
Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,27 @@
11
| expressions.cs:168:27:168:44 | array creation of type Object[] | expressions.cs:168:27:168:44 | 1 | true |
2+
| expressions.cs:409:23:409:65 | array creation of type Int32[,] | expressions.cs:409:23:409:65 | 2 | true |
23
| expressions.cs:409:23:409:65 | array creation of type Int32[,] | expressions.cs:409:23:409:65 | 3 | true |
3-
| expressions.cs:409:23:409:65 | array creation of type Int32[,] | expressions.cs:409:23:409:65 | 3 | true |
4+
| expressions.cs:437:24:437:66 | array creation of type Int32[,] | expressions.cs:437:24:437:66 | 2 | true |
5+
| expressions.cs:437:24:437:66 | array creation of type Int32[,] | expressions.cs:437:24:437:66 | 3 | true |
6+
| expressions.cs:438:17:438:93 | array creation of type Int32[,,] | expressions.cs:438:17:438:93 | 2 | true |
7+
| expressions.cs:438:17:438:93 | array creation of type Int32[,,] | expressions.cs:438:17:438:93 | 2 | true |
8+
| expressions.cs:438:17:438:93 | array creation of type Int32[,,] | expressions.cs:438:17:438:93 | 3 | true |
9+
| expressions.cs:439:17:443:13 | array creation of type Int32[,][,] | expressions.cs:439:17:443:13 | 2 | true |
10+
| expressions.cs:439:17:443:13 | array creation of type Int32[,][,] | expressions.cs:439:17:443:13 | 3 | true |
11+
| expressions.cs:441:19:441:45 | array creation of type Int32[,] | expressions.cs:441:19:441:45 | 2 | true |
12+
| expressions.cs:441:19:441:45 | array creation of type Int32[,] | expressions.cs:441:19:441:45 | 2 | true |
13+
| expressions.cs:441:48:441:82 | array creation of type Int32[,] | expressions.cs:441:48:441:82 | 2 | true |
14+
| expressions.cs:441:48:441:82 | array creation of type Int32[,] | expressions.cs:441:48:441:82 | 3 | true |
15+
| expressions.cs:441:85:441:122 | array creation of type Int32[,] | expressions.cs:441:85:441:122 | 2 | true |
16+
| expressions.cs:441:85:441:122 | array creation of type Int32[,] | expressions.cs:441:85:441:122 | 3 | true |
17+
| expressions.cs:442:19:442:45 | array creation of type Int32[,] | expressions.cs:442:19:442:45 | 2 | true |
18+
| expressions.cs:442:19:442:45 | array creation of type Int32[,] | expressions.cs:442:19:442:45 | 2 | true |
19+
| expressions.cs:442:48:442:82 | array creation of type Int32[,] | expressions.cs:442:48:442:82 | 2 | true |
20+
| expressions.cs:442:48:442:82 | array creation of type Int32[,] | expressions.cs:442:48:442:82 | 3 | true |
21+
| expressions.cs:442:85:442:122 | array creation of type Int32[,] | expressions.cs:442:85:442:122 | 2 | true |
22+
| expressions.cs:442:85:442:122 | array creation of type Int32[,] | expressions.cs:442:85:442:122 | 3 | true |
23+
| expressions.cs:444:17:444:123 | array creation of type Int32[,][] | expressions.cs:444:17:444:123 | 2 | true |
24+
| expressions.cs:444:32:444:54 | array creation of type Int32[,] | expressions.cs:444:32:444:54 | 1 | true |
25+
| expressions.cs:444:32:444:54 | array creation of type Int32[,] | expressions.cs:444:32:444:54 | 2 | true |
26+
| expressions.cs:444:57:444:121 | array creation of type Int32[,] | expressions.cs:444:57:444:121 | 3 | true |
27+
| expressions.cs:444:57:444:121 | array creation of type Int32[,] | expressions.cs:444:57:444:121 | 4 | true |
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
| expressions.cs:437:36:437:53 | (...) => ... |
1+
| expressions.cs:449:36:449:53 | (...) => ... |
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
| expressions.cs:438:38:438:59 | (...) => ... |
1+
| expressions.cs:450:38:450:59 | (...) => ... |

0 commit comments

Comments
 (0)