CodeQL笔记之基础语法(二)


前言

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


一、查询

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

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

1.select查询子句

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

from /* ... variable declarations ... */
where /* ... logical formula ... */
select /* ... expressions ... */

     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

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

2.查询谓词

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

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

在这里插入图片描述
     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

     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
  }
}

     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

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()

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

8.具体类

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

9.抽象类

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

abstract class SqlExpr extends Expr {
    
    
  ...
}

猜你喜欢

转载自blog.csdn.net/qq_44029310/article/details/127598097