Skip to content

Commit c21df48

Browse files
committed
QL: QL: Complete the GVN library.
1 parent a917f24 commit c21df48

2 files changed

Lines changed: 130 additions & 17 deletions

File tree

ql/src/codeql/GlobalValueNumbering.qll

Lines changed: 125 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,35 +5,69 @@ private import codeql_ql.ast.internal.Builtins
55

66
private newtype TValueNumber =
77
TVariableValueNumber(VarDecl var) { variableAccessValueNumber(_, var) } or
8-
TPredicateValueNumber(PredicateOrBuiltin pred, ValueNumberList args) {
8+
TFieldValueNumber(VarDecl var) { fieldAccessValueNumber(_, var) } or
9+
TThisValueNumber(Predicate pred) { thisAccessValueNumber(_, pred) } or
10+
TPredicateValueNumber(PredicateOrBuiltin pred, ValueNumberArgumentList args) {
911
predicateCallValueNumber(_, pred, args)
1012
} or
13+
TClassPredicateValueNumber(PredicateOrBuiltin pred, ValueNumber base, ValueNumberArgumentList args) {
14+
classPredicateCallValueNumber(_, pred, base, args)
15+
} or
1116
TLiteralValueNumber(string value, Type t) { literalValueNumber(_, value, t) } or
1217
TBinaryOpValueNumber(FunctionSymbol symbol, ValueNumber leftOperand, ValueNumber rightOperand) {
1318
binaryOperandValueNumber(_, symbol, leftOperand, rightOperand)
1419
} or
1520
TUnaryOpValueNumber(FunctionSymbol symbol, ValueNumber operand) {
1621
unaryOperandValueNumber(_, symbol, operand)
1722
} or
23+
TInlineCastValueNumber(ValueNumber operand, Type t) { inlineCastValueNumber(_, operand, t) } or
24+
TDontCareValueNumber() or
25+
TRangeValueNumber(ValueNumber lower, ValueNumber high) { rangeValueNumber(_, lower, high) } or
26+
TSetValueNumber(ValueNumberElementList elements) { setValueNumber(_, elements) } or
1827
TUniqueValueNumber(Expr e) { uniqueValueNumber(e) }
1928

20-
private newtype ValueNumberList =
21-
MkNil() or
22-
MkCons(ValueNumber head, ValueNumberList tail) { globalValueNumbers(_, _, head, tail) }
29+
private newtype ValueNumberArgumentList =
30+
MkArgsNil() or
31+
MkArgsCons(ValueNumber head, ValueNumberArgumentList tail) {
32+
argumentValueNumbers(_, _, head, tail)
33+
}
34+
35+
private newtype ValueNumberElementList =
36+
MkElementsNil() or
37+
MkElementsCons(ValueNumber head, ValueNumberElementList tail) {
38+
setValueNumbers(_, _, head, tail)
39+
}
2340

24-
private ValueNumberList globalValueNumbers(Call call, int start) {
41+
private ValueNumberArgumentList argumentValueNumbers(Call call, int start) {
2542
start = call.getNumberOfArguments() and
26-
result = MkNil()
43+
result = MkArgsNil()
2744
or
28-
exists(ValueNumber head, ValueNumberList tail |
29-
globalValueNumbers(call, start, head, tail) and
30-
result = MkCons(head, tail)
45+
exists(ValueNumber head, ValueNumberArgumentList tail |
46+
argumentValueNumbers(call, start, head, tail) and
47+
result = MkArgsCons(head, tail)
3148
)
3249
}
3350

34-
private predicate globalValueNumbers(Call call, int start, ValueNumber head, ValueNumberList tail) {
51+
private predicate argumentValueNumbers(
52+
Call call, int start, ValueNumber head, ValueNumberArgumentList tail
53+
) {
3554
head = valueNumber(call.getArgument(start)) and
36-
tail = globalValueNumbers(call, start + 1)
55+
tail = argumentValueNumbers(call, start + 1)
56+
}
57+
58+
private ValueNumberElementList setValueNumbers(Set set, int start) {
59+
start = set.getNumberOfElements() and
60+
result = MkElementsNil()
61+
or
62+
exists(ValueNumber head, ValueNumberElementList tail |
63+
setValueNumbers(set, start, head, tail) and
64+
result = MkElementsCons(head, tail)
65+
)
66+
}
67+
68+
private predicate setValueNumbers(Set set, int start, ValueNumber head, ValueNumberElementList tail) {
69+
head = valueNumber(set.getElement(start)) and
70+
tail = setValueNumbers(set, start + 1)
3771
}
3872

3973
/**
@@ -51,20 +85,46 @@ private predicate uniqueValueNumber(Expr e) { not numberable(e) }
5185

5286
private predicate numberable(Expr e) {
5387
e instanceof VarAccess or
88+
e instanceof FieldAccess or
89+
e instanceof ThisAccess or
5490
e instanceof Call or
5591
e instanceof Literal or
5692
e instanceof BinOpExpr or
57-
e instanceof UnaryExpr
93+
e instanceof UnaryExpr or
94+
e instanceof InlineCast or
95+
e instanceof ExprAnnotation or
96+
e instanceof DontCare or
97+
e instanceof Range or
98+
e instanceof Set or
99+
e instanceof AsExpr
100+
}
101+
102+
private predicate variableAccessValueNumber(VarAccess access, VarDef var) {
103+
access.getDeclaration() = var
58104
}
59105

60-
private predicate variableAccessValueNumber(VarAccess access, VarDecl var) {
106+
private predicate fieldAccessValueNumber(FieldAccess access, VarDef var) {
61107
access.getDeclaration() = var
62108
}
63109

64-
private predicate predicateCallValueNumber(Call call, PredicateOrBuiltin pred, ValueNumberList args) {
65-
exists(pred.getReturnType()) and
110+
private predicate thisAccessValueNumber(ThisAccess access, Predicate pred) {
111+
access.getEnclosingPredicate() = pred
112+
}
113+
114+
private predicate predicateCallValueNumber(
115+
Call call, PredicateOrBuiltin pred, ValueNumberArgumentList args
116+
) {
117+
call.getTarget() = pred and
118+
not exists(call.(MemberCall).getBase()) and
119+
args = argumentValueNumbers(call, 0)
120+
}
121+
122+
private predicate classPredicateCallValueNumber(
123+
MemberCall call, PredicateOrBuiltin pred, ValueNumber base, ValueNumberArgumentList args
124+
) {
66125
call.getTarget() = pred and
67-
args = globalValueNumbers(call, 0)
126+
valueNumber(call.getBase()) = base and
127+
args = argumentValueNumbers(call, 0)
68128
}
69129

70130
private predicate literalValueNumber(Literal lit, string value, Type t) {
@@ -99,17 +159,46 @@ private predicate unaryOperandValueNumber(UnaryExpr e, FunctionSymbol symbol, Va
99159
valueNumber(e.getOperand()) = operand
100160
}
101161

162+
private predicate inlineCastValueNumber(InlineCast cast, ValueNumber operand, Type t) {
163+
valueNumber(cast.getBase()) = operand and
164+
cast.getTypeExpr().getResolvedType() = t
165+
}
166+
167+
private predicate rangeValueNumber(Range range, ValueNumber lower, ValueNumber high) {
168+
valueNumber(range.getLowEndpoint()) = lower and
169+
valueNumber(range.getHighEndpoint()) = high
170+
}
171+
172+
private predicate setValueNumber(Set set, ValueNumberElementList elements) {
173+
elements = setValueNumbers(set, 0)
174+
}
175+
102176
private TValueNumber nonUniqueValueNumber(Expr e) {
103177
exists(VarDecl var |
104178
variableAccessValueNumber(e, var) and
105179
result = TVariableValueNumber(var)
106180
)
107181
or
108-
exists(PredicateOrBuiltin pred, ValueNumberList args |
182+
exists(VarDecl var |
183+
fieldAccessValueNumber(e, var) and
184+
result = TFieldValueNumber(var)
185+
)
186+
or
187+
exists(Predicate pred |
188+
thisAccessValueNumber(e, pred) and
189+
result = TThisValueNumber(pred)
190+
)
191+
or
192+
exists(PredicateOrBuiltin pred, ValueNumberArgumentList args |
109193
predicateCallValueNumber(e, pred, args) and
110194
result = TPredicateValueNumber(pred, args)
111195
)
112196
or
197+
exists(PredicateOrBuiltin pred, ValueNumber base, ValueNumberArgumentList args |
198+
classPredicateCallValueNumber(e, pred, base, args) and
199+
result = TClassPredicateValueNumber(pred, base, args)
200+
)
201+
or
113202
exists(string value, Type t |
114203
literalValueNumber(e, value, t) and
115204
result = TLiteralValueNumber(value, t)
@@ -124,6 +213,25 @@ private TValueNumber nonUniqueValueNumber(Expr e) {
124213
unaryOperandValueNumber(e, symbol, operand) and
125214
result = TUnaryOpValueNumber(symbol, operand)
126215
)
216+
or
217+
exists(ValueNumber operand, Type t |
218+
inlineCastValueNumber(e, operand, t) and
219+
result = TInlineCastValueNumber(operand, t)
220+
)
221+
or
222+
result = valueNumber([e.(ExprAnnotation).getExpression(), e.(AsExpr).getInnerExpr()])
223+
or
224+
e instanceof DontCare and result = TDontCareValueNumber()
225+
or
226+
exists(ValueNumber lower, ValueNumber high |
227+
rangeValueNumber(e, lower, high) and
228+
result = TRangeValueNumber(lower, high)
229+
)
230+
or
231+
exists(ValueNumberElementList elements |
232+
setValueNumber(e, elements) and
233+
result = TSetValueNumber(elements)
234+
)
127235
}
128236

129237
/** Gets the value number of an expression `e`. */

ql/src/codeql_ql/ast/Ast.qll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1945,6 +1945,11 @@ class Set extends TSet, Expr {
19451945
*/
19461946
Expr getAnElement() { result = getElement(_) }
19471947

1948+
/**
1949+
* Gets the number of elements in this set literal expression.
1950+
*/
1951+
int getNumberOfElements() { result = count(getAnElement()) }
1952+
19481953
override Type getType() { result = this.getElement(0).getType() }
19491954

19501955
override string getAPrimaryQlClass() { result = "Set" }

0 commit comments

Comments
 (0)