首页 > 其他分享 >CodeQL学习笔记(2)-QL语法(递归)

CodeQL学习笔记(2)-QL语法(递归)

时间:2024-10-28 09:09:47浏览次数:4  
标签:parent parentOf CodeQL 递归 Person result 谓词 QL

最近在学习CodeQL,对于CodeQL就不介绍了,目前网上一搜一大把。本系列是学习CodeQL的个人学习笔记,根据个人知识库笔记修改整理而来的,分享出来共同学习。个人觉得QL的语法比较反人类,至少与目前主流的这些OOP语言相比,还是有一定难度的。与现在网上的大多数所谓CodeQL教程不同,本系列基于官方文档情景实例,包含大量的个人理解、思考和延伸,直入主题,只切要害,几乎没有废话,并且坚持用从每一个实例中学习总结归纳,再到实例中验证。希望能给各位一点不一样的见解和思路。当然,也正是如此必定会包含一定的错误,希望各位大佬能在评论区留言指正。

CodeQL学习笔记(1)


递归

我们逐渐来理解递归。先设定一个目标--查询国王是否有活着的兄弟姐妹

// 表示p和“King Basil”的父母是相同的,则p是其兄弟姐妹
from Person p 
where 
    parentOf(p) = parentOf("King Basil") and    // parentOf(Person p)返回p的父母
    not p = "King Basil"
    and not p.isDeceased()    // isDeceased()谓词,判断是否死亡
select p
// 没有结果

然后尝试查找这些兄弟姐妹们是否有孩子

根据paretOf定义一个childOf谓词(反逻辑)

Person childOf(Person p){    // 这里的返回值是一个Person类型
    p = paretOf(result)
}
select childOf(p)
// 依旧没有结果
  1. 在QL谓词中,约定result为返回值。

  2. 理解代码:这里有两个身份,p和result,要搞清楚它们间的关系。定义的childOf谓词在这里表示--childOf(p) = result,p的孩子是result。那么在谓词实现中,要把这个逻辑反过来,类似于数学中的反函数的概念,p = parentOf(result),当且仅当 p 是某人的父亲时,某人是 p 的孩子

  3. 在谓词中不一定要在谓词定义中直接写明result = ,也可以把result放到后面来作为一个“已知”变量来表达关系。(引用官方文档:相反,您还可以通过用 result 来“反向”表示 p 和 result 之间的关系。)

再尝试找是否有活着的堂兄弟、堂兄弟的孩子、二表兄弟等……这里面会涉及到非常复杂的关系,最好是能够定义一个谓词列出所有的亲戚relativeOf(Person p):如果两个人拥有同一个祖先,那么他们就是亲戚

如果我们定义一个谓词ancestorOf(Person p),列出某个人所有的祖先,这其中包含它的parent,parent的parent……无穷尽,这里就存在了一个递归的思想。我们可以把祖先的定义进行拆分,分为直接父母和已经确定是祖先的直接父母

对于祖先定义的拆分的理解,如果某人已经被确定是祖先了,那么它的直接父母肯定也是祖先

Person ancestorOf(Person p){
    result = parentOf(p) or
    result = parentOf(ancestorOf(p))
}

下面看一个递归的具体例子

// 列出0-100
int getANumber(){
    result = 0
    or
    result <= 100 and result = getANumber() + 1
}
select getANumber() as number    // 列名为“number”,列名不用加引号

这里需要与传统函数式编程严格区分开,不是按传统编程语言的“从上到下执行”模式。ql中在处理递归时,会根据查询逻辑查找所有满足条件的可能结果。因此,select getANumber() 其实是在寻找 所有可能满足 getANumber() 定义条件的 result 值,而不是只运行一次 getANumber() 函数。

  1. QL 会首先满足 result = 0,这是递归的基础条件。所以getANumber()在没有其他限制的情况下,可以返回 0。
  2. 然后CodeQL 会继续尝试满足其他条件,以找到 所有可能的 result 值。
    • 递归条件result = getANumber() + 1​意味着 QL 还会去找 比 0 大的所有整数结果,直到达到 result = 100 的上限。
    • 例如,在 result = 0 确定之后,递归条件允许 result = 1(通过 result = getANumber() + 1 得到),接着再允许 result = 2,以此类推,直到 100。(可以看成是result <= 100 and result = 1​, result <= 100 and result = 2​……)

闭包

我们把上面的递归ancestorOf(Person p)改写一下

Person getAncestor(){
  result = this.getAParent()
  or
  result = this.getAParent().getAnAncestor()
}

其实它的本质就是不断的在找parent,parent的parent……,在QL里有个概念叫做闭包,简单理解就是对某个类的谓词重复执行的简化,不需要我们再去写复杂的递归谓词。

传递闭包(+)

直接对getParent这个谓词使用传递闭包p.getAParent+(),这里得到的是p的parent、p的parent的parent……,是不包含p自身的,即递归一次或多次(>=1,和正则表达式中+、*的用法一致)。

from Person p 
where p = "Cornelius"
select p.getAParent+() as name    // 找到Cornelius的所有ancestor,getAnAncestor()等价于getAParent+()

自反传递闭包(*)

与传递闭包唯一的差别是包含p本身,递归0次或多次(>=0)

select p.getAParent*() as name

其他详细的递归深入用法等到后期专题再展开。当前学习的目的仅是快速入门。

完善代码

在学习完闭包之后,就可以实现前面我们的需求--找出国王的所有亲戚relativeOf(Person p)

Person relativeOf(Person p){
    parentOf*(p) = parentOf*(result)
    and
    not result = p     // 由于这个具体例子中的国王已经死了,在where中也已经过滤了,所以可以不加。正常来说自反传递闭包需要排除自身
}

from Person p 
where
    not p.isDeceased() and
    p = relativeOf("King Basil")
select p

标签:parent,parentOf,CodeQL,递归,Person,result,谓词,QL
From: https://www.cnblogs.com/xzajyjs/p/18509625

相关文章

  • java+SSM+mysql缴税管理系统70555-计算机毕设 原创毕设选题推荐(免费领源码)
    摘 要随着互联网大趋势的到来,社会的方方面面,各行各业都在考虑利用互联网作为媒介将自己的信息更及时有效地推广出去,而其中最好的方式就是建立网络管理系统,并对其进行信息管理。由于现在网络的发达,缴税管理系统的信息通过网络进行信息管理掀起了热潮,所以针对管理的用户需求......
  • (赠源码)基于python+HTML5+flask+mysql技术的酒店在线系统的设计与实现89223-计算机毕业
    目录1绪论1.1课题背景及意义1.1.1课题背景1.1.2课题意义1.2 研究现状1.2.1国外研究现状1.2.2 国内研究现状2 开发工具和开发平台2.1关键性知识及技术简介2.1.1HTML5介绍2.1.2 Flask框架概述2.2Python简介2.3 开发环境及工具3系统分......
  • Qlik Sense : security rules how to work
    HowsecurityrulesworkIn QlikSenseEnterpriseonWindows youcanusesecurityrulestograntusersaccesstoresourcessuchasappsandstreams.Allsecurityrulesareinclusivebynature,thatis,youalwaysgrantusersaccesstoaresource,youneve......
  • 一次mysql表空间优化记录
    场景:有个订单表,因为是按订单商品拆的数据,所以一个订单号会出现多行的情况。我们为了更新不漏数据(比如某订单删除了商品,但是根据订单号更新时会漏删除这些数据),我们就采用了先通过订单号删除数据,然后再将订单数据导入,插入的数据会有大量和删除的数据重复的数据。采用的是innodb索引......
  • 基于SSM的心理咨询管理管理系统(含源码+sql+视频导入教程+文档+PPT)
    ......
  • ctfshow(171,172,173)--SQL注入--联合注入
    Web171进入靶场,是一个SQL查询界面:审计:查询语句如下:$sql="selectusername,passwordfromuserwhereusername!='flag'andid='".$_GET['id']."'limit1;";语句功能从数据表user中查询username,password两个字段。查询条件是username!='fla......
  • IDEA如何快速复制日志生成sql语句,太妙啦
    前言我们在使用IDEA开发Java应用时,一般来说,是使用springboot+mybatis的框架。同时,开发过程中,遇到BUG在所难免。其中,有一类BUG就是数据库的报错。正常来说,我们本地调试时,都会在日志里面打印出对应的sql日志,但这类日志我们不能直接使用,因为还可能有一些参数在填充,我们得复制所有的......
  • # MySQL 三万字精华总结 + 面试100 问,和面试官扯皮绰绰有余
    MySQL三万字精华总结+面试100问,和面试官扯皮绰绰有余写在之前:不建议那种上来就是各种面试题罗列,然后背书式的去记忆,对技术的提升帮助很小,对正经面试也没什么帮助,有点东西的面试官深挖下就懵逼了。个人建议把面试题看作是费曼学习法中的回顾、简化的环节,准备面试的......
  • 【MySQL】实战篇—应用开发:使用MySQL与编程语言(如Python、Java、PHP等)进行交互
    MySQL是存储和管理数据的强大工具,而编程语言(如Python、Java、PHP等)则用于开发应用程序和处理业务逻辑。将这两者结合起来,可以实现数据的存储、查询、更新和管理,进而构建功能强大的应用程序。2.重要性和实际应用场景在软件开发中,数据库与编程语言的交互至关重要,以下是一些常......
  • 【MySQL】运维篇—MySQL安装与配置:MySQL的安装与初始配置
    安装和配置MySQL是数据库运维的基础,正确的安装和配置可以确保系统的稳定性和安全性。在本节中,将详细介绍如何在不同平台上安装和配置MySQL,包括Windows、Linux(Ubuntu)和macOS。每个示例都将包括详细的步骤和代码注释。1.在Windows上安装与配置MySQL步骤1:下载MySQL安装包访......