Skip to content

Commit 05307b8

Browse files
committed
C#: Remove more FPs in cs/dereferenced-value-may-be-null
1 parent 4f4d9d3 commit 05307b8

File tree

3 files changed

+38
-41
lines changed

3 files changed

+38
-41
lines changed

csharp/ql/src/semmle/code/csharp/dataflow/Nullness.qll

Lines changed: 37 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -197,43 +197,44 @@ private predicate isNullDefaultArgument(Ssa::ExplicitDefinition def, AlwaysNullE
197197

198198
/** Holds if `def` is an SSA definition that may be `null`. */
199199
private predicate defMaybeNull(Ssa::Definition def, string msg, Element reason) {
200-
// A variable compared to `null` might be `null`
201-
exists(G::DereferenceableExpr de | de = def.getARead() |
202-
reason = de.getANullCheck(_, true) and
203-
msg = "as suggested by $@ null check" and
204-
not de = any(Ssa::PseudoDefinition pdef).getARead() and
205-
strictcount(Element e | e = any(Ssa::Definition def0 | de = def0.getARead()).getElement()) = 1 and
206-
not nonNullDef(def) and
207-
// Don't use a check as reason if there is a `null` assignment
208-
// or argument
209-
not def.(Ssa::ExplicitDefinition).getADefinition().getSource() instanceof MaybeNullExpr and
210-
not isMaybeNullArgument(def, _)
211-
)
212-
or
213-
// A parameter might be `null` if there is a `null` argument somewhere
214-
isMaybeNullArgument(def, reason) and
200+
not nonNullDef(def) and
215201
(
216-
if reason instanceof AlwaysNullExpr
217-
then msg = "because of $@ null argument"
218-
else msg = "because of $@ potential null argument"
219-
)
220-
or
221-
isNullDefaultArgument(def, reason) and msg = "because the parameter has a null default value"
222-
or
223-
// If the source of a variable is `null` then the variable may be `null`
224-
exists(AssignableDefinition adef | adef = def.(Ssa::ExplicitDefinition).getADefinition() |
225-
adef.getSource() instanceof MaybeNullExpr and
226-
reason = adef.getExpr() and
227-
msg = "because of $@ assignment"
228-
)
229-
or
230-
// A variable of nullable type may be null
231-
exists(Dereference d | dereferenceAt(_, _, def, d) |
232-
d.hasNullableType() and
233-
not def instanceof Ssa::PseudoDefinition and
234-
not nonNullDef(def) and
235-
reason = def.getSourceVariable().getAssignable() and
236-
msg = "because it has a nullable type"
202+
// A variable compared to `null` might be `null`
203+
exists(G::DereferenceableExpr de | de = def.getARead() |
204+
reason = de.getANullCheck(_, true) and
205+
msg = "as suggested by $@ null check" and
206+
not de = any(Ssa::PseudoDefinition pdef).getARead() and
207+
strictcount(Element e | e = any(Ssa::Definition def0 | de = def0.getARead()).getElement()) = 1 and
208+
// Don't use a check as reason if there is a `null` assignment
209+
// or argument
210+
not def.(Ssa::ExplicitDefinition).getADefinition().getSource() instanceof MaybeNullExpr and
211+
not isMaybeNullArgument(def, _)
212+
)
213+
or
214+
// A parameter might be `null` if there is a `null` argument somewhere
215+
isMaybeNullArgument(def, reason) and
216+
(
217+
if reason instanceof AlwaysNullExpr
218+
then msg = "because of $@ null argument"
219+
else msg = "because of $@ potential null argument"
220+
)
221+
or
222+
isNullDefaultArgument(def, reason) and msg = "because the parameter has a null default value"
223+
or
224+
// If the source of a variable is `null` then the variable may be `null`
225+
exists(AssignableDefinition adef | adef = def.(Ssa::ExplicitDefinition).getADefinition() |
226+
adef.getSource() instanceof MaybeNullExpr and
227+
reason = adef.getExpr() and
228+
msg = "because of $@ assignment"
229+
)
230+
or
231+
// A variable of nullable type may be null
232+
exists(Dereference d | dereferenceAt(_, _, def, d) |
233+
d.hasNullableType() and
234+
not def instanceof Ssa::PseudoDefinition and
235+
reason = def.getSourceVariable().getAssignable() and
236+
msg = "because it has a nullable type"
237+
)
237238
)
238239
}
239240

csharp/ql/test/query-tests/Nullness/E.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ int Ex41()
409409
{
410410
int? i = 1;
411411
i ??= null;
412-
return i.Value; // GOOD (false positive)
412+
return i.Value; // GOOD
413413
}
414414
}
415415

