C#: Fix false-positives in cs/dereferenced-value-may-be-null

Dereferencing an expression of a nullable type should only be reported when
the expression is not clearly non-null.
This commit is contained in:
Tom Hvitved
2020-07-28 10:52:15 +02:00
parent ce2368de96
commit d39a33655f
7 changed files with 13 additions and 10 deletions

View File

@@ -876,6 +876,8 @@ module Internal {
not e.(QualifiableExpr).isConditional()
or
e instanceof SuppressNullableWarningExpr
or
e.stripCasts().getType() = any(ValueType t | not t instanceof NullableType)
}
/** Holds if expression `e2` is a non-`null` value whenever `e1` is. */

View File

@@ -231,6 +231,7 @@ private predicate defMaybeNull(Ssa::Definition def, string msg, Element reason)
exists(Dereference d | dereferenceAt(_, _, def, d) |
d.hasNullableType() and
not def instanceof Ssa::PseudoDefinition and
not nonNullDef(def) and
reason = def.getSourceVariable().getAssignable() and
msg = "because it has a nullable type"
)

View File

@@ -8,7 +8,10 @@ alwaysNull
| dataflow.cs:80:21:80:44 | access to property NullProperty |
| dataflow.cs:89:31:89:44 | call to method NullFunction |
alwaysNotNull
| dataflow.cs:71:13:71:20 | access to local variable nonNull1 |
| dataflow.cs:71:13:71:35 | Int32 nonNull1 = ... |
| dataflow.cs:71:24:71:35 | default(...) |
| dataflow.cs:71:32:71:34 | access to type Int32 |
| dataflow.cs:72:27:72:30 | this access |
| dataflow.cs:72:27:72:40 | call to method GetType |
| dataflow.cs:73:30:73:33 | true |
@@ -25,6 +28,7 @@ alwaysNotNull
| dataflow.cs:85:24:85:30 | access to local variable nonNull |
| dataflow.cs:85:24:85:55 | call to method ReturnsNonNullIndirect |
| dataflow.cs:86:24:86:30 | access to local variable nonNull |
| dataflow.cs:89:24:89:27 | access to field cond |
| dataflow.cs:89:24:89:27 | this access |
| dataflow.cs:89:31:89:44 | this access |
| dataflow.cs:89:48:89:51 | this access |

View File

@@ -389,13 +389,13 @@ public class E
int Ex38(int? i)
{
i ??= 0;
return i.Value; // GOOD (false positive)
return i.Value; // GOOD
}
System.Drawing.Color Ex39(System.Drawing.Color? color)
{
color ??= System.Drawing.Color.White;
return color.Value; // GOOD (false positive)
return color.Value; // GOOD
}
}

View File

@@ -1115,12 +1115,14 @@
| E.cs:176:13:176:14 | access to local variable b2 | true | E.cs:175:19:175:42 | ... ? ... : ... | true |
| E.cs:176:13:176:22 | ... == ... | false | E.cs:176:13:176:14 | (...) ... | non-null |
| E.cs:176:13:176:22 | ... == ... | true | E.cs:176:13:176:14 | (...) ... | null |
| E.cs:176:13:176:22 | ... == ... | true | E.cs:176:19:176:22 | null | non-null |
| E.cs:180:13:180:23 | ... == ... | false | E.cs:180:13:180:15 | access to parameter obj | non-null |
| E.cs:180:13:180:23 | ... == ... | true | E.cs:180:13:180:15 | access to parameter obj | null |
| E.cs:184:13:184:14 | (...) ... | non-null | E.cs:184:13:184:14 | access to parameter b1 | non-null |
| E.cs:184:13:184:14 | (...) ... | null | E.cs:184:13:184:14 | access to parameter b1 | null |
| E.cs:184:13:184:22 | ... == ... | false | E.cs:184:13:184:14 | (...) ... | non-null |
| E.cs:184:13:184:22 | ... == ... | true | E.cs:184:13:184:14 | (...) ... | null |
| E.cs:184:13:184:22 | ... == ... | true | E.cs:184:19:184:22 | null | non-null |
| E.cs:193:19:193:29 | call to method ToString | non-null | E.cs:193:17:193:17 | access to parameter o | non-null |
| E.cs:198:17:198:29 | ... ? ... : ... | non-null | E.cs:198:17:198:17 | access to parameter b | false |
| E.cs:198:17:198:29 | ... ? ... : ... | non-null | E.cs:198:28:198:29 | "" | non-null |

