PS: Delete the old AST.

This commit is contained in:
Mathias Vorreiter Pedersen
2025-03-26 18:00:10 +00:00
parent 44e4e3eb54
commit d79eb013c8
89 changed files with 0 additions and 4288 deletions

View File

@@ -1,26 +0,0 @@
import powershell
class ArrayExpr extends @array_expression, Expr {
override SourceLocation getLocation() { array_expression_location(this, result) }
StmtBlock getStmtBlock() { array_expression(this, result) }
/**
* Gets the i'th element of this `ArrayExpr`, if this can be determined statically.
*
* See `getStmtBlock` when the array elements are not known statically.
*/
Expr getElement(int i) {
result =
unique( | | this.getStmtBlock().getAStmt()).(CmdExpr).getExpr().(ArrayLiteral).getElement(i)
}
/**
* Gets an element of this `ArrayExpr`, if this can be determined statically.
*
* See `getStmtBlock` when the array elements are not known statically.
*/
Expr getAnElement() { result = this.getElement(_) }
override string toString() { result = "@(...)" }
}

View File

@@ -1,11 +0,0 @@
import powershell
class ArrayLiteral extends @array_literal, Expr {
override SourceLocation getLocation() { array_literal_location(this, result) }
Expr getElement(int index) { array_literal_element(this, index, result) }
Expr getAnElement() { array_literal_element(this, _, result) }
override string toString() { result = "...,..." }
}

View File

@@ -1,13 +0,0 @@
import powershell
class AssignStmt extends @assignment_statement, PipelineBase {
override SourceLocation getLocation() { assignment_statement_location(this, result) }
int getKind() { assignment_statement(this, result, _, _) }
Expr getLeftHandSide() { assignment_statement(this, _, result, _) }
Stmt getRightHandSide() { assignment_statement(this, _, _, result) }
override string toString() { result = "...=..." }
}

View File

@@ -1,14 +0,0 @@
import powershell
private import semmle.code.powershell.controlflow.internal.Scope
class Ast extends @ast {
string toString() { none() }
Ast getParent() { parent(this, result) }
Location getLocation() { none() }
Scope getEnclosingScope() { result = scopeOf(this) }
final Function getEnclosingFunction() { this.getEnclosingScope() = result.getBody() }
}

View File

@@ -1,25 +0,0 @@
import powershell
class Attribute extends @attribute, AttributeBase {
override string toString() { result = this.getName() }
override SourceLocation getLocation() { attribute_location(this, result) }
string getName() { attribute(this, result, _, _) }
int getNumNamedArguments() { attribute(this, _, result, _) }
int getNumPositionalArguments() { attribute(this, _, _, result) }
NamedAttributeArgument getNamedArgument(int i) { attribute_named_argument(this, i, result) }
NamedAttributeArgument getANamedArgument() { result = this.getNamedArgument(_) }
int getNumberOfArguments() { result = count(this.getAPositionalArgument()) }
Expr getPositionalArgument(int i) { attribute_positional_argument(this, i, result) }
Expr getAPositionalArgument() { result = this.getPositionalArgument(_) }
int getNumberOfPositionalArguments() { result = count(this.getAPositionalArgument()) }
}

View File

@@ -1,3 +0,0 @@
import powershell
class AttributeBase extends @attribute_base, Ast { }

View File

@@ -1,13 +0,0 @@
import powershell
/** The base class for constant expressions. */
class BaseConstExpr extends @base_constant_expression, Expr {
/** Gets the type of this constant expression. */
string getType() { none() }
/** Gets a string literal of this constant expression. */
StringLiteral getValue() { none() }
/** Gets a string literal representing this constant expression. */
final override string toString() { result = this.getValue().toString() }
}

View File

@@ -1,319 +0,0 @@
import powershell
class BinaryExpr extends @binary_expression, Expr {
override SourceLocation getLocation() { binary_expression_location(this, result) }
int getKind() { binary_expression(this, result, _, _) }
/** Gets an operand of this binary expression. */
Expr getAnOperand() {
result = this.getLeft()
or
result = this.getRight()
}
/** Holds if this binary expression has the operands `e1` and `e2`. */
predicate hasOperands(Expr e1, Expr e2) {
e1 = this.getLeft() and
e2 = this.getRight()
or
e1 = this.getRight() and
e2 = this.getLeft()
}
Expr getLeft() { binary_expression(this, _, result, _) }
Expr getRight() { binary_expression(this, _, _, result) }
}
abstract private class AbstractArithmeticExpr extends BinaryExpr { }
final class ArithmeticExpr = AbstractArithmeticExpr;
class AddExpr extends AbstractArithmeticExpr {
AddExpr() { this.getKind() = 40 }
final override string toString() { result = "...+..." }
}
class SubExpr extends AbstractArithmeticExpr {
SubExpr() { this.getKind() = 41 }
final override string toString() { result = "...-..." }
}
class MulExpr extends AbstractArithmeticExpr {
MulExpr() { this.getKind() = 37 }
final override string toString() { result = "...*..." }
}
class DivExpr extends AbstractArithmeticExpr {
DivExpr() { this.getKind() = 38 }
final override string toString() { result = ".../..." }
}
class RemExpr extends AbstractArithmeticExpr {
RemExpr() { this.getKind() = 39 }
final override string toString() { result = "...%..." }
}
abstract private class AbstractBitwiseExpr extends BinaryExpr { }
final class BitwiseExpr = AbstractBitwiseExpr;
class BitwiseAndExpr extends AbstractBitwiseExpr {
BitwiseAndExpr() { this.getKind() = 56 }
final override string toString() { result = "...&..." }
}
class BitwiseOrExpr extends AbstractBitwiseExpr {
BitwiseOrExpr() { this.getKind() = 57 }
final override string toString() { result = "...|..." }
}
class BitwiseXorExpr extends AbstractBitwiseExpr {
BitwiseXorExpr() { this.getKind() = 58 }
final override string toString() { result = "...^..." }
}
class ShiftLeftExpr extends AbstractBitwiseExpr {
ShiftLeftExpr() { this.getKind() = 97 }
final override string toString() { result = "...<<..." }
}
class ShiftRightExpr extends AbstractBitwiseExpr {
ShiftRightExpr() { this.getKind() = 98 }
final override string toString() { result = "...>>..." }
}
abstract private class AbstractComparisonExpr extends BinaryExpr { }
final class ComparisonExpr = AbstractComparisonExpr;
abstract private class AbstractCaseInsensitiveComparisonExpr extends AbstractComparisonExpr { }
final class CaseInsensitiveComparisonExpr = AbstractCaseInsensitiveComparisonExpr;
abstract private class AbstractCaseSensitiveComparisonExpr extends AbstractComparisonExpr { }
final class CaseSensitiveComparisonExpr = AbstractCaseSensitiveComparisonExpr;
class EqExpr extends AbstractCaseInsensitiveComparisonExpr {
EqExpr() { this.getKind() = 60 }
final override string toString() { result = "... -eq ..." }
}
class NeExpr extends AbstractCaseInsensitiveComparisonExpr {
NeExpr() { this.getKind() = 61 }
final override string toString() { result = "... -ne ..." }
}
class CEqExpr extends AbstractCaseSensitiveComparisonExpr {
CEqExpr() { this.getKind() = 76 }
final override string toString() { result = "... -ceq ..." }
}
class CNeExpr extends AbstractCaseSensitiveComparisonExpr {
CNeExpr() { this.getKind() = 77 }
final override string toString() { result = "... -cne ..." }
}
abstract private class AbstractRelationalExpr extends AbstractComparisonExpr { }
final class RelationalExpr = AbstractRelationalExpr;
abstract private class AbstractCaseInsensitiveRelationalExpr extends AbstractRelationalExpr { }
final class CaseInsensitiveRelationalExpr = AbstractCaseInsensitiveRelationalExpr;
abstract private class AbstractCaseSensitiveRelationalExpr extends AbstractRelationalExpr { }
final class CaseSensitiveRelationalExpr = AbstractCaseSensitiveRelationalExpr;
class GeExpr extends AbstractCaseInsensitiveRelationalExpr {
GeExpr() { this.getKind() = 62 }
final override string toString() { result = "... -ge ..." }
}
class GtExpr extends AbstractCaseInsensitiveRelationalExpr {
GtExpr() { this.getKind() = 63 }
final override string toString() { result = "... -gt ..." }
}
class LtExpr extends AbstractCaseInsensitiveRelationalExpr {
LtExpr() { this.getKind() = 64 }
final override string toString() { result = "... -lt ..." }
}
class LeExpr extends AbstractCaseInsensitiveRelationalExpr {
LeExpr() { this.getKind() = 65 }
final override string toString() { result = "... -le ..." }
}
class CGeExpr extends AbstractCaseSensitiveRelationalExpr {
CGeExpr() { this.getKind() = 78 }
final override string toString() { result = "... -cge ..." }
}
class CGtExpr extends AbstractCaseSensitiveRelationalExpr {
CGtExpr() { this.getKind() = 79 }
final override string toString() { result = "... -cgt ..." }
}
class CLtExpr extends AbstractCaseSensitiveRelationalExpr {
CLtExpr() { this.getKind() = 80 }
final override string toString() { result = "... -clt ..." }
}
class CLeExpr extends AbstractCaseSensitiveRelationalExpr {
CLeExpr() { this.getKind() = 81 }
final override string toString() { result = "... -cle ..." }
}
class LikeExpr extends AbstractCaseInsensitiveComparisonExpr {
LikeExpr() { this.getKind() = 66 }
final override string toString() { result = "... -like ..." }
}
class NotLikeExpr extends AbstractCaseInsensitiveComparisonExpr {
NotLikeExpr() { this.getKind() = 67 }
final override string toString() { result = "... -notlike ..." }
}
class MatchExpr extends AbstractCaseInsensitiveComparisonExpr {
MatchExpr() { this.getKind() = 68 }
final override string toString() { result = "... -match ..." }
}
class NotMatchExpr extends AbstractCaseInsensitiveComparisonExpr {
NotMatchExpr() { this.getKind() = 69 }
final override string toString() { result = "... -notmatch ..." }
}
class ReplaceExpr extends AbstractCaseInsensitiveComparisonExpr {
ReplaceExpr() { this.getKind() = 70 }
final override string toString() { result = "... -replace ..." }
}
abstract class AbstractTypeExpr extends BinaryExpr { }
final class TypeExpr = AbstractTypeExpr;
abstract class AbstractTypeComparisonExpr extends AbstractTypeExpr { }
final class TypeComparisonExpr = AbstractTypeComparisonExpr;
class IsExpr extends AbstractTypeComparisonExpr {
IsExpr() { this.getKind() = 92 }
final override string toString() { result = "... -is ..." }
}
class IsNotExpr extends AbstractTypeComparisonExpr {
IsNotExpr() { this.getKind() = 93 }
final override string toString() { result = "... -isnot ..." }
}
class AsExpr extends AbstractTypeExpr {
AsExpr() { this.getKind() = 94 }
final override string toString() { result = "... -as ..." }
}
abstract private class AbstractContainmentExpr extends BinaryExpr { }
final class ContainmentExpr = AbstractContainmentExpr;
abstract private class AbstractCaseInsensitiveContainmentExpr extends AbstractContainmentExpr { }
final class CaseInsensitiveContainmentExpr = AbstractCaseInsensitiveContainmentExpr;
class ContainsExpr extends AbstractCaseInsensitiveContainmentExpr {
ContainsExpr() { this.getKind() = 71 }
final override string toString() { result = "... -contains ..." }
}
class NotContainsExpr extends AbstractCaseInsensitiveContainmentExpr {
NotContainsExpr() { this.getKind() = 72 }
final override string toString() { result = "... -notcontains ..." }
}
class InExpr extends AbstractCaseInsensitiveContainmentExpr {
InExpr() { this.getKind() = 73 }
final override string toString() { result = "... -in ..." }
}
class NotInExpr extends AbstractCaseInsensitiveContainmentExpr {
NotInExpr() { this.getKind() = 74 }
final override string toString() { result = "... -notin ..." }
}
abstract private class AbstractLogicalBinaryExpr extends BinaryExpr { }
final class LogicalBinaryExpr = AbstractLogicalBinaryExpr;
class LogicalAndExpr extends AbstractLogicalBinaryExpr {
LogicalAndExpr() { this.getKind() = 53 }
final override string toString() { result = "... -and ..." }
}
class LogicalOrExpr extends AbstractLogicalBinaryExpr {
LogicalOrExpr() { this.getKind() = 54 }
final override string toString() { result = "... -or ..." }
}
class LogicalXorExpr extends AbstractLogicalBinaryExpr {
LogicalXorExpr() { this.getKind() = 55 }
final override string toString() { result = "... -xor ..." }
}
class JoinExpr extends BinaryExpr {
JoinExpr() { this.getKind() = 59 }
final override string toString() { result = "... -join ..." }
}
class SequenceExpr extends BinaryExpr {
SequenceExpr() { this.getKind() = 33 }
final override string toString() { result = "[..]" }
}
class FormatExpr extends BinaryExpr {
FormatExpr() { this.getKind() = 50 }
final override string toString() { result = "... -f ..." }
}

