From 5103d34dbf957ed6d017dbffdcfd6aeccd0b7dd4 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 3 Oct 2024 18:57:31 +0100 Subject: [PATCH] PS: Add tests. --- .../code/powershell/controlflow/CfgNodes.qll | 4 +++- .../dataflow/internal/DataFlowDispatch.qll | 2 +- .../dataflow/typetracking/test.expected | 2 ++ .../dataflow/typetracking/test.ps1 | 19 +++++++++++++++ .../dataflow/typetracking/test.ql | 23 +++++++++++++++++++ 5 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 powershell/ql/test/library-tests/dataflow/typetracking/test.expected create mode 100644 powershell/ql/test/library-tests/dataflow/typetracking/test.ps1 create mode 100644 powershell/ql/test/library-tests/dataflow/typetracking/test.ql diff --git a/powershell/ql/lib/semmle/code/powershell/controlflow/CfgNodes.qll b/powershell/ql/lib/semmle/code/powershell/controlflow/CfgNodes.qll index 47218131304..c58305e421c 100644 --- a/powershell/ql/lib/semmle/code/powershell/controlflow/CfgNodes.qll +++ b/powershell/ql/lib/semmle/code/powershell/controlflow/CfgNodes.qll @@ -128,6 +128,8 @@ abstract private class NonExprChildMapping extends ChildMapping { abstract private class AbstractCallCfgNode extends AstCfgNode { override string getAPrimaryQlClass() { result = "CfgCall" } + final predicate hasName(string name) { this.getName() = name } + abstract string getName(); ExprCfgNode getQualifier() { none() } @@ -231,7 +233,7 @@ module ExprNodes { final override ExprCfgNode getCommand() { none() } } - /** A control-flow node that wraps an `ConstructorCall` expression. */ + /** A control-flow node that wraps an `ConstructorCall` expression. */ class ConstructorCallCfgNode extends InvokeMemberCfgNode { ConstructorCallCfgNode() { super.getExpr() instanceof ConstructorCall } diff --git a/powershell/ql/lib/semmle/code/powershell/dataflow/internal/DataFlowDispatch.qll b/powershell/ql/lib/semmle/code/powershell/dataflow/internal/DataFlowDispatch.qll index ac176a6b29b..33234b957f1 100644 --- a/powershell/ql/lib/semmle/code/powershell/dataflow/internal/DataFlowDispatch.qll +++ b/powershell/ql/lib/semmle/code/powershell/dataflow/internal/DataFlowDispatch.qll @@ -155,7 +155,7 @@ private predicate qualifiedCall(CfgNodes::CallCfgNode call, Node receiver, strin call.getName() = method } -private Node trackInstance(Type t, boolean exact) { +Node trackInstance(Type t, boolean exact) { result = CallGraphConstruction::Make::track(TrackInstanceInput::MkState(t, exact)) } diff --git a/powershell/ql/test/library-tests/dataflow/typetracking/test.expected b/powershell/ql/test/library-tests/dataflow/typetracking/test.expected new file mode 100644 index 00000000000..8ec8033d086 --- /dev/null +++ b/powershell/ql/test/library-tests/dataflow/typetracking/test.expected @@ -0,0 +1,2 @@ +testFailures +failures diff --git a/powershell/ql/test/library-tests/dataflow/typetracking/test.ps1 b/powershell/ql/test/library-tests/dataflow/typetracking/test.ps1 new file mode 100644 index 00000000000..e5c1a1bfe23 --- /dev/null +++ b/powershell/ql/test/library-tests/dataflow/typetracking/test.ps1 @@ -0,0 +1,19 @@ +class MyClass { + [string] $field + MyClass($val) { + $this.field = $val + } +} + +$myClass = [MyClass]::new("hello") + +Sink $myClass # $ MISSING: type=MyClass + + +$withNamedArg = New-Object -TypeName PSObject + +Sink $withNamedArg # $ MISSING: type=PSObject + +$withPositionalArg = New-Object PSObject + +Sink $withPositionalArg # $ MISSING: type=PSObject diff --git a/powershell/ql/test/library-tests/dataflow/typetracking/test.ql b/powershell/ql/test/library-tests/dataflow/typetracking/test.ql new file mode 100644 index 00000000000..338fb02cad6 --- /dev/null +++ b/powershell/ql/test/library-tests/dataflow/typetracking/test.ql @@ -0,0 +1,23 @@ +import powershell +import semmle.code.powershell.dataflow.internal.DataFlowDispatch +import semmle.code.powershell.dataflow.internal.DataFlowPublic +import semmle.code.powershell.dataflow.internal.DataFlowPrivate +import TestUtilities.InlineExpectationsTest + +module TypeTrackingTest implements TestSig { + string getARelevantTag() { result = "type" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + exists(Node n, DataFlowCall c, Type t | + location = n.getLocation() and + element = n.toString() and + tag = "type" and + value = t.getName() and + n = trackInstance(t, _) and + isArgumentNode(n, c, _) and + c.asCall().hasName("Sink") + ) + } +} + +import MakeTest