mirror of
https://github.com/github/codeql.git
synced 2026-04-26 01:05:15 +02:00
Merge pull request #1441 from calumgrant/cs/nullable-warning-expressions
C#: Extract SuppressNullableWarning expressions
This commit is contained in:
@@ -242,6 +242,9 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
case SyntaxKind.SwitchExpression:
|
||||
return Switch.Create(info);
|
||||
|
||||
case SyntaxKind.SuppressNullableWarningExpression:
|
||||
return PostfixUnary.Create(info.SetKind(ExprKind.SUPPRESS_NULLABLE_WARNING), ((PostfixUnaryExpressionSyntax)info.Node).Operand);
|
||||
|
||||
default:
|
||||
info.Context.ModelError(info.Node, $"Unhandled expression '{info.Node}' of kind '{info.Node.Kind()}'");
|
||||
return new Unknown(info);
|
||||
|
||||
@@ -113,6 +113,7 @@ namespace Semmle.Extraction.Kinds
|
||||
PROPERTY_PATTERN = 116,
|
||||
POSITIONAL_PATTERN = 117,
|
||||
SWITCH_CASE = 118,
|
||||
ASSIGN_COALESCE = 119
|
||||
ASSIGN_COALESCE = 119,
|
||||
SUPPRESS_NULLABLE_WARNING = 120
|
||||
}
|
||||
}
|
||||
|
||||
@@ -673,6 +673,8 @@ module Internal {
|
||||
or
|
||||
e.(Call).getTarget().getSourceDeclaration() instanceof NonNullCallable and
|
||||
not e.(QualifiableExpr).isConditional()
|
||||
or
|
||||
e instanceof SuppressNullableWarningExpr
|
||||
}
|
||||
|
||||
/** Holds if expression `e2` is a non-`null` value whenever `e1` is. */
|
||||
|
||||
@@ -83,6 +83,10 @@ module LocalFlow {
|
||||
scope = e2 and
|
||||
isSuccessor = true
|
||||
or
|
||||
e1 = e2.(SuppressNullableWarningExpr).getExpr() and
|
||||
scope = e2 and
|
||||
isSuccessor = true
|
||||
or
|
||||
e2 = any(ConditionalExpr ce |
|
||||
e1 = ce.getThen() or
|
||||
e1 = ce.getElse()
|
||||
|
||||
@@ -990,3 +990,20 @@ class IndexExpr extends Expr, @index_expr {
|
||||
|
||||
override string toString() { result = "^..." }
|
||||
}
|
||||
|
||||
/**
|
||||
* A nullable warning suppression expression, for example `x!` in
|
||||
* ```
|
||||
* string GetName()
|
||||
* {
|
||||
* string? x = ...;
|
||||
* return x!;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class SuppressNullableWarningExpr extends Expr, @suppress_nullable_warning_expr {
|
||||
/** Gets the expression, for example `x` in `x!`. */
|
||||
Expr getExpr() { result.getParent() = this }
|
||||
|
||||
override string toString() { result = "...!" }
|
||||
}
|
||||
|
||||
@@ -987,6 +987,7 @@ case @expr.kind of
|
||||
| 117 = @positional_pattern_expr
|
||||
| 118 = @switch_case_expr
|
||||
| 119 = @assign_coalesce_expr
|
||||
| 120 = @suppress_nullable_warning_expr
|
||||
;
|
||||
|
||||
@switch = @switch_stmt | @switch_expr;
|
||||
|
||||
@@ -836,6 +836,10 @@
|
||||
<v>0</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@suppress_nullable_warning_expr</k>
|
||||
<v>500</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@xmldtd</k>
|
||||
<v>2</v>
|
||||
</e>
|
||||
|
||||
13
csharp/ql/test/library-tests/csharp8/NullableRefTypes.cs
Normal file
13
csharp/ql/test/library-tests/csharp8/NullableRefTypes.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
|
||||
class NullableRefTypes
|
||||
{
|
||||
void TestNullableRefTypes()
|
||||
{
|
||||
string? x = "source";
|
||||
string y = x!;
|
||||
y = x!!;
|
||||
x = null;
|
||||
y = x!;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
suppressNullableWarnings
|
||||
| NullableRefTypes.cs:8:20:8:21 | ...! | NullableRefTypes.cs:8:20:8:20 | access to local variable x |
|
||||
| NullableRefTypes.cs:9:13:9:14 | ...! | NullableRefTypes.cs:9:13:9:13 | access to local variable x |
|
||||
| NullableRefTypes.cs:9:13:9:15 | ...! | NullableRefTypes.cs:9:13:9:14 | ...! |
|
||||
| NullableRefTypes.cs:11:13:11:14 | ...! | NullableRefTypes.cs:11:13:11:13 | access to local variable x |
|
||||
nullableDataFlow
|
||||
| NullableRefTypes.cs:7:17:7:28 | SSA def(x) | NullableRefTypes.cs:8:20:8:20 | access to local variable x |
|
||||
| NullableRefTypes.cs:7:21:7:28 | "source" | NullableRefTypes.cs:7:17:7:28 | SSA def(x) |
|
||||
| NullableRefTypes.cs:8:20:8:20 | access to local variable x | NullableRefTypes.cs:8:20:8:21 | ...! |
|
||||
| NullableRefTypes.cs:8:20:8:20 | access to local variable x | NullableRefTypes.cs:9:13:9:13 | access to local variable x |
|
||||
| NullableRefTypes.cs:9:13:9:13 | access to local variable x | NullableRefTypes.cs:9:13:9:14 | ...! |
|
||||
| NullableRefTypes.cs:9:13:9:14 | ...! | NullableRefTypes.cs:9:13:9:15 | ...! |
|
||||
| NullableRefTypes.cs:10:9:10:16 | SSA def(x) | NullableRefTypes.cs:11:13:11:13 | access to local variable x |
|
||||
| NullableRefTypes.cs:10:13:10:16 | null | NullableRefTypes.cs:10:9:10:16 | SSA def(x) |
|
||||
| NullableRefTypes.cs:11:13:11:13 | access to local variable x | NullableRefTypes.cs:11:13:11:14 | ...! |
|
||||
nullableControlFlow
|
||||
| NullableRefTypes.cs:5:10:5:29 | enter TestNullableRefTypes | NullableRefTypes.cs:6:5:12:5 | {...} | successor |
|
||||
| NullableRefTypes.cs:6:5:12:5 | {...} | NullableRefTypes.cs:7:9:7:29 | ... ...; | successor |
|
||||
| NullableRefTypes.cs:7:9:7:29 | ... ...; | NullableRefTypes.cs:7:21:7:28 | "source" | successor |
|
||||
| NullableRefTypes.cs:7:17:7:28 | String x = ... | NullableRefTypes.cs:8:9:8:22 | ... ...; | successor |
|
||||
| NullableRefTypes.cs:7:21:7:28 | "source" | NullableRefTypes.cs:7:17:7:28 | String x = ... | successor |
|
||||
| NullableRefTypes.cs:8:9:8:22 | ... ...; | NullableRefTypes.cs:8:20:8:20 | access to local variable x | successor |
|
||||
| NullableRefTypes.cs:8:16:8:21 | String y = ... | NullableRefTypes.cs:9:9:9:16 | ...; | successor |
|
||||
| NullableRefTypes.cs:8:20:8:20 | access to local variable x | NullableRefTypes.cs:8:20:8:21 | ...! | successor |
|
||||
| NullableRefTypes.cs:8:20:8:21 | ...! | NullableRefTypes.cs:8:16:8:21 | String y = ... | successor |
|
||||
| NullableRefTypes.cs:9:9:9:15 | ... = ... | NullableRefTypes.cs:10:9:10:17 | ...; | successor |
|
||||
| NullableRefTypes.cs:9:9:9:16 | ...; | NullableRefTypes.cs:9:13:9:13 | access to local variable x | successor |
|
||||
| NullableRefTypes.cs:9:13:9:13 | access to local variable x | NullableRefTypes.cs:9:13:9:14 | ...! | successor |
|
||||
| NullableRefTypes.cs:9:13:9:14 | ...! | NullableRefTypes.cs:9:13:9:15 | ...! | successor |
|
||||
| NullableRefTypes.cs:9:13:9:15 | ...! | NullableRefTypes.cs:9:9:9:15 | ... = ... | successor |
|
||||
| NullableRefTypes.cs:10:9:10:16 | ... = ... | NullableRefTypes.cs:11:9:11:15 | ...; | successor |
|
||||
| NullableRefTypes.cs:10:9:10:17 | ...; | NullableRefTypes.cs:10:13:10:16 | null | successor |
|
||||
| NullableRefTypes.cs:10:13:10:16 | null | NullableRefTypes.cs:10:9:10:16 | ... = ... | successor |
|
||||
| NullableRefTypes.cs:11:9:11:14 | ... = ... | NullableRefTypes.cs:5:10:5:29 | exit TestNullableRefTypes | successor |
|
||||
| NullableRefTypes.cs:11:9:11:15 | ...; | NullableRefTypes.cs:11:13:11:13 | access to local variable x | successor |
|
||||
| NullableRefTypes.cs:11:13:11:13 | access to local variable x | NullableRefTypes.cs:11:13:11:14 | ...! | successor |
|
||||
| NullableRefTypes.cs:11:13:11:14 | ...! | NullableRefTypes.cs:11:9:11:14 | ... = ... | successor |
|
||||
nonNullExpressions
|
||||
| NullableRefTypes.cs:7:21:7:28 | "source" |
|
||||
| NullableRefTypes.cs:8:20:8:20 | access to local variable x |
|
||||
| NullableRefTypes.cs:8:20:8:21 | ...! |
|
||||
| NullableRefTypes.cs:9:9:9:15 | ... = ... |
|
||||
| NullableRefTypes.cs:9:13:9:13 | access to local variable x |
|
||||
| NullableRefTypes.cs:9:13:9:14 | ...! |
|
||||
| NullableRefTypes.cs:9:13:9:15 | ...! |
|
||||
| NullableRefTypes.cs:11:9:11:14 | ... = ... |
|
||||
| NullableRefTypes.cs:11:13:11:14 | ...! |
|
||||
22
csharp/ql/test/library-tests/csharp8/NullableRefTypes.ql
Normal file
22
csharp/ql/test/library-tests/csharp8/NullableRefTypes.ql
Normal file
@@ -0,0 +1,22 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.dataflow.Nullness
|
||||
|
||||
query predicate suppressNullableWarnings(SuppressNullableWarningExpr e, Expr op) {
|
||||
op = e.getExpr()
|
||||
}
|
||||
|
||||
query predicate nullableDataFlow(DataFlow::Node src, DataFlow::Node sink) {
|
||||
src.getEnclosingCallable().hasName("TestNullableRefTypes") and
|
||||
DataFlow::localFlowStep(src, sink)
|
||||
}
|
||||
|
||||
query predicate nullableControlFlow(
|
||||
ControlFlow::Node a, ControlFlow::Node b, ControlFlow::SuccessorType t
|
||||
) {
|
||||
a.getEnclosingCallable().hasName("TestNullableRefTypes") and
|
||||
b = a.getASuccessorByType(t)
|
||||
}
|
||||
|
||||
query predicate nonNullExpressions(NonNullExpr e) {
|
||||
e.getEnclosingCallable().getName() = "TestNullableRefTypes"
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Support for suppress-nullable-warning expressions.
|
||||
compatibility: backwards
|
||||
Reference in New Issue
Block a user