View File

@@ -1,7 +0,0 @@
import powershell
class BreakStmt extends GotoStmt, @break_statement {
override SourceLocation getLocation() { break_statement_location(this, result) }
override string toString() { result = "break" }
}

View File

@@ -1,79 +0,0 @@
import powershell
private import semmle.code.powershell.dataflow.internal.DataFlowImplCommon
private import semmle.code.powershell.dataflow.internal.DataFlowDispatch
private import semmle.code.powershell.controlflow.CfgNodes
abstract private class AbstractCall extends Ast {
abstract Expr getCommand();
abstract string getName();
/** Gets the i'th argument to this call. */
abstract Expr getArgument(int i);
/** Gets the i'th positional argument to this call. */
abstract Expr getPositionalArgument(int i);
/** Holds if an argument with name `name` is provided to this call. */
final predicate hasNamedArgument(string name) { exists(this.getNamedArgument(name)) }
/** Gets the argument to this call with the name `name`. */
abstract Expr getNamedArgument(string name);
/** Gets any argument to this call. */
final Expr getAnArgument() { result = this.getArgument(_) }
/** Gets the qualifier of this call, if any. */
Expr getQualifier() { none() }
/** Gets a possible runtime target of this call. */
abstract Function getATarget();
}
/** A call to a command. For example, `Write-Host "Hello, world!"`. */
class CmdCall extends AbstractCall instanceof Cmd {
final override Expr getCommand() { result = Cmd.super.getCommand() }
final override Expr getPositionalArgument(int i) { result = Cmd.super.getPositionalArgument(i) }
final override string getName() { result = Cmd.super.getCommandName() }
final override Expr getArgument(int i) { result = Cmd.super.getArgument(i) }
final override Expr getNamedArgument(string name) { result = Cmd.super.getNamedArgument(name) }
final override Function getATarget() {
exists(DataFlowCall call | call.asCall().(StmtNodes::CmdCfgNode).getStmt() = this |
result.getBody() = viableCallableLambda(call, _).asCfgScope()
or
result.getBody() = getTarget(call)
)
}
}
/** A call to a method on an object. For example, `$obj.ToString()`. */
class MethodCall extends AbstractCall instanceof InvokeMemberExpr {
final override Expr getCommand() { result = super.getMember() }
final override Expr getPositionalArgument(int i) {
result = InvokeMemberExpr.super.getArgument(i)
}
final override Expr getArgument(int i) { result = this.getPositionalArgument(i) }
final override Expr getQualifier() { result = InvokeMemberExpr.super.getQualifier() }
final override Expr getNamedArgument(string name) { none() }
final override Function getATarget() {
exists(DataFlowCall call | call.asCall().(ExprNodes::InvokeMemberCfgNode).getExpr() = this |
result.getBody() = viableCallableLambda(call, _).asCfgScope()
or
result.getBody() = getTarget(call)
)
}
final override string getName() { result = InvokeMemberExpr.super.getName() }
}
final class Call = AbstractCall;

View File

@@ -1,39 +0,0 @@
import powershell
class CatchClause extends @catch_clause, Ast {
override SourceLocation getLocation() { catch_clause_location(this, result) }
override string toString() { result = "catch {...}" }
StmtBlock getBody() { catch_clause(this, result, _) }
TypeConstraint getCatchType(int i) { catch_clause_catch_type(this, i, result) }
int getNumberOfCatchTypes() { result = count(this.getACatchType()) }
TypeConstraint getACatchType() { result = this.getCatchType(_) }
predicate isCatchAll() { not exists(this.getACatchType()) }
TryStmt getTryStmt() { result.getACatchClause() = this }
predicate isLast() {
exists(TryStmt ts, int last |
ts = this.getTryStmt() and
last = max(int i | exists(ts.getCatchClause(i))) and
this = ts.getCatchClause(last)
)
}
}
class GeneralCatchClause extends CatchClause {
GeneralCatchClause() { this.isCatchAll() }
override string toString() { result = "catch {...}" }
}
class SpecificCatchClause extends CatchClause {
SpecificCatchClause() { not this.isCatchAll() }
override string toString() { result = "catch[...] {...}" }
}

View File

@@ -1,3 +0,0 @@
import powershell
class Chainable extends @chainable, PipelineBase { }

View File

@@ -1,114 +0,0 @@
import powershell
private predicate parseCommandName(Cmd cmd, string namespace, string name) {
exists(string qualified | command(cmd, qualified, _, _, _) |
namespace = qualified.regexpCapture("([^\\\\]+)\\\\([^\\\\]+)", 1) and
name = qualified.regexpCapture("([^\\\\]+)\\\\([^\\\\]+)", 2)
or
// Not a qualified name
not exists(qualified.indexOf("\\")) and
namespace = "" and
name = qualified
)
}
/** A call to a command. */
class Cmd extends @command, CmdBase {
override string toString() {
exists(string name | name = this.getQualifiedCommandName() |
if name = "" then result = "call" else result = "call to " + name
)
or
not exists(this.getQualifiedCommandName()) and
result = "call"
}
override SourceLocation getLocation() { command_location(this, result) }
/** Gets the name of the command without any qualifiers. */
string getCommandName() { parseCommandName(this, _, result) }
/** Holds if the command is qualified. */
predicate isQualified() { parseCommandName(this, any(string s | s != ""), _) }
/** Gets the namespace qualifier of this command, if any. */
string getNamespaceQualifier() {
result != "" and
parseCommandName(this, result, _)
or
// Implicit import because it's in a module manifest
parseCommandName(this, "", _) and
exists(ModuleManifest manifest |
manifest.getACmdLetToExport() = this.getCommandName() and
result = manifest.getModuleName()
)
}
/** Gets the (possibly qualified) name of this command. */
string getQualifiedCommandName() { command(this, result, _, _, _) }
int getKind() { command(this, _, result, _, _) }
int getNumElements() { command(this, _, _, result, _) }
int getNumRedirection() { command(this, _, _, _, result) }
CmdElement getElement(int i) { command_command_element(this, i, result) }
/** Gets the expression that determines the command to invoke. */
Expr getCommand() { result = this.getElement(0) }
/** Gets the name of this command, if this is statically known. */
StringConstExpr getCmdName() { result = this.getElement(0) }
/** Gets any argument to this command. */
Expr getAnArgument() { result = this.getArgument(_) }
/**
* Gets the `i`th argument to this command.
*
* The argument may be named or positional.
*/
Expr getArgument(int i) {
result =
rank[i + 1](CmdElement e, int j |
e = this.getElement(j) and
not e instanceof CmdParameter and
j > 0 // 0'th element is the command name itself
|
e order by j
)
}
/** Gets the `i`th positional argument to this command. */
Expr getPositionalArgument(int i) {
result =
rank[i + 1](Argument e, int j |
e = this.getArgument(j) and
e instanceof PositionalArgument
|
e order by j
)
}
/** Holds if this call has an argument named `name`. */
predicate hasNamedArgument(string name) { exists(this.getNamedArgument(name)) }
/** Gets the named argument with the given name. */
Expr getNamedArgument(string name) {
exists(int i, CmdParameter p |
this.getElement(i) = p and
p.getName() = name and
result = p.getArgument()
)
}
Redirection getRedirection(int i) { command_redirection(this, i, result) }
Redirection getARedirection() { result = this.getRedirection(_) }
}
/** A call to operator `&`. */
class CallOperator extends Cmd {
CallOperator() { this.getKind() = 28 }
}

View File

@@ -1,3 +0,0 @@
import powershell
class CmdBase extends @command_base, Chainable { }

View File

@@ -1,3 +0,0 @@
import powershell
class CmdElement extends @command_element, Ast { }

View File

@@ -1,15 +0,0 @@
import powershell
class CmdExpr extends @command_expression, CmdBase {
override SourceLocation getLocation() { command_expression_location(this, result) }
Expr getExpr() { command_expression(this, result, _) }
int getNumRedirections() { command_expression(this, _, result) }
Redirection getRedirection(int i) { command_expression_redirection(this, i, result) }
Redirection getARedirection() { result = this.getRedirection(_) }
override string toString() { result = this.getExpr().toString() }
}

View File

@@ -1,23 +0,0 @@
import powershell
class CmdParameter extends @command_parameter, CmdElement {
override SourceLocation getLocation() { command_parameter_location(this, result) }
string getName() { command_parameter(this, result) }
Expr getArgument() {
// When an argumnt is of the form -Name:$var
command_parameter_argument(this, result)
or
// When an argument is of the form -Name $var
exists(int i, Cmd cmd |
cmd = this.getCmd() and
cmd.getElement(i) = this and
result = cmd.getElement(i + 1)
)
}
Cmd getCmd() { result.getElement(_) = this }
override string toString() { command_parameter(this, result) }
}

View File

@@ -1,17 +0,0 @@
import powershell
class Comment extends @comment_entity {
Location getLocation() { comment_entity_location(this, result) }
StringLiteral getCommentContents() { comment_entity(this, result) }
string toString() { result = this.getCommentContents().toString() }
}
class SingleLineComment extends Comment {
SingleLineComment() { this.getCommentContents().getNumContinuations() = 1 }
}
class MultiLineComment extends Comment {
MultiLineComment() { this.getCommentContents().getNumContinuations() > 1 }
}

View File

