diff --git a/powershell/ql/lib/semmle/code/powershell/Command.qll b/powershell/ql/lib/semmle/code/powershell/Command.qll index 73c2df41a7a..908a812c3ac 100644 --- a/powershell/ql/lib/semmle/code/powershell/Command.qll +++ b/powershell/ql/lib/semmle/code/powershell/Command.qll @@ -40,3 +40,20 @@ class Cmd extends @command, CmdBase { Redirection getARedirection() { result = this.getRedirection(_) } } + +/** + * An argument to a command. + * + * The argument may be named or positional. + */ +class Argument extends Expr { + Cmd cmd; + + Argument() { cmd.getArgument(_) = this or cmd.getNamedArgument(_) = this } + + Cmd getCmd() { result = cmd } + + int getIndex() { cmd.getArgument(result) = this } + + string getName() { cmd.getNamedArgument(result) = this } +} diff --git a/powershell/ql/lib/semmle/code/powershell/InvokeMemberExpression.qll b/powershell/ql/lib/semmle/code/powershell/InvokeMemberExpression.qll index 1ff04f78e3a..c337a4f08fa 100644 --- a/powershell/ql/lib/semmle/code/powershell/InvokeMemberExpression.qll +++ b/powershell/ql/lib/semmle/code/powershell/InvokeMemberExpression.qll @@ -3,7 +3,7 @@ import powershell class InvokeMemberExpr extends @invoke_member_expression, MemberExprBase { override SourceLocation getLocation() { invoke_member_expression_location(this, result) } - Expr getBase() { invoke_member_expression(this, result, _) } + Expr getQualifier() { invoke_member_expression(this, result, _) } CmdElement getMember() { invoke_member_expression(this, _, result) } diff --git a/powershell/ql/lib/semmle/code/powershell/controlflow/CfgNodes.qll b/powershell/ql/lib/semmle/code/powershell/controlflow/CfgNodes.qll index a4f83847963..a94c43ff057 100644 --- a/powershell/ql/lib/semmle/code/powershell/controlflow/CfgNodes.qll +++ b/powershell/ql/lib/semmle/code/powershell/controlflow/CfgNodes.qll @@ -166,6 +166,37 @@ module ExprNodes { predicate isImplicitWrite() { e.isImplicit() } } + + /** A control-flow node that wraps an argument expression. */ + class ArgumentCfgNode extends ExprCfgNode { + override string getAPrimaryQlClass() { result = "ArgumentCfgNode" } + + override Argument e; + + final override Argument getExpr() { result = super.getExpr() } + } + + private class InvokeMemberChildMapping extends ExprChildMapping, InvokeMemberExpr { + override predicate relevantChild(Ast n) { n = this.getQualifier() or n = this.getAnArgument() } + } + + /** A control-flow node that wraps an `InvokeMemberExpr` expression. */ + class InvokeMemberCfgNode extends ExprCfgNode { + override string getAPrimaryQlClass() { result = "InvokeMemberCfgNode" } + + override InvokeMemberChildMapping e; + + final override InvokeMemberExpr getExpr() { result = super.getExpr() } + + final ExprCfgNode getQualifier() { e.hasCfgChild(e.getQualifier(), this, result) } + } + + /** A control-flow node that wraps a qualifier expression. */ + class QualifierCfgNode extends ExprCfgNode { + QualifierCfgNode() { this = any(InvokeMemberCfgNode invoke).getQualifier() } + + InvokeMemberCfgNode getInvokeMember() { this = result.getQualifier() } + } } module StmtNodes { diff --git a/powershell/ql/lib/semmle/code/powershell/controlflow/internal/Scope.qll b/powershell/ql/lib/semmle/code/powershell/controlflow/internal/Scope.qll index 1a23cacec35..84b794dbee8 100644 --- a/powershell/ql/lib/semmle/code/powershell/controlflow/internal/Scope.qll +++ b/powershell/ql/lib/semmle/code/powershell/controlflow/internal/Scope.qll @@ -17,4 +17,23 @@ Scope scopeOf(Ast n) { class Scope extends Ast, @script_block { /** Gets the outer scope, if any. */ Scope getOuterScope() { result = scopeOf(this) } + + /** + * Gets the `i`'th paramter in this scope. + * + * This may be both function paramters and parameter block parameters. + */ + Parameter getParameter(int i) { + exists(Function func | + func.getBody() = this and + result = func.getParameter(i) + ) + } + + /** + * Gets a paramter in this scope. + * + * This may be both function paramters and parameter block parameters. + */ + Parameter getAParameter() { result = this.getParameter(_) } } diff --git a/powershell/ql/test/library-tests/ast/Expressions/expressions.ql b/powershell/ql/test/library-tests/ast/Expressions/expressions.ql index 22d68304d1f..6f3064f5c40 100644 --- a/powershell/ql/test/library-tests/ast/Expressions/expressions.ql +++ b/powershell/ql/test/library-tests/ast/Expressions/expressions.ql @@ -10,7 +10,7 @@ query predicate cmdExpr(CmdExpr cmd, Expr e) { } query predicate invokeMemoryExpression(InvokeMemberExpr invoke, Expr e, int i, Expr arg) { - e = invoke.getBase() and + e = invoke.getQualifier() and arg = invoke.getArgument(i) } diff --git a/powershell/ql/test/library-tests/dataflow/local/test.ps1 b/powershell/ql/test/library-tests/dataflow/local/test.ps1 index 6530b256fdc..86bbd7cadaf 100644 --- a/powershell/ql/test/library-tests/dataflow/local/test.ps1 +++ b/powershell/ql/test/library-tests/dataflow/local/test.ps1 @@ -1,8 +1,8 @@ -$a1 = Source() -Sink($a1) +$a1 = Source +Sink $a1 -$b = GetBool() +$b = GetBool if($b) { - $a2 = Source() + $a2 = Source } -Sink($a2) \ No newline at end of file +Sink $a2 \ No newline at end of file