csharp/ql/test/query-tests/Nullness/NullMaybe.expected

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -373,8 +373,6 @@ nodes
373373
| E.cs:404:9:404:18 | SSA def(i) |
374374
| E.cs:404:9:404:18 | SSA def(i) |
375375
| E.cs:405:16:405:16 | access to local variable i |
376-
| E.cs:411:9:411:18 | SSA def(i) |
377-
| E.cs:412:16:412:16 | access to local variable i |
378376
| Forwarding.cs:7:16:7:23 | SSA def(s) |
379377
| Forwarding.cs:14:9:17:9 | if (...) ... |
380378
| Forwarding.cs:19:9:22:9 | if (...) ... |
@@ -726,7 +724,6 @@ edges
726724
| E.cs:384:27:384:28 | access to parameter e2 | E.cs:386:16:386:17 | access to parameter e1 |
727725
| E.cs:404:9:404:18 | SSA def(i) | E.cs:405:16:405:16 | access to local variable i |
728726
| E.cs:404:9:404:18 | SSA def(i) | E.cs:405:16:405:16 | access to local variable i |
729-
| E.cs:411:9:411:18 | SSA def(i) | E.cs:412:16:412:16 | access to local variable i |
730727
| Forwarding.cs:7:16:7:23 | SSA def(s) | Forwarding.cs:14:9:17:9 | if (...) ... |
731728
| Forwarding.cs:14:9:17:9 | if (...) ... | Forwarding.cs:19:9:22:9 | if (...) ... |
732729
| Forwarding.cs:19:9:22:9 | if (...) ... | Forwarding.cs:24:9:27:9 | if (...) ... |
@@ -835,7 +832,6 @@ edges
835832
| E.cs:386:27:386:28 | access to parameter e2 | E.cs:380:30:380:31 | SSA param(e2) | E.cs:386:27:386:28 | access to parameter e2 | Variable $@ may be null here as suggested by $@ null check. | E.cs:380:30:380:31 | e2 | e2 | E.cs:382:28:382:37 | ... != ... | this |
836833
| E.cs:386:27:386:28 | access to parameter e2 | E.cs:380:30:380:31 | SSA param(e2) | E.cs:386:27:386:28 | access to parameter e2 | Variable $@ may be null here as suggested by $@ null check. | E.cs:380:30:380:31 | e2 | e2 | E.cs:382:58:382:67 | ... == ... | this |
837834
| E.cs:386:27:386:28 | access to parameter e2 | E.cs:380:30:380:31 | SSA param(e2) | E.cs:386:27:386:28 | access to parameter e2 | Variable $@ may be null here as suggested by $@ null check. | E.cs:380:30:380:31 | e2 | e2 | E.cs:384:27:384:36 | ... == ... | this |
838-
| E.cs:412:16:412:16 | access to local variable i | E.cs:411:9:411:18 | SSA def(i) | E.cs:412:16:412:16 | access to local variable i | Variable $@ may be null here because of $@ assignment. | E.cs:410:14:410:14 | i | i | E.cs:411:9:411:18 | ... = ... | this |
839835
| GuardedString.cs:35:31:35:31 | access to local variable s | GuardedString.cs:7:16:7:32 | SSA def(s) | GuardedString.cs:35:31:35:31 | access to local variable s | Variable $@ may be null here because of $@ assignment. | GuardedString.cs:7:16:7:16 | s | s | GuardedString.cs:7:16:7:32 | String s = ... | this |
840836
| NullMaybeBad.cs:7:27:7:27 | access to parameter o | NullMaybeBad.cs:13:17:13:20 | null | NullMaybeBad.cs:7:27:7:27 | access to parameter o | Variable $@ may be null here because of $@ null argument. | NullMaybeBad.cs:5:25:5:25 | o | o | NullMaybeBad.cs:13:17:13:20 | null | this |
841837
| StringConcatenation.cs:16:17:16:17 | access to local variable s | StringConcatenation.cs:14:16:14:23 | SSA def(s) | StringConcatenation.cs:16:17:16:17 | access to local variable s | Variable $@ may be null here because of $@ assignment. | StringConcatenation.cs:14:16:14:16 | s | s | StringConcatenation.cs:14:16:14:23 | String s = ... | this |

0 commit comments

Comments
 (0)