@@ -1,15 +0,0 @@
import powershell
class Configuration extends @configuration_definition, Stmt {
override SourceLocation getLocation() { configuration_definition_location(this, result) }
override string toString() { result = "Configuration" }
Expr getName() { configuration_definition(this, _, _, result) }
ScriptBlockExpr getBody() { configuration_definition(this, result, _, _) }
predicate isMeta() { configuration_definition(this, _, 1, _) }
predicate isResource() { configuration_definition(this, _, 0, _) }
}

View File

@@ -1,127 +0,0 @@
import powershell
class ConstExpr extends @constant_expression, BaseConstExpr {
override SourceLocation getLocation() { constant_expression_location(this, result) }
override string getType() { constant_expression(this, result) }
override StringLiteral getValue() { constant_expression_value(this, result) }
}
private newtype TConstantValue =
TConstInteger(int value) {
exists(ConstExpr ce | ce.getType() = "Int32" and ce.getValue().getValue().toInt() = value)
or
value = [0 .. 10] // needed for `trackKnownValue` in `DataFlowPrivate`
} or
TConstDouble(float double) {
exists(ConstExpr ce | ce.getType() = "Double" and ce.getValue().getValue().toFloat() = double)
} or
TConstString(string value) { exists(StringLiteral sl | sl.getValue() = value) } or
TConstBoolean(boolean value) {
exists(VarAccess va |
value = true and
va.getUserPath() = "true"
or
value = false and
va.getUserPath() = "false"
)
} or
TNull()
/** A constant value. */
class ConstantValue extends TConstantValue {
/** Gets a string representation of this value. */
final string toString() { result = this.getValue() }
/** Gets the value of this consant. */
string getValue() { none() }
/** Gets the integer value of this constant, if any. */
int asInt() { none() }
/** Gets the floating point value of this constant, if any. */
float asDouble() { none() }
/** Gets the string value of this constant, if any. */
string asString() { none() }
/** Gets the boolean value of this constant, if any. */
boolean asBoolean() { none() }
/** Holds if this constant represents the null value. */
predicate isNull() { none() }
/** Gets a (unique) serialized version of this value. */
string serialize() { none() }
/** Gets an exprssion that has this value. */
Expr getAnExpr() { none() }
}
/** A constant integer value */
class ConstInteger extends ConstantValue, TConstInteger {
final override int asInt() { this = TConstInteger(result) }
final override string getValue() { result = this.asInt().toString() }
final override string serialize() { result = this.getValue() }
final override ConstExpr getAnExpr() { result.getValue().getValue() = this.getValue() }
}
/** A constant floating point value. */
class ConstDouble extends ConstantValue, TConstDouble {
final override float asDouble() { this = TConstDouble(result) }
final override string getValue() { result = this.asDouble().toString() }
final override string serialize() {
exists(string res | res = this.asDouble().toString() |
if exists(res.indexOf(".")) then result = res else result = res + ".0"
)
}
final override ConstExpr getAnExpr() { result.getValue().getValue() = this.getValue() }
}
/** A constant string value. */
class ConstString extends ConstantValue, TConstString {
final override string asString() { this = TConstString(result) }
final override string getValue() { result = this.asString() }
final override string serialize() {
result = "\"" + this.asString().replaceAll("\"", "\\\"") + "\""
}
final override BaseConstExpr getAnExpr() { result.getValue().getValue() = this.getValue() }
}
/** A constant boolean value. */
class ConstBoolean extends ConstantValue, TConstBoolean {
final override boolean asBoolean() { this = TConstBoolean(result) }
final override string getValue() { result = this.asBoolean().toString() }
final override string serialize() { result = this.getValue() }
final override VarAccess getAnExpr() {
this.asBoolean() = true and
result.getUserPath() = "true"
or
this.asBoolean() = false and
result.getUserPath() = "false"
}
}
/** The constant null value. */
class NullConst extends ConstantValue, TNull {
final override predicate isNull() { any() }
final override string getValue() { result = "null" }
final override string serialize() { result = this.getValue() }
final override VarAccess getAnExpr() { result.getUserPath() = "null" }
}

View File

@@ -1,7 +0,0 @@
import powershell
class ContinueStmt extends GotoStmt, @continue_statement {
override SourceLocation getLocation() { continue_statement_location(this, result) }
override string toString() { result = "continue" }
}

View File

@@ -1,13 +0,0 @@
import powershell
class ConvertExpr extends @convert_expression, Expr {
override string toString() { result = "[...]..." }
override SourceLocation getLocation() { convert_expression_location(this, result) }
Expr getBase() { convert_expression(this, _, result, _, _) }
TypeConstraint getType() { convert_expression(this, _, _, result, _) }
AttributeBase getAttribute() { convert_expression(this, result, _, _, _) }
}

View File

@@ -1,15 +0,0 @@
import powershell
class DataStmt extends @data_statement, Stmt {
override SourceLocation getLocation() { data_statement_location(this, result) }
override string toString() { result = "data {...}" }
string getVariableName() { data_statement_variable(this, result) }
Expr getCmdAllowed(int i) { data_statement_commands_allowed(this, i, result) }
Expr getACmdAllowed() { result = this.getCmdAllowed(_) }
StmtBlock getBody() { data_statement(this, result) }
}

View File

@@ -1,11 +0,0 @@
import powershell
class DoUntilStmt extends @do_until_statement, LoopStmt {
override SourceLocation getLocation() { do_until_statement_location(this, result) }
override string toString() { result = "DoUntil" }
PipelineBase getCondition() { do_until_statement_condition(this, result) }
final override StmtBlock getBody() { do_until_statement(this, result) }
}

View File

@@ -1,11 +0,0 @@
import powershell
class DoWhileStmt extends @do_while_statement, LoopStmt {
override SourceLocation getLocation() { do_while_statement_location(this, result) }
override string toString() { result = "DoWhile" }
PipelineBase getCondition() { do_while_statement_condition(this, result) }
final override StmtBlock getBody() { do_while_statement(this, result) }
}

View File

@@ -1,11 +0,0 @@
import powershell
class DynamicStmt extends @dynamic_keyword_statement, Stmt {
override SourceLocation getLocation() { dynamic_keyword_statement_location(this, result) }
override string toString() { result = "&..." }
CmdElement getCmd(int i) { dynamic_keyword_statement_command_elements(this, i, result) }
CmdElement getACmd() { result = this.getCmd(_) }
}

View File

@@ -1,7 +0,0 @@
import powershell
class ErrorExpr extends @error_expression, Expr {
final override SourceLocation getLocation() { error_expression_location(this, result) }
final override string toString() { result = "error" }
}

View File

@@ -1,7 +0,0 @@
import powershell
class ErrorStmt extends @error_statement, PipelineBase {
final override SourceLocation getLocation() { error_statement_location(this, result) }
final override string toString() { result = "error" }
}

View File

@@ -1,12 +0,0 @@
import powershell
class ExitStmt extends @exit_statement, Stmt {
override SourceLocation getLocation() { exit_statement_location(this, result) }
override string toString() { if this.hasPipeline() then result = "exit ..." else result = "exit" }
/** ..., if any. */
PipelineBase getPipeline() { exit_statement_pipeline(this, result) }
predicate hasPipeline() { exists(this.getPipeline()) }
}

View File

@@ -1,15 +0,0 @@
import powershell
class ExpandableStringExpr extends @expandable_string_expression, Expr {
override SourceLocation getLocation() { expandable_string_expression_location(this, result) }
override string toString() { result = this.getUnexpandedValue().toString() }
StringLiteral getUnexpandedValue() { expandable_string_expression(this, result, _, _) }
int getNumExprs() { result = count(this.getAnExpr()) }
Expr getExpr(int i) { expandable_string_expression_nested_expression(this, i, result) }
Expr getAnExpr() { result = this.getExpr(_) }
}

View File

@@ -1,11 +0,0 @@
import powershell
/**
* An expression.
*
* This is the topmost class in the hierachy of all expression in PowerShell.
*/
class Expr extends @expression, CmdElement {
/** Gets the constant value of this expression, if this is known. */
final ConstantValue getValue() { result.getAnExpr() = this }
}

View File