View File

@@ -219,10 +219,12 @@
| E.cs:175:19:175:29 | ... == ... | E.cs:175:19:175:21 | access to parameter obj | true | true |
| E.cs:176:13:176:22 | ... == ... | E.cs:176:13:176:14 | (...) ... | false | false |
| E.cs:176:13:176:22 | ... == ... | E.cs:176:13:176:14 | (...) ... | true | true |
| E.cs:176:13:176:22 | ... == ... | E.cs:176:19:176:22 | null | true | false |
| E.cs:180:13:180:23 | ... == ... | E.cs:180:13:180:15 | access to parameter obj | false | false |
| E.cs:180:13:180:23 | ... == ... | E.cs:180:13:180:15 | access to parameter obj | true | true |
| E.cs:184:13:184:22 | ... == ... | E.cs:184:13:184:14 | (...) ... | false | false |
| E.cs:184:13:184:22 | ... == ... | E.cs:184:13:184:14 | (...) ... | true | true |
| E.cs:184:13:184:22 | ... == ... | E.cs:184:19:184:22 | null | true | false |
| E.cs:193:17:193:17 | access to parameter o | E.cs:193:17:193:17 | access to parameter o | non-null | false |
| E.cs:193:17:193:17 | access to parameter o | E.cs:193:17:193:17 | access to parameter o | null | true |
| E.cs:208:13:208:23 | ... is ... | E.cs:208:13:208:13 | access to parameter s | false | true |

View File

@@ -370,10 +370,6 @@ nodes
| E.cs:384:27:384:28 | access to parameter e2 |
| E.cs:386:16:386:17 | access to parameter e1 |
| E.cs:386:27:386:28 | access to parameter e2 |
| E.cs:391:9:391:15 | SSA def(i) |
| E.cs:392:16:392:16 | access to parameter i |
| E.cs:397:9:397:44 | SSA def(color) |
| E.cs:398:16:398:20 | access to parameter color |
| Forwarding.cs:7:16:7:23 | SSA def(s) |
| Forwarding.cs:14:9:17:9 | if (...) ... |
| Forwarding.cs:19:9:22:9 | if (...) ... |
@@ -723,8 +719,6 @@ edges
| E.cs:384:9:385:24 | if (...) ... | E.cs:384:27:384:28 | access to parameter e2 |
| E.cs:384:9:385:24 | if (...) ... | E.cs:386:27:386:28 | access to parameter e2 |
| E.cs:384:27:384:28 | access to parameter e2 | E.cs:386:16:386:17 | access to parameter e1 |
| E.cs:391:9:391:15 | SSA def(i) | E.cs:392:16:392:16 | access to parameter i |
| E.cs:397:9:397:44 | SSA def(color) | E.cs:398:16:398:20 | access to parameter color |
| Forwarding.cs:7:16:7:23 | SSA def(s) | Forwarding.cs:14:9:17:9 | if (...) ... |
| Forwarding.cs:14:9:17:9 | if (...) ... | Forwarding.cs:19:9:22:9 | if (...) ... |
| Forwarding.cs:19:9:22:9 | if (...) ... | Forwarding.cs:24:9:27:9 | if (...) ... |
@@ -833,8 +827,6 @@ edges
| 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 |
| 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 |
| 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 |
| E.cs:392:16:392:16 | access to parameter i | E.cs:391:9:391:15 | SSA def(i) | E.cs:392:16:392:16 | access to parameter i | Variable $@ may be null here because it has a nullable type. | E.cs:389:19:389:19 | i | i | E.cs:389:19:389:19 | i | this |
| E.cs:398:16:398:20 | access to parameter color | E.cs:397:9:397:44 | SSA def(color) | E.cs:398:16:398:20 | access to parameter color | Variable $@ may be null here because it has a nullable type. | E.cs:395:53:395:57 | color | color | E.cs:395:53:395:57 | color | this |
| 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 |
| 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 |
| 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 |