欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

代码分析平台CodeQL学习手记(六)

来源:本站整理 作者:佚名 时间:2020-01-22 TAG: 我要投稿

在前面的文章中,我们通过一个抓小偷的例子,为大家展示了逻辑谓词、连接词和聚合操作的威力。在本文中,我们将通过一个抓纵火犯的例子来复习谓词的知识,并进一步学习类的定义和用法,以及如何覆盖父类的成员谓词。
简介
上一次,我们用QL破获了王冠失窃案,之后我们便获得了QL大侦探的美誉。可是,不久之后,村里又发生了一起案件:村北的庄稼地被人恶意纵火,导致地里的农作物颗粒无收,村民损失惨重。所以,我们奉命找出纵火犯。
现在,我们除了手头上的村民信息之外,还掌握了一条重要线索:村南和村北的村民之间交恶已久,所以,纵火犯很可能就是住在村南的村民。
在破案过程中,我们将进一步介绍如何在QL代码中定义和使用谓词和类。有了它们,不仅可以让我们编写的查询逻辑变得更加易于理解,同时,还有助于简化我们的侦查工作。
缩小包围圈
现在,怀疑对象已经被锁定为一个特定的村民群体,即那些生活在村庄南部的村民。因此,我们可以定义一个新的谓词southern,用于遴选住在村南的村民,这样的话,就不必在所有查询这些村民的代码中加入GetLocation()=“south”这一条件了。谓词southern的定义如下所示:
predicate southern(Person p) {
    p.getLocation() = "south"
}
使用谓词southern(p)时,我们需要提供一个参数p,以便让谓词检查p是否满足条件p.getLocation() = "south",也就是住在村南。
好了,根据上面的例子,我们再次复习一下谓词的定义和分类。我们知道,谓词分为两类:一类是带有返回值的谓词,另一类是没有返回值的谓词。在定义谓词时,首先要注意的是,谓词的名称必须以小写字母开头。另外,上面的这个谓词属于没有返回结果的谓词,定义这种类型的谓词时,需要使用关键字predicate;不过,当需要定义带有返回结果的谓词的时候,需要把这里的关键字predicate替换为返回结果的数据类型。这时,还需要引入了一个新的参数来保存返回结果——特殊变量result。例如,int getAge() {result = ...}便是定义了一个返回整型数据的谓词。
现在,我们就可以利用上面定义的谓词来找出所有住在村南的居民了,具体代码如下所示:
/* 谓词southern的定义如上所示 */
from Person p
where southern(p)
select p

运行结果如下所示:

如您所见,利用谓词的好处是,不仅使得我们的代码的逻辑更加清晰,同时,也能提高编写代码的效率。对于上面的查询代码,from子句表示要考察所有村民(Person p),然后,在where子句中加入了一个限制条件:住在村南的居民(southern(p))。
实际上,除了利用上面的查询来找出考察对象之外,我们还可以自定义一个Southerner类,用它来找出我们的考察对象,也就是住在村南的居民,具体代码如下所示:
class Southerner extends Person {
    Southerner() { southern(this) }
}
对于QL语言来说,可以用类来表示一个逻辑属性:当一个值满足该属性时,它就是类的成员。这意味着一个值可以属于多个类,这其实不难理解,举例来说,3既属于“整数”类,也属于“奇数”类,同时属于“质数”类,等等。
在上面的类的定义中,表达式southern(this)定义了这个类所表示的逻辑属性,我们称这个谓词为这个类的特征谓词。需要注意的是,这个表达式中使用了一个特殊变量this,就这里来耍,该变量表示一个Person类型的值,也就是一个村民;如果this满足southern(this)这一限制条件,那么,this代表的村民就属于Southerner类,也就是居住在村南的村民。
对于熟悉面向对象编程语言的读者来说,会发现特征谓词跟构造函数非常类似。不过,特征谓词并非构造函数,实际上它是一个逻辑属性,并且不创建任何对象。
在QL语言中,我们通常需要根据现有的类(超集)来定义新的类(子集)。 在我们的例子中,Southerner是村民中的一个特殊群体,所以,我们说Southerner(住在村南的村民)类继承自Person(村民)类,换句话说,Southerner是Person的一个子集。
借助于这个类,在列出所有住在村南的居民的时候,相应的代码会变得更加简洁:
from Southerner s
select s
第一句是声明变量,就是住在村南的村民,然后,没有附加任何条件就直接列出这些变量了。完整的代码如下所示:

运行结果如下所示:

通过上面的例子,您可能已经注意到,有些谓词是跟在某些变量后面的,例如p.getAge();而有些则是以参数的形式传递变量,例如southern(p)。这是因为,getAge()是一个定义在类Person中的一个成员谓词(类似于成员函数),也就是说,它是一个只能用于该类中的成员变量的谓词。在定义类时,我们也可定义自己的成员谓词,这一点将在下面看到。相反,谓词southern是单独定义的,不属于任何类。实际上,我们还可以将多个成员谓词串起来完成一系列的操作,例如,p. getage ().sqrt(),这里首先获取村民p的年龄,然后计算年龄的平方根——用起来是不是特别方便啊!
出行管制
在这里,我们还要考虑另一个因素:发生王冠失窃案后,村子里实施了出行管制。案发之前,村民是可以在村子里自由走动的,因此,谓词isAllowedIn(string region) 是适用于任何村民和任何区域的。举例来说,下面的查询代码将会列出所有村民,因为他们都可以去村北:

[1] [2]  下一页

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载