@@ -1,224 +0,0 @@
/**
* Provides classes representing filesystem files and folders.
* Based on csharp/ql/lib/semmle/code/csharp/File.qll
*/
/** A file or folder. */
class Container extends @container {
/**
* Gets the absolute, canonical path of this container, using forward slashes
* as path separator.
*
* The path starts with a _root prefix_ followed by zero or more _path
* segments_ separated by forward slashes.
*
* The root prefix is of one of the following forms:
*
* 1. A single forward slash `/` (Unix-style)
* 2. An upper-case drive letter followed by a colon and a forward slash,
* such as `C:/` (Windows-style)
* 3. Two forward slashes, a computer name, and then another forward slash,
* such as `//FileServer/` (UNC-style)
*
* Path segments are never empty (that is, absolute paths never contain two
* contiguous slashes, except as part of a UNC-style root prefix). Also, path
* segments never contain forward slashes, and no path segment is of the
* form `.` (one dot) or `..` (two dots).
*
* Note that an absolute path never ends with a forward slash, except if it is
* a bare root prefix, that is, the path has no path segments. A container
* whose absolute path has no segments is always a `Folder`, not a `File`.
*/
string getAbsolutePath() { none() }
/**
* Gets a URL representing the location of this container.
*
* For more information see [Providing URLs](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/#providing-urls).
*/
string getURL() { none() }
/**
* Gets the relative path of this file or folder from the root folder of the
* analyzed source location. The relative path of the root folder itself is
* the empty string.
*
* This has no result if the container is outside the source root, that is,
* if the root folder is not a reflexive, transitive parent of this container.
*/
string getRelativePath() {
exists(string absPath, string pref |
absPath = this.getAbsolutePath() and sourceLocationPrefix(pref)
|
absPath = pref and result = ""
or
absPath = pref.regexpReplaceAll("/$", "") + "/" + result and
not result.matches("/%")
)
}
/**
* Gets the base name of this container including extension, that is, the last
* segment of its absolute path, or the empty string if it has no segments.
*
* Here are some examples of absolute paths and the corresponding base names
* (surrounded with quotes to avoid ambiguity):
*
* <table border="1">
* <tr><th>Absolute path</th><th>Base name</th></tr>
* <tr><td>"/tmp/tst.sql"</td><td>"tst.sql"</td></tr>
* <tr><td>"C:/Program Files (x86)"</td><td>"Program Files (x86)"</td></tr>
* <tr><td>"/"</td><td>""</td></tr>
* <tr><td>"C:/"</td><td>""</td></tr>
* <tr><td>"D:/"</td><td>""</td></tr>
* <tr><td>"//FileServer/"</td><td>""</td></tr>
* </table>
*/
string getBaseName() {
result = this.getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1)
}
/**
* Gets the extension of this container, that is, the suffix of its base name
* after the last dot character, if any.
*
* In particular,
*
* - if the name does not include a dot, there is no extension, so this
* predicate has no result;
* - if the name ends in a dot, the extension is the empty string;
* - if the name contains multiple dots, the extension follows the last dot.
*
* Here are some examples of absolute paths and the corresponding extensions
* (surrounded with quotes to avoid ambiguity):
*
* <table border="1">
* <tr><th>Absolute path</th><th>Extension</th></tr>
* <tr><td>"/tmp/tst.cs"</td><td>"cs"</td></tr>
* <tr><td>"/tmp/.classpath"</td><td>"classpath"</td></tr>
* <tr><td>"/bin/bash"</td><td>not defined</td></tr>
* <tr><td>"/tmp/tst2."</td><td>""</td></tr>
* <tr><td>"/tmp/x.tar.gz"</td><td>"gz"</td></tr>
* </table>
*/
string getExtension() {
result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3)
}
/**
* Gets the stem of this container, that is, the prefix of its base name up to
* (but not including) the last dot character if there is one, or the entire
* base name if there is not.
*
* Here are some examples of absolute paths and the corresponding stems
* (surrounded with quotes to avoid ambiguity):
*
* <table border="1">
* <tr><th>Absolute path</th><th>Stem</th></tr>
* <tr><td>"/tmp/tst.cs"</td><td>"tst"</td></tr>
* <tr><td>"/tmp/.classpath"</td><td>""</td></tr>
* <tr><td>"/bin/bash"</td><td>"bash"</td></tr>
* <tr><td>"/tmp/tst2."</td><td>"tst2"</td></tr>
* <tr><td>"/tmp/x.tar.gz"</td><td>"x.tar"</td></tr>
* </table>
*/
string getStem() {
result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1)
}
/** Gets the parent container of this file or folder, if any. */
Container getParentContainer() { containerparent(result, this) }
/** Gets a file or sub-folder in this container. */
Container getAChildContainer() { this = result.getParentContainer() }
/** Gets a file in this container. */
File getAFile() { result = this.getAChildContainer() }
/** Gets the file in this container that has the given `baseName`, if any. */
File getFile(string baseName) {
result = this.getAFile() and
result.getBaseName() = baseName
}
/** Gets a sub-folder in this container. */
Folder getAFolder() { result = this.getAChildContainer() }
/** Gets the sub-folder in this container that has the given `baseName`, if any. */
Folder getFolder(string baseName) {
result = this.getAFolder() and
result.getBaseName() = baseName
}
/** Gets the file or sub-folder in this container that has the given `name`, if any. */
Container getChildContainer(string name) {
result = this.getAChildContainer() and
result.getBaseName() = name
}
/** Gets the file in this container that has the given `stem` and `extension`, if any. */
File getFile(string stem, string extension) {
result = this.getAChildContainer() and
result.getStem() = stem and
result.getExtension() = extension
}
/** Gets a sub-folder contained in this container. */
Folder getASubFolder() { result = this.getAChildContainer() }
/**
* Gets a textual representation of the path of this container.
*
* This is the absolute path of the container.
*/
string toString() { result = this.getAbsolutePath() }
}
/** A folder. */
class Folder extends Container, @folder {
override string getAbsolutePath() { folders(this, result) }
override string getURL() { result = "folder://" + this.getAbsolutePath() }
}
/** A file. */
class File extends Container, @file {
override string getAbsolutePath() { files(this, result) }
/** Gets the number of lines in this file. */
int getNumberOfLines() { numlines(this, result, _, _) }
/** Gets the number of lines containing code in this file. */
int getNumberOfLinesOfCode() { numlines(this, _, result, _) }
/** Gets the number of lines containing comments in this file. */
int getNumberOfLinesOfComments() { numlines(this, _, _, result) }
override string getURL() { result = "file://" + this.getAbsolutePath() + ":0:0:0:0" }
/** Holds if this file is a QL test stub file. */
pragma[noinline]
private predicate isStub() {
// this.extractedQlTest() and
this.getAbsolutePath().matches("%resources/stubs/%")
}
/** Holds if this file contains source code. */
predicate fromSource() {
this.getExtension() = "cs" and
not this.isStub()
}
/** Holds if this file is a library. */
predicate fromLibrary() {
not this.getBaseName() = "" and
not this.fromSource()
}
}
/**
* A source file.
*/
class SourceFile extends File {
SourceFile() { this.fromSource() }
}

View File

@@ -1,7 +0,0 @@
import powershell
class FileRedirection extends @file_redirection, Redirection {
override string toString() { result = "FileRedirection" }
override Location getLocation() { file_redirection_location(this, result) }
}

View File

@@ -1,23 +0,0 @@
import powershell
class ForEachStmt extends @foreach_statement, LoopStmt {
override SourceLocation getLocation() { foreach_statement_location(this, result) }
override string toString() { result = "forach(... in ...)" }
final override StmtBlock getBody() { foreach_statement(this, _, _, result, _) }
VarAccess getVarAccess() { foreach_statement(this, result, _, _, _) }
Variable getVariable() {
exists(VarAccess va |
va = this.getVarAccess() and
foreach_statement(this, va, _, _, _) and
result = va.getVariable()
)
}
PipelineBase getIterableExpr() { foreach_statement(this, _, result, _, _) }
predicate isParallel() { foreach_statement(this, _, _, _, 1) }
}

View File

@@ -1,15 +0,0 @@
import powershell
class ForStmt extends @for_statement, LoopStmt {
override SourceLocation getLocation() { for_statement_location(this, result) }
override string toString() { result = "for(...;...;...)" }
PipelineBase getInitializer() { for_statement_initializer(this, result) }
PipelineBase getCondition() { for_statement_condition(this, result) }
PipelineBase getIterator() { for_statement_iterator(this, result) }
final override StmtBlock getBody() { for_statement(this, result) }
}

View File

@@ -1,127 +0,0 @@
import powershell
import semmle.code.powershell.controlflow.BasicBlocks
abstract private class AbstractFunction extends Ast {
/** Gets the name of this function. */
abstract string getName();
/** Holds if this function has name `name`. */
final predicate hasName(string name) { this.getName() = name }
/** Gets the body of this function. */
abstract ScriptBlock getBody();
/**
* Gets the i'th function parameter, if any.
*
* Note that this predicate only returns _function_ parameters.
* To also get _block_ parameters use the `getParameter` predicate.
*/
abstract Parameter getFunctionParameter(int i);
/** Gets the declaring type of this function, if any. */
abstract Type getDeclaringType();
/**
* Gets any function parameter of this function.
*
* Note that this only gets _function_ paramters. To get any parameter
* use the `getAParameter` predicate.
*/
final Parameter getAFunctionParameter() { result = this.getFunctionParameter(_) }
/** Gets the number of function parameters. */
final int getNumberOfFunctionParameters() { result = count(this.getAFunctionParameter()) }
/**
* Gets the number of parameters (both function and block).
* Note: This excludes the `this` parameter.
*/
final int getNumberOfParameters() { result = count(this.getAParameter()) }
/**
* Gets the i'th parameter of this function, if any.
*
* This does not include the `this` parameter.
*
* The implicit underscore parameter (if any) is included at index `-1`.
*/
final Parameter getParameter(int i) {
result.getFunction() = this and
result.getIndex() = i
}
final Parameter getParameterExcludingPiplines(int i) {
result = this.getFunctionParameter(i)
or
result = this.getBody().getParamBlock().getParameterExcludingPiplines(i)
}
final Parameter getThisParameter() {
result.isThis() and
result.getFunction() = this
}
/** Gets any parameter of this function. */
final Parameter getAParameter() { result = this.getParameter(_) }
/** Gets the entry point of this function in the control-flow graph. */
EntryBasicBlock getEntryBasicBlock() { result.getScope() = this.getBody() }
}
final class Function = AbstractFunction;
/**
* A function definition.
*/
private class FunctionBase extends @function_definition, Stmt, AbstractFunction {
override string toString() { result = this.getName() }
override SourceLocation getLocation() { function_definition_location(this, result) }
override string getName() { function_definition(this, _, result, _, _) }
override ScriptBlock getBody() { function_definition(this, result, _, _, _) }
predicate isFilter() { function_definition(this, _, _, true, _) }
predicate isWorkflow() { function_definition(this, _, _, _, true) }
override Parameter getFunctionParameter(int i) { result.isFunctionParameter(this, i) }
override Type getDeclaringType() { none() }
}
private predicate isMethod(Member m, ScriptBlock body) {
function_member(m, body, _, _, _, _, _, _, _)
}
/**
* A method definition. That is, a function defined inside a class definition.
*/
class Method extends FunctionBase {
Method() { isMethod(_, super.getBody()) }
/** Gets the member corresponding to this function definition. */
Member getMember() { isMethod(result, super.getBody()) }
/** Holds if this method is a constructor. */
predicate isConstructor() { function_member(this.getMember(), _, true, _, _, _, _, _, _) }
final override Type getDeclaringType() { result = this.getMember().getDeclaringType() }
}
/** A constructor definition. */
class Constructor extends Method {
Constructor() { this.isConstructor() }
}
class TopLevel extends AbstractFunction instanceof TopLevelScriptBlock {
final override string getName() { result = "toplevel" }
final override ScriptBlock getBody() { result = this }
final override Parameter getFunctionParameter(int i) { none() }
final override Type getDeclaringType() { none() }
}

View File

@@ -1,8 +0,0 @@
import powershell
/** A `break` or `continue` statement. */
class GotoStmt extends @labelled_statement, Stmt {
/** ..., if any. */
Expr getLabel() { statement_label(this, result) }
}

View File

@@ -1,21 +0,0 @@
import powershell
class HashTableExpr extends @hash_table, Expr {
final override Location getLocation() { hash_table_location(this, result) }
final override string toString() { result = "${...}" }
Stmt getElement(Expr key) { hash_table_key_value_pairs(this, _, key, result) } // TODO: Change @ast to @expr in db scheme
Stmt getElementFromConstant(string key) {
result = this.getElement(any(StringConstExpr sc | sc.getValue().getValue() = key))
}
predicate hasKey(Expr key) { exists(this.getElement(key)) }
Stmt getAnElement() { result = this.getElement(_) }
predicate hasEntry(int index, Expr key, Stmt value) {
hash_table_key_value_pairs(this, index, key, value)
}
}

View File

@@ -1,24 +0,0 @@
import powershell
class IfStmt extends @if_statement, Stmt {
override SourceLocation getLocation() { if_statement_location(this, result) }
override string toString() {
if this.hasElse() then result = "if (...) {...} else {...}" else result = "if (...) {...}"
}
PipelineBase getCondition(int i) { if_statement_clause(this, i, result, _) }
PipelineBase getACondition() { result = this.getCondition(_) }
StmtBlock getThen(int i) { if_statement_clause(this, i, _, result) }
int getNumberOfConditions() { result = count(this.getACondition()) }
StmtBlock getAThen() { result = this.getThen(_) }
/** ..., if any. */
StmtBlock getElse() { if_statement_else(this, result) }
predicate hasElse() { exists(this.getElse()) }
}

View File

@@ -1,30 +0,0 @@
import powershell
private import internal.ExplicitWrite::Private
class IndexExpr extends @index_expression, Expr {
override string toString() { result = "...[...]" }
override SourceLocation getLocation() { index_expression_location(this, result) }
Expr getIndex() { index_expression(this, result, _, _) } // TODO: Change @ast to @expr in the dbscheme
Expr getBase() { index_expression(this, _, result, _) } // TODO: Change @ast to @expr in the dbscheme
predicate isNullConditional() { index_expression(this, _, _, true) }
}
private predicate isImplicitIndexWrite(Expr e) { none() }
/** An index expression that is being written to. */
class IndexExprWrite extends IndexExpr {
IndexExprWrite() { isExplicitWrite(this, _) or isImplicitIndexWrite(this) }
predicate isExplicit(AssignStmt assign) { isExplicitWrite(this, assign) }
predicate isImplicit() { isImplicitIndexWrite(this) }
}
/** An index expression that is being read from. */
class IndexExprRead extends IndexExpr {
IndexExprRead() { not this instanceof IndexExprWrite }
}

