Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The `MaybeNullExpr` class now takes null-conditional access (such as `?.` and `?[]`) into account when modeling potential null values.
6 changes: 6 additions & 0 deletions csharp/ql/lib/semmle/code/csharp/dataflow/Nullness.qll
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ private Expr maybeNullExpr(Expr reason) {
)
or
result.(NullCoalescingExpr).getRightOperand() = maybeNullExpr(reason)
or
result =
any(QualifiableExpr qe |
qe.isConditional() and
qe.getQualifier() = maybeNullExpr(reason)
)
}

/** An expression that may be `null`. */
Expand Down
32 changes: 32 additions & 0 deletions csharp/ql/test/library-tests/nullconditional/NullConditional.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;

public class C
{
public int Field;

public string Property { get; set; } = "";

public void M(C c, int[] numbers, bool b)
{
// Get values.
var fieldValue = c?.Field;
var propertyValue = c?.Property;
var n = numbers?[0];

// Set values
c?.Field = 42;
c?.Property = "Hello";
numbers?[0] = 7;

// Set values using operators
c?.Field -= 1;
c?.Property += " World";

// Using the return of an assignment
var x = c?.Field = 10;

// Using in a conditional expression
int? maybenull = 0;
maybenull = (b ? c : null)?.Field;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
| NullConditional.cs:30:9:30:41 | ... = ... |
| NullConditional.cs:30:21:30:41 | access to field Field |
| NullConditional.cs:30:22:30:33 | ... ? ... : ... |
| NullConditional.cs:30:30:30:33 | null |
6 changes: 6 additions & 0 deletions csharp/ql/test/library-tests/nullconditional/maybenull.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import csharp
import semmle.code.csharp.dataflow.Nullness

from MaybeNullExpr mne
where mne.getFile().getBaseName() = "NullConditional.cs"
select mne
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
| NullConditional.cs:12:26:12:33 | access to field Field |
| NullConditional.cs:13:29:13:39 | access to property Property |
| NullConditional.cs:14:17:14:27 | access to array element |
| NullConditional.cs:17:9:17:16 | access to field Field |
| NullConditional.cs:18:9:18:19 | access to property Property |
| NullConditional.cs:19:9:19:19 | access to array element |
| NullConditional.cs:22:9:22:16 | access to field Field |
| NullConditional.cs:22:9:22:16 | access to field Field |
| NullConditional.cs:23:9:23:19 | access to property Property |
| NullConditional.cs:23:9:23:19 | access to property Property |
| NullConditional.cs:26:17:26:24 | access to field Field |
| NullConditional.cs:30:21:30:41 | access to field Field |
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import csharp

from QualifiableExpr e
where e.isConditional()
select e
2 changes: 2 additions & 0 deletions csharp/ql/test/library-tests/nullconditional/options
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
semmle-extractor-options: /nostdlib /noconfig
semmle-extractor-options: --load-sources-from-project:${testdir}/../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj