Predicate
CodeQL
中的Predicates
(谓词)充当类似函数的功能,谓词实际上就是对元组集合的求值操作
QL内置了一些谓词可以直接使用,不需要导入
自定义谓词:
返回结果类型(若谓词无返回值,前面写关键词predicate)
谓词名称(第一个字母小写)
谓词参数
谓词主体
predicate name(type arg)
{
statements
}
注:谓词的参数和返回值的值域都为有限的元组集合,即在谓词主体中要显式声明出来
无返回值:
一般用于数据筛选吧,满足条件的输入才通过
predicate isSmall(int i) {
i in [1 .. 9]
}
有返回值:
将关键字predicate换为返回值的类型,返回值的变量为result
int getSuccessor(int i) {
result = i + 1 and
i in [1 .. 9]
}
在谓词里面,result
可以作为参数传入其他谓词,如下面定义了getAParentOf
这个谓词的”逆“
只需将result
和其他变量的关系表达出来即可
Person getAChildOf(Person p) {
p = getAParentOf(result) # result的parent是p, 即p的child是result
}
多返回值谓词
string getFunc(string action) {
action = "rce" and result = "popen"
or
action = "rce" and result = "system"
or
action = "ssrf" and result = "file_get_contents"
or
action = "ssrf" and result = "curl_exec"
}
getFunc("rce")
返回两个结果popen
、system
getFunc("csrf")
不返回结果
递归谓词
string getANeighbor(string country) {
country = "France" and result = "Belgium"
or
country = "France" and result = "Germany"
or
country = "Germany" and result = "Austria"
or
country = "Germany" and result = "Belgium"
or
country = getANeighbor(result)
}
上面谓词getANeighbor
作的限定关系并没有直接体现对称关系,即x=getANeighbor(y)同时y=getANeighbor(x)
可以使用递归谓词来解决
getANeighbor("Belgium")
返回France
和Germany
谓词种类
可以分成三种谓词:
non-member predicates
member predicates
characteristic predicates
int getSuccessor(int i) { // 1. Non-member predicate
result = i + 1 and
i in [1 .. 9]
}
class FavoriteNumbers extends int {
FavoriteNumbers() { // 2. Characteristic predicate
this = 1 or
this = 4 or
this = 9
}
string getName() { // 3. Member predicate for the class `FavoriteNumbers`
this = 1 and result = "one"
or
this = 4 and result = "four"
or
this = 9 and result = "nine"
}
}
集合绑定
上面说到谓词的参数和返回结果的值域都要是有限的tuple,即谓词只能包含有限数量的元组
如下的谓词编译时就会报错。
/*
Compilation errors:
ERROR: "i" is not bound to a value.
ERROR: "result" is not bound to a value.
ERROR: expression "i * 4" is not bound to a value.
*/
int multiplyBy4(int i) {
result = i * 4
}
/*
Compilation errors:
ERROR: "str" is not bound to a value.
ERROR: expression "str.length()" is not bound to a value.
*/
predicate shortString(string str) {
str.length() < 10
}
可以通过在谓词上使用bindingset
标志,其声明了该谓词的输入绑定到了有限的数据集合
bindingset[x] bindingset[y]
predicate plusOne(int x, int y) {
x + 1 = y
}
from int x, int y
where y = 42 and plusOne(x, y)
select x, y
bindingset[x] bindingset[y]
是or
关系,即x或y是有限的
而bindingset[x, y]
是and
关系,即x和y必须是有限的
bindingset[str, len]
string truncate(string str, int len) {
if str.length() > len
then result = str.prefix(len)
else result = str
}
Last updated
Was this helpful?