Skip to content

Commit 22e508b

Browse files
committed
PS: Introduce a class for constant values.
1 parent 820f4b2 commit 22e508b

File tree

3 files changed

+127
-1
lines changed

3 files changed

+127
-1
lines changed

powershell/ql/lib/semmle/code/powershell/ConstantExpression.qll

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,119 @@ class ConstExpr extends @constant_expression, BaseConstExpr {
99

1010
override string toString() { result = this.getValue().toString() }
1111
}
12+
13+
private newtype TConstantValue =
14+
TConstInteger(int value) {
15+
exists(ConstExpr ce | ce.getType() = "Int32" and ce.getValue().getValue().toInt() = value)
16+
} or
17+
TConstDouble(float double) {
18+
exists(ConstExpr ce | ce.getType() = "Double" and ce.getValue().getValue().toFloat() = double)
19+
} or
20+
TConstString(string value) { exists(StringLiteral sl | sl.getValue() = value) } or
21+
TConstBoolean(boolean value) {
22+
exists(VarAccess va |
23+
value = true and
24+
va.getUserPath() = "true"
25+
or
26+
value = false and
27+
va.getUserPath() = "false"
28+
)
29+
} or
30+
TNull()
31+
32+
/** A constant value. */
33+
class ConstantValue extends TConstantValue {
34+
/** Gets a string representation of this value. */
35+
final string toString() { result = this.getValue() }
36+
37+
/** Gets the value of this consant. */
38+
string getValue() { none() }
39+
40+
/** Gets the integer value of this constant, if any. */
41+
int asInt() { none() }
42+
43+
/** Gets the floating point value of this constant, if any. */
44+
float asDouble() { none() }
45+
46+
/** Gets the string value of this constant, if any. */
47+
string asString() { none() }
48+
49+
/** Gets the boolean value of this constant, if any. */
50+
boolean asBoolean() { none() }
51+
52+
/** Holds if this constant represents the null value. */
53+
predicate isNull() { none() }
54+
55+
/** Gets a (unique) serialized version of this value. */
56+
string serialize() { none() }
57+
58+
/** Gets an exprssion that has this value. */
59+
Expr getAnExpr() { none() }
60+
}
61+
62+
/** A constant integer value */
63+
class ConstInteger extends ConstantValue, TConstInteger {
64+
final override int asInt() { this = TConstInteger(result) }
65+
66+
final override string getValue() { result = this.asInt().toString() }
67+
68+
final override string serialize() { result = this.getValue() }
69+
70+
final override ConstExpr getAnExpr() { result.getValue().getValue() = this.getValue() }
71+
}
72+
73+
/** A constant floating point value. */
74+
class ConstDouble extends ConstantValue, TConstDouble {
75+
final override float asDouble() { this = TConstDouble(result) }
76+
77+
final override string getValue() { result = this.asDouble().toString() }
78+
79+
final override string serialize() {
80+
exists(string res | res = this.asDouble().toString() |
81+
if exists(res.indexOf(".")) then result = res else result = res + ".0"
82+
)
83+
}
84+
85+
final override ConstExpr getAnExpr() { result.getValue().getValue() = this.getValue() }
86+
}
87+
88+
/** A constant string value. */
89+
class ConstString extends ConstantValue, TConstString {
90+
final override string asString() { this = TConstString(result) }
91+
92+
final override string getValue() { result = this.asString() }
93+
94+
final override string serialize() {
95+
result = "\"" + this.asString().replaceAll("\"", "\\\"") + "\""
96+
}
97+
98+
final override ConstExpr getAnExpr() { result.getValue().getValue() = this.getValue() }
99+
}
100+
101+
/** A constant boolean value. */
102+
class ConstBoolean extends ConstantValue, TConstBoolean {
103+
final override boolean asBoolean() { this = TConstBoolean(result) }
104+
105+
final override string getValue() { result = this.asBoolean().toString() }
106+
107+
final override string serialize() { result = this.getValue() }
108+
109+
final override VarAccess getAnExpr() {
110+
this.asBoolean() = true and
111+
result.getUserPath() = "true"
112+
or
113+
this.asBoolean() = false and
114+
result.getUserPath() = "false"
115+
}
116+
}
117+
118+
/** The constant null value. */
119+
class NullConst extends ConstantValue, TNull {
120+
final override predicate isNull() { any() }
121+
122+
final override string getValue() { result = "null" }
123+
124+
final override string serialize() { result = this.getValue() }
125+
126+
final override VarAccess getAnExpr() { result.getUserPath() = "null" }
127+
}
Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
11
import powershell
22

3-
class Expr extends @expression, CmdElement { }
3+
/**
4+
* An expression.
5+
*
6+
* This is the topmost class in the hierachy of all expression in PowerShell.
7+
*/
8+
class Expr extends @expression, CmdElement {
9+
/** Gets the constant value of this expression, if this is known. */
10+
final ConstantValue getValue() { result.getAnExpr() = this }
11+
}

powershell/ql/lib/semmle/code/powershell/controlflow/CfgNodes.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ class ExprCfgNode extends AstCfgNode {
4646

4747
/** Gets the underlying expression. */
4848
Expr getExpr() { result = e }
49+
50+
final ConstantValue getValue() { result = e.getValue() }
4951
}
5052

5153
/** A control-flow node that wraps an AST statement. */

0 commit comments

Comments
 (0)