View File

@@ -1,49 +0,0 @@
import powershell
class InvokeMemberExpr extends @invoke_member_expression, MemberExprBase {
override SourceLocation getLocation() { invoke_member_expression_location(this, result) }
Expr getQualifier() { invoke_member_expression(this, result, _) }
string getName() { result = this.getMember().(StringConstExpr).getValue().getValue() }
CmdElement getMember() { invoke_member_expression(this, _, result) }
string getMemberName() { result = this.getMember().(StringConstExpr).getValue().getValue() }
Expr getArgument(int i) { invoke_member_expression_argument(this, i, result) }
Expr getAnArgument() { invoke_member_expression_argument(this, _, result) }
override string toString() { result = "call to " + this.getName() }
override predicate isStatic() { this.getQualifier() instanceof TypeNameExpr }
}
/**
* A call to a constructor. For example:
*
* ```powershell
* [System.IO.FileInfo]::new("C:\\file.txt")
* ```
*/
class ConstructorCall extends InvokeMemberExpr {
TypeNameExpr typename;
ConstructorCall() {
this.isStatic() and typename = this.getQualifier() and this.getName() = "new"
}
/**
* Gets the type being constructed by this constructor call.
*
* Note that the type may not exist in the database.
*
* Use `getConstructedTypeName` to get the name of the type (which will
* always exist in the database).
*/
Type getConstructedType() { result = typename.getType() }
/** Gets the name of the type being constructed by this constructor call. */
string getConstructedTypeName() { result = typename.getName() }
}

View File

@@ -1,5 +0,0 @@
import powershell
class LabeledStmt extends @labeled_statement, Stmt {
string getLabel() { label(this, result) }
}

View File

@@ -1,52 +0,0 @@
/**
* Provides the `Location` class to give a location for each
* program element.
*
* A `SourceLocation` provides a section of text in a source file
* containing the program element.
*
* Based on csharp/ql/lib/semmle/code/csharp/Location.qll
*/
import File
/**
* A location of a program element.
*/
class Location extends @location {
/** Gets the file of the location. */
File getFile() { none() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
none()
}
/** Gets a textual representation of this location. */
string toString() { none() }
/** Gets the 1-based line number (inclusive) where this location starts. */
int getStartLine() { this.hasLocationInfo(_, result, _, _, _) }
/** Gets the 1-based line number (inclusive) where this location ends. */
int getEndLine() { this.hasLocationInfo(_, _, _, result, _) }
/** Gets the 1-based column number (inclusive) where this location starts. */
int getStartColumn() { this.hasLocationInfo(_, _, result, _, _) }
/** Gets the 1-based column number (inclusive) where this location ends. */
int getEndColumn() { this.hasLocationInfo(_, _, _, _, result) }
}
/** An empty location. */
class EmptyLocation extends Location {
EmptyLocation() { this.hasLocationInfo("", 0, 0, 0, 0) }
}

View File

@@ -1,5 +0,0 @@
import powershell
class LoopStmt extends @loop_statement, LabeledStmt {
StmtBlock getBody() { none() }
}

View File

@@ -1,17 +0,0 @@
import powershell
class Member extends @member, Ast {
Type getDeclaringType() { result.getAMember() = this }
string getName() { none() }
override string toString() { result = this.getName() }
predicate isHidden() { none() }
predicate isPrivate() { none() }
predicate isPublic() { none() }
predicate isStatic() { none() }
}

View File

@@ -1,28 +0,0 @@
import powershell
class MemberExpr extends @member_expression, MemberExprBase {
final override Location getLocation() { member_expression_location(this, result) }
Expr getQualifier() { member_expression(this, result, _, _, _) }
CmdElement getMember() { member_expression(this, _, result, _, _) }
/** Gets the name of the member being looked up, if any. */
string getMemberName() { result = this.getMember().(StringConstExpr).getValue().getValue() }
predicate isNullConditional() { member_expression(this, _, _, true, _) }
override predicate isStatic() { member_expression(this, _, _, _, true) }
final override string toString() { result = this.getMember().toString() }
}
/** A `MemberExpr` that is being written to. */
class MemberExprWriteAccess extends MemberExpr {
MemberExprWriteAccess() { this = any(AssignStmt assign).getLeftHandSide() }
}
/** A `MemberExpr` that is being read from. */
class MemberExprReadAccess extends MemberExpr {
MemberExprReadAccess() { not this instanceof MemberExprWriteAccess }
}

View File

@@ -1,5 +0,0 @@
import powershell
class MemberExprBase extends @member_expression_base, Expr {
predicate isStatic() { none() }
}

View File

@@ -1,7 +0,0 @@
import powershell
class MergingRedirection extends @merging_redirection, Redirection {
override string toString() { result = "MergingRedirection" }
override Location getLocation() { merging_redirection_location(this, result) }
}

View File

@@ -1,44 +0,0 @@
import powershell
class ModuleManifestFile extends File {
ModuleManifestFile() { this.getExtension() = "psd1" }
}
private Expr getEntry(HashTableExpr ht, string key) {
result = ht.getElementFromConstant(key).(CmdExpr).getExpr() and
not result instanceof ArrayLiteral
}
private Expr getAnEntry(HashTableExpr ht, string key) {
exists(Expr e | e = ht.getElementFromConstant(key).(CmdExpr).getExpr() |
not e instanceof ArrayLiteral and result = e
or
result = e.(ArrayLiteral).getAnElement()
)
}
class ModuleManifest extends HashTableExpr {
string moduleVersion;
ModuleManifest() {
// The hash table is in a .psd1 file
this.getLocation().getFile() instanceof ModuleManifestFile and
// It's at the top level of the file
this.getParent().(CmdExpr).getParent().(NamedBlock).getParent() instanceof TopLevel and
// It has a `ModuleVersion` entry. The only required field is ModuleVersion.
// https://learn.microsoft.com/en-us/powershell/scripting/developer/module/how-to-write-a-powershell-module-manifest?view=powershell-7.4#to-create-and-use-a-module-manifest
moduleVersion = getEntry(this, "ModuleVersion").getValue().asString()
}
string getModuleVersion() { result = moduleVersion }
string getModuleName() {
result + ".psd1" = this.getLocation().getFile().getBaseName()
}
string getAFunctionToExport() {
result = getAnEntry(this, "FunctionsToExport").getValue().asString()
}
string getACmdLetToExport() { result = getAnEntry(this, "CmdletsToExport").getValue().asString() }
}

View File

@@ -1,17 +0,0 @@
import powershell
class ModuleSpecification extends @module_specification {
string toString() { result = this.getName() }
string getName() { module_specification(this, result, _, _, _, _) }
string getGuid() { module_specification(this, _, result, _, _, _) }
string getMaxVersion() { module_specification(this, _, _, result, _, _) }
string getRequiredVersion() { module_specification(this, _, _, _, result, _) }
string getVersion() { module_specification(this, _, _, _, _, result) }
Location getLocation() { result instanceof EmptyLocation }
}

View File

@@ -1,21 +0,0 @@
import powershell
class NamedAttributeArgument extends @named_attribute_argument, Ast {
final override string toString() { result = this.getName() }
final override SourceLocation getLocation() { named_attribute_argument_location(this, result) }
string getName() { named_attribute_argument(this, result, _) }
predicate hasName(string s) { this.getName() = s }
Expr getValue() { named_attribute_argument(this, _, result) }
}
class ValueFromPipelineAttribute extends NamedAttributeArgument {
ValueFromPipelineAttribute() { this.getName() = "ValueFromPipeline" }
}
class ValueFromPipelineByPropertyName extends NamedAttributeArgument {
ValueFromPipelineByPropertyName() { this.getName() = "ValueFromPipelineByPropertyName" }
}

View File

@@ -1,19 +0,0 @@
import powershell
class NamedBlock extends @named_block, Ast {
override string toString() { result = "{...}" }
override SourceLocation getLocation() { named_block_location(this, result) }
int getNumStatements() { named_block(this, result, _) }
int getNumTraps() { named_block(this, _, result) }
Stmt getStmt(int i) { named_block_statement(this, i, result) }
Stmt getAStmt() { result = this.getStmt(_) }
TrapStmt getTrap(int i) { named_block_trap(this, i, result) }
TrapStmt getATrap() { result = this.getTrap(_) }
}

View File

@@ -1,55 +0,0 @@
import powershell
abstract private class AbstractObjectCreation extends Call {
/**
* The type of the object being constructed.
* Note that the type may not exist in the database.
*
* Use `getConstructedTypeName` to get the name of the type (which will
* always exist in the database).
*/
abstract Type getConstructedType();
/** The name of the type of the object being constructed. */
abstract string getConstructedTypeName();
}
/**
* An object creation from a call to a constructor. For example:
* ```powershell
* [System.IO.FileInfo]::new("C:\\file.txt")
* ```
*/
class NewObjectCreation extends AbstractObjectCreation instanceof ConstructorCall {
final override Type getConstructedType() { result = ConstructorCall.super.getConstructedType() }
final override string getConstructedTypeName() {
result = ConstructorCall.super.getConstructedTypeName()
}
}
/**
* An object creation from a call to `New-Object`. For example:
* ```powershell
* New-Object -TypeName System.IO.FileInfo -ArgumentList "C:\\file.txt"
* ```
*/
class DotNetObjectCreation extends AbstractObjectCreation instanceof Cmd {
DotNetObjectCreation() { this.getCommandName() = "New-Object" }
final override Type getConstructedType() { none() }
final override string getConstructedTypeName() {
// Either it's the named argument `TypeName`
result = Cmd.super.getNamedArgument("TypeName").(StringConstExpr).getValue().getValue()
or
// Or it's the first positional argument if that's the named argument
not Cmd.super.hasNamedArgument("TypeName") and
exists(StringConstExpr arg | arg = Cmd.super.getPositionalArgument(0) |
result = arg.getValue().getValue() and
not arg = Cmd.super.getNamedArgument(["ArgumentList", "Property"])
)
}
}
final class ObjectCreation = AbstractObjectCreation;

View File

@@ -1,21 +0,0 @@
import powershell
class ParamBlock extends @param_block, Ast {
override string toString() { result = "param(...)" }
override SourceLocation getLocation() { param_block_location(this, result) }
int getNumAttributes() { param_block(this, result, _) }
int getNumParameters() { param_block(this, _, result) }
Attribute getAttribute(int i) { param_block_attribute(this, i, result) }
Attribute getAnAttribute() { result = this.getAttribute(_) }
Parameter getParameter(int i) { result.hasParameterBlock(this, i) }
Parameter getParameterExcludingPiplines(int i) { result.hasParameterBlockExcludingPipelines(this, i) }
Parameter getAParameter() { result = this.getParameter(_) }
}

View File

@@ -1,9 +0,0 @@
import powershell
class ParenExpr extends @paren_expression, Expr {
PipelineBase getBase() { paren_expression(this, result) }
override SourceLocation getLocation() { paren_expression_location(this, result) }
override string toString() { result = "(...)" }
}

