diff --git a/csharp/ql/src/semmle/code/csharp/XML.qll b/csharp/ql/src/semmle/code/csharp/XML.qll index db84dc35baf9..d5399e27740e 100644 --- a/csharp/ql/src/semmle/code/csharp/XML.qll +++ b/csharp/ql/src/semmle/code/csharp/XML.qll @@ -5,13 +5,6 @@ import semmle.code.csharp.Element import semmle.code.csharp.Location -/** Adapter so that XMLLocatables are elements */ -library class XMLLocatableElement extends @xmllocatable, Element { - override string toString() { result = this.(XMLLocatable).toString() } - - override Location getALocation() { result = this.(XMLLocatable).getALocation() } -} - /** An XML element that has a location. */ class XMLLocatable extends @xmllocatable { XMLLocatable() { diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll b/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll index 00841dbe3ce2..3841a96d9f36 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll @@ -793,7 +793,10 @@ module Internal { TBooleanValue(boolean b) { b = true or b = false } or TIntegerValue(int i) { i = any(Expr e).getValue().toInt() } or TNullValue(boolean b) { b = true or b = false } or - TMatchValue(Case c, boolean b) { b = true or b = false } or + TMatchValue(Case c, boolean b) { + exists(c.getPattern()) and + (b = true or b = false) + } or TEmptyCollectionValue(boolean b) { b = true or b = false } /** A callable that always returns a `null` value. */ diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index 912e9ec1280e..06a82f8ef4dd 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -355,7 +355,7 @@ private module Cached { TSsaDefinitionNode(Ssa::Definition def) or TInstanceParameterNode(Callable c) { c.hasBody() and not c.(Modifiable).isStatic() } or TCilParameterNode(CIL::Parameter p) { p.getMethod().hasBody() } or - TTaintedParameterNode(Parameter p) { p.getCallable().hasBody() } or + TTaintedParameterNode(Parameter p) { explicitParameterNode(_, p) } or TTaintedReturnNode(ControlFlow::Nodes::ElementNode cfn) { any(Callable c).canYieldReturn(cfn.getElement()) } or diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Call.qll b/csharp/ql/src/semmle/code/csharp/exprs/Call.qll index 5eba096e8b40..9e451781c540 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Call.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Call.qll @@ -295,7 +295,7 @@ class MethodCall extends Call, QualifiableExpr, LateBindableExpr, @method_invoca override Method getQualifiedDeclaration() { result = getTarget() } - override string toString() { result = "call to method " + this.getTarget().getName() } + override string toString() { result = "call to method " + concat(this.getTarget().getName()) } override Expr getRawArgument(int i) { if exists(getQualifier()) diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll b/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll index 6fa563b99ef7..e3226db31cb3 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll @@ -116,10 +116,17 @@ private predicate isDynamicElementAccess(@dynamic_element_access_expr e) { any() * A local variable declaration, for example `var i = 0`. */ class LocalVariableDeclExpr extends Expr, @local_var_decl_expr { - /** Gets the local variable being declared. */ + /** + * Gets the local variable being declared, if any. The only case where + * no variable is declared is when a discard symbol is used, for example + * ``` + * if (int.TryParse(s, out var _)) + * ... + * ``` + */ LocalVariable getVariable() { localvars(result, _, _, _, _, this) } - /** Gets the name of the variable being declared. */ + /** Gets the name of the variable being declared, if any. */ string getName() { result = this.getVariable().getName() } /** Gets the initializer expression of this local variable declaration, if any. */ @@ -136,6 +143,9 @@ class LocalVariableDeclExpr extends Expr, @local_var_decl_expr { override string toString() { result = this.getVariable().getType().getName() + " " + this.getName() + or + not exists(this.getVariable()) and + result = "_" } /** Gets the variable access used in this declaration, if any. */ diff --git a/csharp/ql/test/library-tests/dataflow/global/GetAnOutNode.expected b/csharp/ql/test/library-tests/dataflow/global/GetAnOutNode.expected index 34b473e56592..586a0ef9ca8e 100644 --- a/csharp/ql/test/library-tests/dataflow/global/GetAnOutNode.expected +++ b/csharp/ql/test/library-tests/dataflow/global/GetAnOutNode.expected @@ -82,8 +82,8 @@ | GlobalDataFlow.cs:100:24:100:33 | call to method Return | return | GlobalDataFlow.cs:100:24:100:33 | call to method Return | | GlobalDataFlow.cs:102:28:102:63 | call to method GetMethod | return | GlobalDataFlow.cs:102:28:102:63 | call to method GetMethod | | GlobalDataFlow.cs:102:28:102:103 | call to method Invoke | return | GlobalDataFlow.cs:102:28:102:103 | call to method Invoke | -| GlobalDataFlow.cs:104:9:104:46 | call to method ReturnOut | out | GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:104:9:104:46 | call to method ReturnOut | ref | GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) | +| GlobalDataFlow.cs:104:9:104:49 | call to method ReturnOut | out | GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) | +| GlobalDataFlow.cs:104:9:104:49 | call to method ReturnOut | ref | GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) | | GlobalDataFlow.cs:106:9:106:49 | call to method ReturnOut | out | GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) | | GlobalDataFlow.cs:108:9:108:49 | call to method ReturnRef | out | GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) | | GlobalDataFlow.cs:108:9:108:49 | call to method ReturnRef | ref | GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) | diff --git a/csharp/ql/test/library-tests/dataflow/global/GlobalDataFlow.cs b/csharp/ql/test/library-tests/dataflow/global/GlobalDataFlow.cs index 5f8300b1a580..41630b7fd8f6 100644 --- a/csharp/ql/test/library-tests/dataflow/global/GlobalDataFlow.cs +++ b/csharp/ql/test/library-tests/dataflow/global/GlobalDataFlow.cs @@ -101,7 +101,7 @@ public void M() Check(nonSink0); nonSink0 = (string)typeof(DataFlow).GetMethod("Return").Invoke(null, new object[] { nonSink0 }); Check(nonSink0); - ReturnOut("", out nonSink0, out var _); + ReturnOut("", out nonSink0, out string _); Check(nonSink0); ReturnOut(sink1, out var _, out nonSink0); Check(nonSink0); diff --git a/csharp/ql/test/library-tests/linq/Linq1.expected b/csharp/ql/test/library-tests/linq/Linq1.expected index 5415468aafd9..b2405edbe0d7 100644 --- a/csharp/ql/test/library-tests/linq/Linq1.expected +++ b/csharp/ql/test/library-tests/linq/Linq1.expected @@ -26,6 +26,8 @@ | queries.cs:27:11:27:42 | call to method Join | 2 | queries.cs:27:21:27:25 | access to local variable list1 | | queries.cs:27:11:27:42 | call to method Join | 3 | queries.cs:27:30:27:33 | access to local variable next | | queries.cs:27:11:27:42 | call to method Join | 4 | queries.cs:27:42:27:42 | access to local variable c | +| queries.cs:28:11:28:18 | call to method | 0 | queries.cs:27:11:27:42 | call to method Join | +| queries.cs:28:11:28:18 | call to method | 1 | queries.cs:28:18:28:18 | 1 | | queries.cs:32:11:32:21 | call to method SelectMany | 0 | queries.cs:31:11:31:25 | IList a = ... | | queries.cs:32:11:32:21 | call to method SelectMany | 1 | queries.cs:32:11:32:21 | IList b = ... | | queries.cs:32:11:32:21 | call to method SelectMany | 2 | queries.cs:32:21:32:21 | access to local variable a | @@ -49,3 +51,5 @@ | queries.cs:55:11:55:49 | call to method GroupJoin | 3 | queries.cs:55:30:55:30 | access to local variable a | | queries.cs:55:11:55:49 | call to method GroupJoin | 4 | queries.cs:55:39:55:42 | access to indexer | | queries.cs:55:11:55:49 | call to method GroupJoin | 5 | queries.cs:55:11:55:49 | IList> d = ... | +| queries.cs:56:11:56:22 | call to method | 0 | queries.cs:55:11:55:49 | call to method GroupJoin | +| queries.cs:56:11:56:22 | call to method | 1 | queries.cs:56:18:56:22 | (..., ...) | diff --git a/csharp/ql/test/library-tests/standalone/controlflow/cfg.expected b/csharp/ql/test/library-tests/standalone/controlflow/cfg.expected index 3989e384b6df..06473196df99 100644 --- a/csharp/ql/test/library-tests/standalone/controlflow/cfg.expected +++ b/csharp/ql/test/library-tests/standalone/controlflow/cfg.expected @@ -5,11 +5,13 @@ | ControlFlow.cs:9:17:9:33 | Call (unknown target) | ControlFlow.cs:9:13:9:33 | (unknown type) v | | ControlFlow.cs:10:9:10:13 | Expression | ControlFlow.cs:10:22:10:22 | access to local variable v | | ControlFlow.cs:10:9:10:43 | Call (unknown target) | ControlFlow.cs:12:9:12:87 | ...; | +| ControlFlow.cs:10:9:10:43 | call to method | ControlFlow.cs:12:9:12:87 | ...; | | ControlFlow.cs:10:9:10:44 | ...; | ControlFlow.cs:10:9:10:13 | Expression | | ControlFlow.cs:10:22:10:22 | access to local variable v | ControlFlow.cs:10:22:10:24 | Expression | | ControlFlow.cs:10:22:10:24 | Expression | ControlFlow.cs:10:22:10:26 | Expression | | ControlFlow.cs:10:22:10:26 | Expression | ControlFlow.cs:10:29:10:42 | "This is true" | | ControlFlow.cs:10:29:10:42 | "This is true" | ControlFlow.cs:10:9:10:43 | Call (unknown target) | +| ControlFlow.cs:10:29:10:42 | "This is true" | ControlFlow.cs:10:9:10:43 | call to method | | ControlFlow.cs:12:9:12:86 | Call (unknown target) | ControlFlow.cs:12:37:12:47 | Expression | | ControlFlow.cs:12:9:12:87 | ...; | ControlFlow.cs:12:9:12:86 | Call (unknown target) | | ControlFlow.cs:12:35:12:86 | { ..., ... } | ControlFlow.cs:7:10:7:10 | exit F | diff --git a/csharp/ql/test/library-tests/standalone/errorrecovery/ErrorCalls.expected b/csharp/ql/test/library-tests/standalone/errorrecovery/ErrorCalls.expected index edfcbf9a93b7..05ae24318c33 100644 --- a/csharp/ql/test/library-tests/standalone/errorrecovery/ErrorCalls.expected +++ b/csharp/ql/test/library-tests/standalone/errorrecovery/ErrorCalls.expected @@ -1,6 +1,6 @@ -| errors.cs:24:31:24:40 | errors.cs:24:31:24:40 | unknown | none | +| errors.cs:24:31:24:40 | errors.cs:24:31:24:40 | call to method | none | | errors.cs:43:21:43:28 | errors.cs:43:21:43:28 | object creation of type C1 | C1 | | errors.cs:44:13:44:19 | errors.cs:44:13:44:19 | call to method m1 | m1 | | errors.cs:45:13:45:19 | errors.cs:45:13:45:19 | call to method m2 | m2 | -| errors.cs:46:13:46:38 | errors.cs:46:13:46:38 | unknown | none | +| errors.cs:46:13:46:38 | errors.cs:46:13:46:38 | call to method | none | | errors.cs:53:17:53:25 | errors.cs:53:17:53:25 | object creation of type C2 | none |