Skip to content

Commit b205702

Browse files
committed
C#: Fix bug in guards logic for foreach loops
1 parent ddb33c9 commit b205702

File tree

4 files changed

+7
-4
lines changed

4 files changed

+7
-4
lines changed

csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,12 @@ module AbstractValues {
212212
c.isValidFor(cfe) and
213213
foreachEmptiness(fs, cfe) and
214214
e = fs.getIterableExpr()
215-
)
215+
) and
216+
// Only when taking the non-empty successor do we know that the original iterator
217+
// expression was non-empty. When taking the empty successor, we may have already
218+
// iterated through the `foreach` loop zero or more times, hence the iterator
219+
// expression can be both empty and non-empty
220+
this.isNonEmpty()
216221
}
217222

218223
override EmptyCollectionValue getDualValue() {

csharp/ql/test/library-tests/controlflow/guards/Collections.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ void M10(string[] args)
100100
{
101101
foreach (var arg in args)
102102
;
103-
Console.WriteLine(args); // INCORRECT: guarded by `args` being empty
103+
Console.WriteLine(args);
104104
}
105105
}
106106

csharp/ql/test/library-tests/controlflow/guards/GuardedControlFlowNode.expected

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
| Collections.cs:67:13:67:13 | access to local variable x | Collections.cs:65:13:65:24 | ... == ... | Collections.cs:65:13:65:13 | access to local variable x | true |
3939
| Collections.cs:68:13:68:13 | access to local variable x | Collections.cs:65:13:65:24 | ... == ... | Collections.cs:65:13:65:13 | access to local variable x | true |
4040
| Collections.cs:96:31:96:34 | access to parameter args | Collections.cs:95:29:95:32 | access to parameter args | Collections.cs:95:29:95:32 | access to parameter args | non-empty |
41-
| Collections.cs:103:27:103:30 | access to parameter args | Collections.cs:101:29:101:32 | access to parameter args | Collections.cs:101:29:101:32 | access to parameter args | empty |
4241
| Guards.cs:12:13:12:13 | access to parameter s | Guards.cs:10:16:10:16 | access to parameter s | Guards.cs:10:16:10:16 | access to parameter s | non-null |
4342
| Guards.cs:12:13:12:13 | access to parameter s | Guards.cs:10:16:10:24 | ... == ... | Guards.cs:10:16:10:16 | access to parameter s | false |
4443
| Guards.cs:14:31:14:31 | access to parameter s | Guards.cs:10:16:10:16 | access to parameter s | Guards.cs:10:16:10:16 | access to parameter s | non-null |

csharp/ql/test/library-tests/controlflow/guards/GuardedExpr.expected

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
| Collections.cs:67:13:67:13 | access to local variable x | Collections.cs:65:13:65:24 | ... == ... | Collections.cs:65:13:65:13 | access to local variable x | true |
3939
| Collections.cs:68:13:68:13 | access to local variable x | Collections.cs:65:13:65:24 | ... == ... | Collections.cs:65:13:65:13 | access to local variable x | true |
4040
| Collections.cs:96:31:96:34 | access to parameter args | Collections.cs:95:29:95:32 | access to parameter args | Collections.cs:95:29:95:32 | access to parameter args | non-empty |
41-
| Collections.cs:103:27:103:30 | access to parameter args | Collections.cs:101:29:101:32 | access to parameter args | Collections.cs:101:29:101:32 | access to parameter args | empty |
4241
| Guards.cs:12:13:12:13 | access to parameter s | Guards.cs:10:16:10:16 | access to parameter s | Guards.cs:10:16:10:16 | access to parameter s | non-null |
4342
| Guards.cs:12:13:12:13 | access to parameter s | Guards.cs:10:16:10:24 | ... == ... | Guards.cs:10:16:10:16 | access to parameter s | false |
4443
| Guards.cs:14:31:14:31 | access to parameter s | Guards.cs:10:16:10:16 | access to parameter s | Guards.cs:10:16:10:16 | access to parameter s | non-null |

0 commit comments

Comments
 (0)