• CodeQL笔记之基础语法(二)



    前言

          学习利用CodeQL进行代码审计。基础语法包含一些概念和例子。本文是查询和类的部分。


    一、查询

         查询就是整个QL语言运行后输出的结果。有两种查询类型:

    • 第一种是该模块中定义了select 查询子句
    • 查询谓词,这意味着我们可以在当前模块中定义或者从其他模块中导入

    1.select查询子句

         1)select子句格式如下所示(通常在文件末尾),其中from和where语句部分是可选的。我们可以在from中定义变量,在where中给变量赋值和对查询结果的过滤,最后在select中显示结果。

    from /* ... variable declarations ... */
    where /* ... logical formula ... */
    select /* ... expressions ... */
    
    • 1
    • 2
    • 3

         2)在select语句中还可以使用一些关键字:

    • as关键字,后面跟随一个名字。作用跟SQL中的as相似给个别名,给结果列提供了一个"标签",并允许在后续的select表达式中使用它们。
    • order by关键字,后面跟随一个一个结果列名。作用相当于sql中的order by,用于排序结果,并且在结果列名后可选asc(升序)或desc(降序)关键字。

         3)官方例子如下,第一张图结果返回的是select子句 查询的结果,第二张图加了个排序

    from int x, int y
    where x = 3 and y in [0 .. 2]
    select x, y, x * y as product, "product: " + product
    
    • 1
    • 2
    • 3

    在这里插入图片描述
    在这里插入图片描述

    2.查询谓词

         1)查询谓词是一个非成员谓词,并在最开头使用query作为注解。它返回谓词计算结果的所有元组,下面是一个官方的示例:

    query int getProduct(int x, int y) {
      x = 3 and
      y in [0 .. 2] and
      result = x * y
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述
         2)编写查询谓词相对比编写select子句的好处是你可以在代码的其他部分中调用谓词。例如,我们可以在类中去调用getProduct:

    query int getProduct(int x, int y) {
      x = 3 and
      y in [0 .. 2] and
      result = x * y
    }
    class MultipleOfThree extends int {
      MultipleOfThree() { this = getProduct(_, _) }
    }
    
    from MultipleOfThree m  
    select m
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

         3)这样我们的查询结果就有两个,一个是内置的#select,一个是getProduct
    在这里插入图片描述
    在这里插入图片描述
         4)二者对比之下,select 子句就像一个匿名谓词,后面你不能调用它。在调试代码时向谓词添加查询注释也很有帮助 。这样,您可以显式地看到谓词求值的元组集。

    二、类型

    1.概述

         QL 是一种静态类型语言,因此每个变量都必须有一个声明的类型。在QL中类型是一组值。例如,类型int是整数集。而值可以归属多个集合,也就代表了一个值可以有多种类型。QL 中的类型有基本类型、类、字符类型、类域类型、代数数据类型、类型联合和数据库类型

    2.原始类型

         这些类型内置在QL 中,并且在全局命名空间中始终可用,也与我们正在查询的数据库没有关系。

    • boolean:此类型包含值true和false。
    • float:此类型包含 64 位浮点数,例如6.28 和 -0.618。
    • int:此类型包含 32 位二进制补码整数,例如-1 和 42。
    • string:此类型包含 16 位字符的有限字符串。
    • date:此类型包含日期(和可选的时间)。

    3.类(Classes)

         1)我们可以在CodeQL中定义自己的类型,一种方法定义一个类。
         2)类提供了一种重用和结构化代码的简单方法,例如,你能将相关值分组在一起、在这些值上定义成员谓词、定义子类以重写成员谓词。
         3)QL 中的类不会“创建”新对象,它只是表示一个逻辑属性。如果值满足该逻辑属性,则该值属于特定类。
         4)定义一个类,需要以下参数:

    • class关键字
    • 类的名称。这是一个以大写字母开头的标识符
    • 类通过extends和 / 或instanceof派生类的超类型
    • 类的主体,用大括号括起来

         5)官方案例:

    class OneTwoThree extends int {
      OneTwoThree() { // characteristic predicate
        this = 1 or this = 2 or this = 3
      }
    
      string getAString() { // member predicate
        result = "One, two or three: " + this.toString()
      }
    
      predicate isEven() { // member predicate
        this = 2
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

         6)在CodeQL中,类允许多重继承,但是以下操作是非法的:

    • 不能继承本身
    • 不能继承final类
    • 不能继承不兼容的类型,可以参考:https://codeql.github.com/docs/ql-language-reference/annotations/#annotations-overview

    4.类的主体

         1)类的主体可以包含以下内容:

    • 特征谓词的声明
    • 任意数量的成员谓词声明
    • 任意数量的字段声明

         2)在类中,我们可以使用this来指代类本身。当我们定义类时,该类还会从其父类继承所有非私有成员谓词和字段,我们可以覆盖(override)这些谓词和字段。

    5.特征谓词

         类似于其他语言中类的构造函数,只能定义一个,我们可以在特征谓词中使用this来限制类中可能的值。在上述例子中,OneTwoThree被限制为1-3中的整数。

    6.成员谓词

         这些谓词仅适用于特定类的成员。我们可以在值上调用成员谓词。

    	(OneTwoThree).getAString()
    	// 结果是 One, two or three: 1
    
    • 1
    • 2

    7.字段

         字段是在类的主体中声明的变量,一个类的主题中可以有任意数量的字段声明。我们可以在类中的谓词适用这些变量,用法和this类似,字段必须受限于特征谓词。官方案例:

    class SmallInt extends int {
      SmallInt() { this = [1 .. 10] }
    }
    
    class DivisibleInt extends SmallInt {
      SmallInt divisor;   // declaration of the field `divisor`
      DivisibleInt() { this % divisor = 0 }
    
      SmallInt getADivisor() { result = divisor }
    }
    
    from DivisibleInt i
    select i, i.getADivisor()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

         在这个案例中,先声明了SmallInt divisor并定义了一个divisor字段,将其约束在特征谓词中,然后在成员谓词getADivisor的声明中使用它 。
    在这里插入图片描述

    8.具体类

         上面的例子都是具体类,具体类是通过限制较大类型中的值来定义的。具体类中的值也是超类型交集中的那些值,这些值也满足类的特征谓词。

    9.抽象类

         抽象类使用关键字abstract放在关键字class前来定义。抽象的概念相信在许多其他语言中我们都有接触到(例如java)。抽象类我们又可以叫做元类,它定义其子类的谓词和字段。格式如下:

    abstract class SqlExpr extends Expr {
      ...
    }
    
    • 1
    • 2
    • 3
  • 相关阅读:
    统计学中箱型图的理解
    c++类的初始化
    金融机构在实施敏捷时面临的巨大障碍
    Go 语言基础语法 3
    在模型推理时合并BN和Conv层
    WebFlux+SSE流式传输
    vue3学习(十一)--- v-model
    《MATLAB科研绘图与学术图表绘制从入门到精通》示例:绘制婴儿性别比例饼图
    人生旅途之解锁悉尼
    PAT 1035 插入与归并
  • 原文地址:https://blog.csdn.net/qq_44029310/article/details/127598097