Metadata
ql 脚本开头的一段注释,描述脚本的一些关键信息
Property | Value | Description |
---|---|---|
@description | <text> | 一段描述文字 |
@id | <text> | 多个简短的单词组成的 id,小写,单词间用横杠连接 |
@kind | problem, path-problem | 查询的类型,an alert (@kind problem) or a path (@kind path-problem) |
@name | <text> | 名字 |
@tags | correctness, maintainability, readability, security | These tags group queries together in broad categories to make it easier to search for them and identify them. |
@precision | low, medium, high, very-high | Indicates the percentage of query results that are true positives (as opposed to false positive results). |
@problem.severity | error, warning, recommendation | Defines the level of severity of any alerts generated by a non-security query. |
@security-severity | <score> | Defines the level of severity, between 0.0 and 10.0, for queries with @tags security. |
逻辑连接词
import tutorial
from Person t
where
/* 1 */ t.getHeight() > 150 and
/* 2 */ not t.getHairColor() = "blond" and
/* 3 */ exists (string c | t.getHairColor() = c) and
/* 4 */ not t.getAge() < 30 and
/* 5 */ t.getLocation() = "east" and
/* 6 */ (t.getHairColor() = "black" or t.getHairColor() = "brown") and
/* 7 */ not (t.getHeight() > 180 and t.getHeight() < 190) and
/* 8 */ exists(Person p | p.getAge() > t.getAge()) and
/* 9 */ not t = max(Person p | | p order by p.getHeight()) and
/* 10 */ t.getHeight() < avg(float i | exists(Person p | p.getHeight() = i) | i) and
/* 11 */ t = max(Person p | p.getLocation() = "east" | p order by p.getAge())
select "The thief is " + t + "!"
Code Snippet 1:
find the thief
Class
class Southerner extends Person {
Southerner() { isSouthern(this) }
}
QL 中的类表示一个逻辑属性: 当一个值满足该属性时,它就是该类的成员。这意味着一个值可以在很多个类中ーー属于某个特定的类并不妨碍它也属于其他类
表达式 isSouthern(this)
定义了由类表示的逻辑属性,称为其特征谓词。它使用一个特殊的变量 this,并指示如果谓词 isSouthern(this)
命中,则 Person “ this ” 是
Southerner(南方人)
注意上面 class 中的 Southerner()
是一个特征谓词,并不是构造函数,不会创建任何对象
除了特征谓词,class 中还存在成员谓词,比如 southerner.getAge()
。成员谓词需要显式调用,而且可以很方便地通过逻辑连接词连接起来
递归
假设有一个谓词 parentOf(Person p)
,它会返回 p 的父母
我们可以通过两个特殊符号 * 和 + 来递归调用这个谓词:
- parentOf+(p): 表示调用一次或多次,相当于查询 p 的祖先
- parentOf*(p): 表示调用零次或多次,相当于查询 p 的祖先或者 p 的本身
谓词 Predicate
QL 中的谓词类似一个封装好的 from-where-select 查询结构,便于重复利用。下面是一个例子,isEvalCall 是一个谓词,用来查询所有对 eval 函数的调用:
import python
predicate isEvalCall(Call c, Name name) {
c.getFunc() = name and
name.getId() = "eval"
}
from Call c, Name name
where isEvalCall(c, name) and
c.getLocation().getFile().getRelativePath().regexpMatch("2/challenge-1/.*")
select c, "call to 'eval'."
谓词的结构:
predicate <name>(<variable type>:<variable name>) {}
Note
名称开头必须是小写