View File

@@ -1,17 +0,0 @@
import powershell
class Pipeline extends @pipeline, Chainable {
override string toString() {
if this.getNumberOfComponents() = 1
then result = this.getComponent(0).toString()
else result = "...|..."
}
override SourceLocation getLocation() { pipeline_location(this, result) }
int getNumberOfComponents() { result = count(this.getAComponent()) }
CmdBase getComponent(int i) { pipeline_component(this, i, result) }
CmdBase getAComponent() { result = this.getComponent(_) }
}

View File

@@ -1,3 +0,0 @@
import powershell
class PipelineBase extends @pipeline_base, Stmt { }

View File

@@ -1,11 +0,0 @@
import powershell
class PipelineChain extends @pipeline_chain, Chainable {
final override SourceLocation getLocation() { pipeline_chain_location(this, result) }
predicate isBackground() { pipeline_chain(this, true, _, _, _) }
Chainable getLeft() { pipeline_chain(this, _, _, result, _) }
Pipeline getRight() { pipeline_chain(this, _, _, _, result) }
}

View File

@@ -1,17 +0,0 @@
import powershell
class PropertyMember extends @property_member, Member {
override string getName() { property_member(this, _, _, _, _, result, _) }
override SourceLocation getLocation() { property_member_location(this, result) }
override string toString() { result = this.getName() }
override predicate isHidden() { property_member(this, true, _, _, _, _, _) }
override predicate isPrivate() { property_member(this, _, true, _, _, _, _) }
override predicate isPublic() { property_member(this, _, _, true, _, _, _) }
override predicate isStatic() { property_member(this, _, _, _, true, _, _) }
}

View File

@@ -1,3 +0,0 @@
import powershell
class Redirection extends @redirection, Ast { }

View File

@@ -1,13 +0,0 @@
import powershell
class ReturnStmt extends @return_statement, Stmt {
override SourceLocation getLocation() { return_statement_location(this, result) }
override string toString() {
if this.hasPipeline() then result = "return ..." else result = "return"
}
PipelineBase getPipeline() { return_statement_pipeline(this, result) }
predicate hasPipeline() { exists(this.getPipeline()) }
}

View File

@@ -1,111 +0,0 @@
import powershell
private import semmle.code.powershell.controlflow.internal.Scope
class ScriptBlock extends @script_block, Ast {
predicate isTopLevel() { not exists(this.getParent()) }
override string toString() {
if this.isTopLevel()
then result = this.getLocation().getFile().getBaseName()
else result = "{...}"
}
override Location getLocation() { script_block_location(this, result) }
int getNumUsings() { script_block(this, result, _, _, _, _) }
int getNumRequiredModules() { script_block(this, _, result, _, _, _) }
int getNumRequiredAssemblies() { script_block(this, _, _, result, _, _) }
int getNumRequiredPsEditions() { script_block(this, _, _, _, result, _) }
int getNumRequiredPsSnapIns() { script_block(this, _, _, _, _, result) }
Stmt getUsing(int i) { script_block_using(this, i, result) }
Stmt getAUsing() { result = this.getUsing(_) }
ParamBlock getParamBlock() { script_block_param_block(this, result) }
NamedBlock getBeginBlock() { script_block_begin_block(this, result) }
NamedBlock getCleanBlock() { script_block_clean_block(this, result) }
NamedBlock getDynamicParamBlock() { script_block_dynamic_param_block(this, result) }
NamedBlock getEndBlock() { script_block_end_block(this, result) }
NamedBlock getProcessBlock() { script_block_process_block(this, result) }
string getRequiredApplicationId() { script_block_required_application_id(this, result) }
boolean getRequiresElevation() { script_block_requires_elevation(this, result) }
string getRequiredPsVersion() { script_block_required_ps_version(this, result) }
ModuleSpecification getModuleSpecification(int i) {
script_block_required_module(this, i, result)
}
ModuleSpecification getAModuleSpecification() { result = this.getModuleSpecification(_) }
final override Scope getEnclosingScope() { result = 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)
)
or
this.isTopLevel() and
result = this.getParamBlock().getParameter(i)
}
/**
* Gets a paramter in this scope.
*
* This may be both function parameters and parameter block parameters.
*/
Parameter getAParameter() { result = this.getParameter(_) }
Parameter getThisParameter() {
exists(Function func |
func.getBody() = this and
result = func.getThisParameter()
)
}
/** Gets the number of function parameters. */
final int getNumberOfParameters() { result = count(this.getAParameter()) }
final Parameter getParameterExcludingPiplines(int i) {
result = this.getParamBlock().getParameterExcludingPiplines(i)
}
}
/** A `process` block. */
class ProcessBlock extends NamedBlock {
ScriptBlock scriptBlock;
ProcessBlock() { scriptBlock.getProcessBlock() = this }
ScriptBlock getScriptBlock() { result = scriptBlock }
PipelineParameter getPipelineParameter() {
result = scriptBlock.getEnclosingFunction().getAParameter()
}
PipelineByPropertyNameParameter getAPipelineByPropertyNameParameter() {
result = scriptBlock.getEnclosingFunction().getAParameter()
}
}
class TopLevelScriptBlock extends ScriptBlock {
TopLevelScriptBlock() { this.isTopLevel() }
}

View File

@@ -1,9 +0,0 @@
import powershell
class ScriptBlockExpr extends @script_block_expression, Expr {
override SourceLocation getLocation() { script_block_expression_location(this, result) }
override string toString() { result = "{...}" }
ScriptBlock getBody() { script_block_expression(this, result) }
}

View File

@@ -1,25 +0,0 @@
import powershell
/**
* A location in source code, comprising of a source file and a segment of text
* within the file.
*/
class SourceLocation extends Location, @location_default {
override File getFile() { locations_default(this, result, _, _, _, _) }
override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
exists(File f | locations_default(this, f, startline, startcolumn, endline, endcolumn) |
filepath = f.getAbsolutePath()
)
}
override string toString() {
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
this.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
result = filepath + ":" + startline + ":" + startcolumn + ":" + endline + ":" + endcolumn
)
}
}

View File

@@ -1,28 +0,0 @@
import powershell
abstract private class AbstractSplitExpr extends Expr {
abstract Expr getExpr();
/** ..., if any. */
Expr getSeparator() { none() }
}
final class SplitExpr = AbstractSplitExpr;
class UnarySplitExpr extends AbstractSplitExpr, UnaryExpr {
UnarySplitExpr() { this.getKind() = 75 }
final override string toString() { result = "-split ..." }
final override Expr getExpr() { result = this.getOperand() }
}
class BinarySplitExpr extends AbstractSplitExpr, BinaryExpr {
BinarySplitExpr() { this.getKind() = 75 }
final override string toString() { result = "... -split ..." }
final override Expr getExpr() { result = this.getLeft() }
final override Expr getSeparator() { result = this.getRight() }
}

View File

@@ -1,3 +0,0 @@
import powershell
class Stmt extends @statement, Ast { }

View File

@@ -1,32 +0,0 @@
import powershell
private import semmle.code.powershell.internal.AstEscape::Private
private module ReturnContainerInterpreter implements InterpretAstInputSig {
class T = Ast;
pragma[inline]
T interpret(Ast a) { result = a }
}
class StmtBlock extends @statement_block, Ast {
override SourceLocation getLocation() { statement_block_location(this, result) }
int getNumberOfStmts() { statement_block(this, result, _) }
int getNumTraps() { statement_block(this, _, result) }
Stmt getStmt(int index) { statement_block_statement(this, index, result) }
Stmt getAStmt() { result = this.getStmt(_) }
TrapStmt getTrapStmt(int index) { statement_block_trap(this, index, result) }
TrapStmt getATrapStmt() { result = this.getTrapStmt(_) }
override string toString() { result = "{...}" }
/** Gets an element that may escape this `StmtBlock`. */
Ast getAnElement() {
result = this.(AstEscape<ReturnContainerInterpreter>::Element).getAnEscapingElement()
}
}

View File

@@ -1,10 +0,0 @@
import powershell
/** A string constant. */
class StringConstExpr extends @string_constant_expression, BaseConstExpr {
override StringLiteral getValue() { string_constant_expression(this, result) }
override string getType() { result = "String" }
override SourceLocation getLocation() { string_constant_expression_location(this, result) }
}

View File

@@ -1,16 +0,0 @@
import powershell
class StringLiteral extends @string_literal {
int getNumContinuations() { result = strictcount(int i | exists(this.getContinuation(i))) }
string getContinuation(int index) { string_literal_line(this, index, result) }
/** Get the full string literal with all its parts concatenated */
string toString() { result = this.getValue() }
string getValue() {
result = concat(int i | i = [0 .. this.getNumContinuations()] | this.getContinuation(i), "\n")
}
SourceLocation getLocation() { string_literal_location(this, result) }
}

View File

@@ -1,10 +0,0 @@
import powershell
// TODO: Should we remove this from the dbscheme?
class ExpandableSubExpr extends @sub_expression, Expr {
final override Location getLocation() { sub_expression_location(this, result) }
StmtBlock getExpr() { sub_expression(this, result) }
final override string toString() { result = "$(...)" }
}

View File

@@ -1,25 +0,0 @@
import powershell
class SwitchStmt extends LabeledStmt, @switch_statement {
final override Location getLocation() { switch_statement_location(this, result) }
PipelineBase getCondition() { switch_statement(this, result, _) }
StmtBlock getDefault() { switch_statement_default(this, result) }
StmtBlock getCase(int i, Expr e) { switch_statement_clauses(this, i, e, result) }
StmtBlock getCase(int i) { result = this.getCase(i, _) }
StmtBlock getACase() { result = this.getCase(_) }
StmtBlock getCaseForExpr(Expr e) { result = this.getCase(_, e) }
Expr getPattern(int i) { exists(this.getCase(i, result)) }
Expr getAPattern() { result = this.getPattern(_) }
int getNumberOfCases() { result = count(this.getACase()) }
final override string toString() { result = "switch(...) {...}" }
}

View File

@@ -1,23 +0,0 @@
import powershell
class ConditionalExpr extends @ternary_expression, Expr {
override string toString() { result = "...?...:..." }
override SourceLocation getLocation() { ternary_expression_location(this, result) }
Expr getCondition() { ternary_expression(this, result, _, _) }
Expr getIfFalse() { ternary_expression(this, _, result, _) }
Expr getIfTrue() { ternary_expression(this, _, _, result) }
Expr getBranch(boolean value) {
value = true and
result = this.getIfTrue()
or
value = false and
result = this.getIfFalse()
}
Expr getABranch() { result = this.getBranch(_) }
}

View File

