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

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

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

在前面的文章中,我们通过一个抓纵火犯的例子来复习了谓词的相关知识,并进一步学习类的定义和用法,以及如何覆盖父类的成员谓词。在本文中,我们将以寻找合法王位继承人为例深入讲解递归的概念与应用。
简介
就在我们连续破获了发生在村庄中的两起案件后,村庄又恢复了往日的平静。然而,就在我们离开村子前的最后一个夜晚,城堡中年老的国王——伟大的Basil国王——在睡梦中与世长辞,村庄再次陷入混乱之中!
为什么会再次陷入混乱呢?因为老国王既没结过婚,也没有自己的孩子,所以,没有人知道应该由谁来继承国王的城堡和财产。这时,许多村民都声称自己是国王家族的后裔,是合法的继承人。为此,人们争论不休,鸡犬不宁。
最终,受村民之托,我们决定留在村子里平息这场争论——找到真正的王位继承人。
寻找国王的兄弟姐妹
既然许多村民都声称自己是王室家族的后裔,我们就需要弄清楚他们跟国王到底有没有亲缘关系。当然,这是一项非常艰巨的任务,不过,好在我们手头上已经掌握了村民们许多的数据,同时,我们还获得了一份名单,上面记录了村里所有的父母及其子女之间的关系。
为了深入了解国王及其家世,我们开始进入城堡查找相应的线索,最终找到了一些古老的家谱。掌握这条重要的线索后,我们立刻查询现有的数据库中,看看国王家族中是否还有人健在。
为此,我们可以借助于一个谓词:parentOf(Person p)。它的作用是,输入一个表示村民的变量p,该谓词就会返回该村民的父母。例如,通过它,我们可以将所有村民p与其父母一起列出:
from Person p
select parentOf(p) + " is a parent of " + p
运行结果如下所示:

如您所见,这里返回的信息太多了,如果通过人工方式进行搜索的话,那就太费时费力了。所以,我们打算编写了一个QL查询来查找国王的继承人。
尽管国王膝下并没有子女,但是,也许他还有兄弟姐妹健在。为此,我们可以编写一个查询,来查找国王的兄弟姐妹。很明显,这里要查找的人,就是除了国王本人之外,跟国王同父同母的村民,具体代码如下所示:
from Person p
    where parentOf(p) = parentOf("King Basil") and
    not p = "King Basil"
select p
上面的代码的运行结果如下所示:

如您所见,确实是有兄弟姐妹的!不过,既然国王年事已高,他的同胞们肯定也不小了,所以,我们需要考察他们是否还健在。为了完成这项任务,我们可以编写一个词,即isDeceased(),让它来判断某人是否已经离世。
下面,我们就借助谓词isDeceased()来考察国王的兄弟姐妹是否还健在,具体的代码如下所示:
from Person p
where parentOf(p) = parentOf("King Basil") and
    not p = "King Basil"
    and not p.isDeceased()
select p
下面是上述代码的运行结果:

不幸的是,Basil国王的兄弟姐妹都已经不在人世了——上面没有返回任何结果。既然老国王同辈的亲属已经不在了,我们就需要进一步调查还有没有晚辈的亲属。为此,我们可以定义一个谓词childOf(),用来返回某人的子女。我们知道,当且仅当村民p是某人的父母时,某人才是村民p的子女。所以,在定义谓词childOf()时,我们可以借助于前面介绍过的谓词parentOf(),具体如下所示:
Person childOf(Person p) {
    p = parentOf(result)
}
对于上面的定义,我们可以这样理解:遍历所有村民,把符合p = parentOf(result)条件的村民作为返回值。当然,我们也可用result =
好了,下面我们利用谓词childOf()来编写一个查询,看看国王的兄弟姐妹是否有后代:
from Person p
where parentOf(p) = parentOf("King Basil") and
    not p = "King Basil"
select childOf(p)
上面的代码的运行结果如下所示:

如您所见,这里的查询没有返回任何结果,这表明国王的兄弟姐妹们并没有后代。既然国王的近亲没有后代,那么接下来,我们要做的事情就是调查老国王远亲是否还健在,或者是否有后代。
寻找国王的远亲
到目前为止,事情好像变得越来越复杂了。为了找到国王的所有亲戚,我们想要定义一个谓词relativeOf(Person p),以便帮忙找出某人的所有亲属。
不过,在编写这个谓词之前,需要对亲属关系下一个精确地定义:如果两个人有共同的祖先,他们就是亲属关系。
为此,我们又引入一个共同祖先的关系。这时,我们可以定义一个谓词ancestorOf(Person p),用来找出某人p的所有祖先。当然,某人p的祖先可以是p的父辈,或者p的父辈的父辈,或者p的父辈的父辈的父辈,依此类推。不过,如果这样做的话,我们就会得到一个无穷无尽的父辈名单。很明显,我们必须寻找一个更可行的方法。
思考良久,我们终于想到,如果把问题重新表述一下,就能帮我们找到答案。也就是说,这里所说的祖先,要么是某人的父母,要么是已知为某人祖先的人的父母。好了,下面我们将上面的话翻译成QL语言,具体如下所示:
Person ancestorOf(Person p) {
    result = parentOf(p) or

[1] [2] [3]  下一页

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