@@ -1,13 +0,0 @@
import powershell
class ThrowStmt extends @throw_statement, Stmt {
override SourceLocation getLocation() { throw_statement_location(this, result) }
override string toString() {
if this.hasPipeline() then result = "throw ..." else result = "throw"
}
PipelineBase getPipeline() { throw_statement_pipeline(this, result) }
predicate hasPipeline() { exists(this.getPipeline()) }
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +0,0 @@
import powershell
class TrapStmt extends @trap_statement, Stmt {
override SourceLocation getLocation() { trap_statement_location(this, result) }
override string toString() { result = "TrapStatement at: " + this.getLocation().toString() }
}

View File

@@ -1,18 +0,0 @@
import powershell
class TryStmt extends @try_statement, Stmt {
override SourceLocation getLocation() { try_statement_location(this, result) }
override string toString() { result = "try {...}" }
CatchClause getCatchClause(int i) { try_statement_catch_clause(this, i, result) }
CatchClause getACatchClause() { result = this.getCatchClause(_) }
/** ..., if any. */
StmtBlock getFinally() { try_statement_finally(this, result) }
StmtBlock getBody() { try_statement(this, result) }
predicate hasFinally() { exists(this.getFinally()) }
}

View File

@@ -1,31 +0,0 @@
import powershell
class Type extends @type_definition, Stmt {
override SourceLocation getLocation() { type_definition_location(this, result) }
override string toString() { result = this.getName() }
string getName() { type_definition(this, result, _, _, _, _) }
Member getMember(int i) { type_definition_members(this, i, result) }
Member getAMember() { result = this.getMember(_) }
Method getMethod(string name) {
result.getMember() = this.getAMember() and
result.hasName(name)
}
Constructor getAConstructor() {
result = this.getAMethod() and
result.getName() = this.getName()
}
Method getAMethod() { result = this.getMethod(_) }
TypeConstraint getBaseType(int i) { type_definition_base_type(this, i, result) }
TypeConstraint getABaseType() { result = this.getBaseType(_) }
Type getASubtype() { result.getABaseType().getName() = this.getName() }
}

View File

@@ -1,13 +0,0 @@
import powershell
class TypeConstraint extends @type_constraint, AttributeBase {
override SourceLocation getLocation() { type_constraint_location(this, result) }
/** Gets the assembly name. */
string getName() { type_constraint(this, result, _) }
/** Gets the full name of this type constraint including namespaces. */
string getFullName() { type_constraint(this, _, result) }
override string toString() { result = this.getName() }
}

View File

@@ -1,14 +0,0 @@
import powershell
class TypeNameExpr extends @type_expression, Expr {
string getName() { type_expression(this, result, _) }
string getFullyQualifiedName() { type_expression(this, _, result) }
override string toString() { result = this.getName() }
override SourceLocation getLocation() { type_expression_location(this, result) }
/** Gets the type referred to by this `TypeNameExpr`. */
Type getType() { result.getName() = this.getName() }
}

View File

@@ -1,73 +0,0 @@
import powershell
class UnaryExpr extends @unary_expression, Expr {
override SourceLocation getLocation() { unary_expression_location(this, result) }
int getKind() { unary_expression(this, _, result, _) }
Expr getOperand() { unary_expression(this, result, _, _) }
}
class NotExpr extends UnaryExpr {
NotExpr() { this.getKind() = [36, 51] }
predicate isExclamationMark() { this.getKind() = 36 }
predicate isNot() { this.getKind() = 51 }
final override string toString() {
this.isExclamationMark() and result = "!..."
or
this.isNot() and result = "-not ..."
}
}
abstract private class AbstractUnaryArithmeticExpr extends UnaryExpr { }
final class UnaryArithmeticExpr = AbstractUnaryArithmeticExpr;
abstract private class AbstractPostfixExpr extends AbstractUnaryArithmeticExpr, UnaryExpr { }
abstract private class AbstractPrefixExpr extends AbstractUnaryArithmeticExpr, UnaryExpr { }
abstract private class AbstractIncrExpr extends AbstractUnaryArithmeticExpr, UnaryExpr { }
abstract private class AbstractDecrExpr extends AbstractUnaryArithmeticExpr, UnaryExpr { }
final class PostfixExpr = AbstractPostfixExpr;
final class PrefixExpr = AbstractPrefixExpr;
final class IncrExpr = AbstractIncrExpr;
final class DecrExpr = AbstractDecrExpr;
class PostfixIncrExpr extends AbstractPostfixExpr, AbstractIncrExpr {
PostfixIncrExpr() { this.getKind() = 95 }
final override string toString() { result = "...++" }
}
class PostfixDecrExpr extends AbstractPostfixExpr, AbstractIncrExpr {
PostfixDecrExpr() { this.getKind() = 96 }
final override string toString() { result = "...--" }
}
class PrefixDecrExpr extends AbstractPostfixExpr, AbstractIncrExpr {
PrefixDecrExpr() { this.getKind() = 31 }
final override string toString() { result = "--..." }
}
class PrefixIncrExpr extends AbstractPostfixExpr, AbstractIncrExpr {
PrefixIncrExpr() { this.getKind() = 32 }
final override string toString() { result = "++..." }
}
class NegateExpr extends AbstractUnaryArithmeticExpr {
NegateExpr() { this.getKind() = 41 }
final override string toString() { result = "-..." }
}

View File

@@ -1,7 +0,0 @@
import powershell
class UsingExpr extends @using_expression, Expr {
override string toString() { result = "$using..." }
override SourceLocation getLocation() { using_expression_location(this, result) }
}

View File

@@ -1,21 +0,0 @@
import powershell
class UsingStmt extends @using_statement, Stmt {
override SourceLocation getLocation() { using_statement_location(this, result) }
override string toString() { result = "using ..." }
string getName() {
exists(StringConstExpr const |
using_statement_name(this, const) and // TODO: Change dbscheme
result = const.getValue().getValue()
)
}
string getAlias() {
exists(StringConstExpr const |
using_statement_alias(this, const) and // TODO: Change dbscheme
result = const.getValue().getValue()
)
}
}

View File

@@ -1,406 +0,0 @@
private import powershell
private import semmle.code.powershell.controlflow.internal.Scope
private import internal.Parameter::Private as Internal
private predicate isFunctionParameterImpl(Internal::Parameter p, Function f, int i) {
function_definition_parameter(f, i, p)
}
private predicate hasParameterBlockImpl(Internal::Parameter p, ParamBlock block, int i) {
param_block_parameter(block, i, p)
}
private predicate hasParameterBlockExcludingPipelinesImpl(
Internal::Parameter p, ParamBlock block, int i
) {
p =
rank[i + 1](Internal::Parameter cand, int j |
hasParameterBlockImpl(cand, block, j) and
not cand.getAnAttribute().(Attribute).getANamedArgument() instanceof
ValueFromPipelineAttribute and
not cand.getAnAttribute().(Attribute).getANamedArgument() instanceof
ValueFromPipelineByPropertyName
|
cand order by j
)
}
/**
* Gets the enclosing scope of `p`.
*
* For a function parameter, this is the function body. For a parameter from a
* parameter block, this is the enclosing scope of the parameter block.
*
* In both of the above cases, the enclosing scope is the function body.
*/
private Scope getEnclosingScopeImpl(Internal::Parameter p) {
exists(Function f |
isFunctionParameterImpl(p, f, _) and
result = f.getBody()
)
or
exists(ParamBlock b |
hasParameterBlockImpl(p, b, _) and
result = b.getEnclosingScope()
)
}
bindingset[scope]
pragma[inline_late]
private predicate isParameterImpl(string name, Scope scope) {
exists(Internal::Parameter p | p.getName() = name and getEnclosingScopeImpl(p) = scope)
or
name = "_"
}
private predicate isThisParameter(Scope scope, Type t) {
t = scope.getEnclosingFunction().getDeclaringType()
}
private newtype TParameterImpl =
TInternalParameter(Internal::Parameter p) or
TUnderscore(Scope scope) {
exists(VarAccess va | va.getUserPath() = ["_", "PSItem"] and scope = va.getEnclosingScope())
} or
TThisParameter(Scope scope) { isThisParameter(scope, _) }
private class ParameterImpl extends TParameterImpl {
abstract Location getLocation();
string toString() { result = this.getName() }
abstract string getName();
abstract Scope getEnclosingScope();
predicate hasParameterBlock(ParamBlock block, int i) { none() }
predicate hasParameterBlockExcludingPipelines(ParamBlock block, int i) { none() }
predicate isFunctionParameter(Function f, int i) { none() }
Expr getDefaultValue() { none() }
abstract Attribute getAnAttribute();
VarAccess getAnAccess() {
// TODO: This won't join order nicely.
result.getUserPath() = this.getName() and
result.getEnclosingScope() = this.getEnclosingScope()
}
abstract predicate isPipeline();
abstract predicate isPipelineByPropertyName();
/**
* Gets the static type of this parameter.
* The type of this parameter at runtime may be a subtype of this static
* type.
*/
abstract string getStaticType();
}
private class InternalParameter extends ParameterImpl, TInternalParameter {
Internal::Parameter p;
InternalParameter() { this = TInternalParameter(p) }
override Location getLocation() { result = p.getLocation() }
override string getName() { result = p.getName() }
final override Scope getEnclosingScope() { result = getEnclosingScopeImpl(p) }
override predicate hasParameterBlock(ParamBlock block, int i) {
hasParameterBlockImpl(p, block, i)
}
override predicate hasParameterBlockExcludingPipelines(ParamBlock block, int i) {
hasParameterBlockExcludingPipelinesImpl(p, block, i)
}
override predicate isFunctionParameter(Function f, int i) { isFunctionParameterImpl(p, f, i) }
override Expr getDefaultValue() { result = p.getDefaultValue() }
override Attribute getAnAttribute() { result = p.getAnAttribute() }
override predicate isPipeline() {
this.getAnAttribute().getANamedArgument() instanceof ValueFromPipelineAttribute
}
override predicate isPipelineByPropertyName() {
this.getAnAttribute().getANamedArgument() instanceof ValueFromPipelineByPropertyName
}
final override string getStaticType() { result = p.getStaticType() }
}
/**
* The variable that represents an element in the pipeline.
*
* This is either the variable `$_` or the variable `$PSItem`.
*/
private class Underscore extends ParameterImpl, TUnderscore {
Scope scope;
Underscore() { this = TUnderscore(scope) }
override Location getLocation() {
// The location is the first access (ordered by location) to the variable in the scope
exists(VarAccess va |
va =
min(VarAccess cand, Location location |
cand = this.getAnAccess() and location = cand.getLocation()
|
cand order by location.getStartLine(), location.getStartColumn()
) and
result = va.getLocation()
)
}
override string getName() { result = "_" }
final override Scope getEnclosingScope() { result = scope }
final override Attribute getAnAttribute() { none() }
final override predicate isPipeline() { any() }
final override predicate isPipelineByPropertyName() { none() }
final override predicate isFunctionParameter(Function f, int i) { f.getBody() = scope and i = -1 }
final override string getStaticType() { none() }
}
private class ThisParameter extends ParameterImpl, TThisParameter {
Scope scope;
ThisParameter() { this = TThisParameter(scope) }
override Location getLocation() { result = scope.getLocation() }
override string getName() { result = "this" }
final override Scope getEnclosingScope() { result = scope }
final override Attribute getAnAttribute() { none() }
final override predicate isPipeline() { none() }
final override predicate isPipelineByPropertyName() { none() }
final override string getStaticType() {
exists(Type t |
isThisParameter(scope, t) and
result = t.getName()
)
}
}
private predicate isPipelineIteratorVariable(ParameterImpl p, ProcessBlock pb) {
p.isPipeline() and
pb.getEnclosingScope() = p.getEnclosingScope()
}
private predicate isPipelineByPropertyNameIteratorVariable(ParameterImpl p, ProcessBlock pb) {
p.isPipelineByPropertyName() and
pb.getEnclosingScope() = p.getEnclosingScope()
}
private newtype TVariable =
TLocalVariable(string name, Scope scope) {
not isParameterImpl(name, scope) and
not name = "this" and // This is modeled as a parameter
exists(VarAccess va | va.getUserPath() = name and scope = va.getEnclosingScope())
} or
TParameter(ParameterImpl p) or
TPipelineIteratorVariable(ProcessBlock pb) { isPipelineIteratorVariable(_, pb) } or
TPipelineByPropertyNameIteratorVariable(ParameterImpl p) {
isPipelineByPropertyNameIteratorVariable(p, _)
}
private class AbstractVariable extends TVariable {
abstract Location getLocation();
string toString() { result = this.getName() }
abstract string getName();
final predicate hasName(string s) { this.getName() = s }
abstract Scope getDeclaringScope();
VarAccess getAnAccess() {
exists(string s |
s = concat(this.getAQlClass(), ", ") and
// TODO: This won't join order nicely.
result.getUserPath() = this.getName() and
result.getEnclosingScope() = this.getDeclaringScope()
)
}
}
final class Variable = AbstractVariable;
abstract class AbstractLocalScopeVariable extends AbstractVariable { }
final class LocalScopeVariable = AbstractLocalScopeVariable;
class LocalVariable extends AbstractLocalScopeVariable, TLocalVariable {
string name;
Scope scope;
LocalVariable() { this = TLocalVariable(name, scope) }
override Location getLocation() {
// The location is the first access (ordered by location) to the variable in the scope
exists(VarAccess va |
va =
min(VarAccess cand, Location location |
cand = this.getAnAccess() and location = cand.getLocation()
|
cand order by location.getStartLine(), location.getStartColumn()
) and
result = va.getLocation()
)
}
override string getName() { result = name }
final override Scope getDeclaringScope() { result = scope }
}
/**
* A variable of the form `$Env:HOME`.
*/
class EnvVariable extends Variable {
string var;
EnvVariable() { this.getName() = ["env:", "Env:"] + var }
/**
* Gets the part of the variable name that represens which environment
* variable.
*/
string getEnvironmentVariable() { result = var }
}
class Parameter extends AbstractLocalScopeVariable, TParameter {
ParameterImpl p;
Parameter() { this = TParameter(p) }
override Location getLocation() { result = p.getLocation() }
override string getName() { result = p.getName() }
final predicate hasName(string name) { name = p.getName() }
final override Scope getDeclaringScope() { result = p.getEnclosingScope() }
predicate hasParameterBlock(ParamBlock block, int i) { p.hasParameterBlock(block, i) }
predicate hasParameterBlockExcludingPipelines(ParamBlock block, int i) {
p.hasParameterBlockExcludingPipelines(block, i)
}
predicate isFunctionParameter(Function f, int i) { p.isFunctionParameter(f, i) }
Expr getDefaultValue() { result = p.getDefaultValue() }
predicate hasDefaultValue() { exists(this.getDefaultValue()) }
/** Holds if this is the `this` parameter. */
predicate isThis() { p instanceof ThisParameter }
/**
* Gets the index of this parameter, if any.
*
* The parameter may be in a parameter block or a function parameter.
*/
int getIndex() { result = this.getFunctionIndex() or result = this.getBlockIndex() }
int getIndexExcludingPipelines() {
result = this.getFunctionIndex() or result = this.getBlockIndexExcludingPipelines()
}
/** Gets the index of this parameter in the parameter block, if any. */
int getBlockIndex() { this.hasParameterBlock(_, result) }
int getBlockIndexExcludingPipelines() { this.hasParameterBlockExcludingPipelines(_, result) }
/** Gets the index of this parameter in the function, if any. */
int getFunctionIndex() { this.isFunctionParameter(_, result) }
Function getFunction() { result.getBody() = this.getDeclaringScope() }
Attribute getAnAttribute() { result = p.getAnAttribute() }
predicate isPipeline() { p.isPipeline() }
predicate isPipelineByPropertyName() { p.isPipelineByPropertyName() }
string getStaticType() { result = p.getStaticType() }
}
class PipelineParameter extends Parameter {
PipelineParameter() { this.isPipeline() }
PipelineIteratorVariable getIteratorVariable() {
result.getProcessBlock().getEnclosingScope() = p.getEnclosingScope()
}
}
class PipelineByPropertyNameParameter extends Parameter {
PipelineByPropertyNameParameter() { this.isPipelineByPropertyName() }
PipelineByPropertyNameIteratorVariable getIteratorVariable() { result.getParameter() = this }
}
/**
* The variable that represents the value of a pipeline during a process block.
*
* That is, it is _not_ the `ValueFromPipeline` variable, but the value that is obtained by reading
* from the pipeline.
*/
class PipelineIteratorVariable extends AbstractLocalScopeVariable, TPipelineIteratorVariable {
private ProcessBlock pb;
PipelineIteratorVariable() { this = TPipelineIteratorVariable(pb) }
override Location getLocation() { result = pb.getLocation() }
override string getName() { result = "pipeline iterator for " + pb.toString() }
final override Scope getDeclaringScope() { result = pb.getEnclosingScope() }
ProcessBlock getProcessBlock() { result = pb }
}
/**
* The variable that represents the value of a pipeline that picks out a
* property specific property during a process block.
*
* That is, it is _not_ the `PipelineByPropertyName` variable, but the value that is obtained by reading
* from the pipeline.
*/
class PipelineByPropertyNameIteratorVariable extends AbstractLocalScopeVariable,
TPipelineByPropertyNameIteratorVariable
{
private ParameterImpl p;
PipelineByPropertyNameIteratorVariable() { this = TPipelineByPropertyNameIteratorVariable(p) }
override Location getLocation() { result = p.getLocation() }
override string getName() { result = "pipeline iterator for " + p.toString() }
final override Scope getDeclaringScope() { result = p.getEnclosingScope() }
Parameter getParameter() { result = TParameter(p) }
ProcessBlock getProcessBlock() { isPipelineByPropertyNameIteratorVariable(p, result) }
}

View File

@@ -1,59 +0,0 @@
import powershell
private import internal.ExplicitWrite::Private
private predicate isParameterName(@variable_expression ve) { parameter(_, ve, _, _) }
class VarAccess extends @variable_expression, Expr {
VarAccess() { not isParameterName(this) }
override string toString() { result = this.getUserPath() }
override SourceLocation getLocation() { variable_expression_location(this, result) }
string getUserPath() { variable_expression(this, result, _, _, _, _, _, _, _, _, _, _) }
string getDriveName() { variable_expression(this, _, result, _, _, _, _, _, _, _, _, _) }
boolean isConstant() { variable_expression(this, _, _, result, _, _, _, _, _, _, _, _) }
boolean isGlobal() { variable_expression(this, _, _, _, result, _, _, _, _, _, _, _) }
boolean isLocal() { variable_expression(this, _, _, _, _, result, _, _, _, _, _, _) }
boolean isPrivate() { variable_expression(this, _, _, _, _, _, result, _, _, _, _, _) }
boolean isScript() { variable_expression(this, _, _, _, _, _, _, result, _, _, _, _) }
boolean isUnqualified() { variable_expression(this, _, _, _, _, _, _, _, result, _, _, _) }
boolean isUnscoped() { variable_expression(this, _, _, _, _, _, _, _, _, result, _, _) }
boolean isVariable() { variable_expression(this, _, _, _, _, _, _, _, _, _, result, _) }
boolean isDriveQualified() { variable_expression(this, _, _, _, _, _, _, _, _, _, _, result) }
Variable getVariable() { result.getAnAccess() = this }
}
private predicate isImplicitVariableWriteAccess(Expr e) { none() }
class VarReadAccess extends VarAccess {
VarReadAccess() { not this instanceof VarWriteAccess }
}
class VarWriteAccess extends VarAccess {
VarWriteAccess() { isExplicitWrite(this, _) or isImplicitVariableWriteAccess(this) }
predicate isExplicit(AssignStmt assign) { isExplicitWrite(this, assign) }
predicate isImplicit() { isImplicitVariableWriteAccess(this) }
}
/** An access to an environment variable such as `$Env:PATH` */
class EnvVarAccess extends VarAccess {
EnvVarAccess() { super.getVariable() instanceof EnvVariable }
override EnvVariable getVariable() { result = super.getVariable() }
string getEnvironmentVariable() { result = this.getVariable().getEnvironmentVariable() }
}

View File

@@ -1,11 +0,0 @@
import powershell
class WhileStmt extends @while_statement, LoopStmt {
override SourceLocation getLocation() { while_statement_location(this, result) }
override string toString() { result = "while(...) {...}" }
PipelineBase getCondition() { while_statement_condition(this, result) }
final override StmtBlock getBody() { while_statement(this, result) }
}

View File

@@ -1,20 +0,0 @@
private import powershell
private import ControlFlowGraphImpl
/** Gets the enclosing scope of `n`. */
Scope scopeOf(Ast n) {
exists(Ast m | m = n.getParent() |
m = result
or
not m instanceof Scope and result = scopeOf(m)
)
}
/**
* A variable scope. This is either a top-level (file), a module, a class,
* or a callable.
*/
class Scope extends Ast, ScriptBlock {
/** Gets the outer scope, if any. */
Scope getOuterScope() { result = scopeOf(this) }
}

View File

@@ -1,13 +0,0 @@
module Private {
import Parameter::Private
import ExplicitWrite::Private
import Argument::Private
import Operation::Private
}
module Public {
import Parameter::Public
import ExplicitWrite::Public
import Argument::Public
import Operation::Public
}

View File

@@ -1,31 +0,0 @@
import powershell
module Private {
abstract private class AbstractOperation extends Expr {
abstract Expr getAnOperand();
abstract int getKind();
}
class BinaryOperation extends BinaryExpr, AbstractOperation {
final override Expr getAnOperand() { result = BinaryExpr.super.getAnOperand() }
final override int getKind() { result = BinaryExpr.super.getKind() }
}
class UnaryOperation extends UnaryExpr, AbstractOperation {
final override Expr getAnOperand() { result = UnaryExpr.super.getOperand() }
final override int getKind() { result = UnaryExpr.super.getKind() }
}
final class Operation = AbstractOperation;
}
module Public {
class Operation = Private::Operation;
class BinaryOperation = Private::BinaryOperation;
class UnaryOperation = Private::UnaryOperation;
}

View File

@@ -1,28 +0,0 @@
import powershell
module Private {
class Parameter extends @parameter, Ast {
override string toString() { result = this.getName().toString() }
string getName() {
exists(@variable_expression ve |
parameter(this, ve, _, _) and
variable_expression(ve, result, _, _, _, _, _, _, _, _, _, _)
)
}
string getStaticType() { parameter(this, _, result, _) }
int getNumAttributes() { parameter(this, _, _, result) }
AttributeBase getAttribute(int i) { parameter_attribute(this, i, result) }
AttributeBase getAnAttribute() { result = this.getAttribute(_) }
Expr getDefaultValue() { parameter_default_value(this, result) }
override SourceLocation getLocation() { parameter_location(this, result) }
}
}
module Public { }