代码分析平台CodeQL学习手记(二)
2019-12-24 12:26:53 Author: www.4hou.com(查看原文) 阅读量:325 收藏

代码分析平台CodeQL入门(一)

在上一篇文章中,我们为读者介绍了CodeQL平台相关的基本概念,并演示了如何编写和运行简单的QL程序。在本文中,我们开始为读者介绍一些简单的数据类型,以便为将来的编程工作打好基础。

基本数据类型及其内建函数

现在,我们开始学习QL语言中的基本数据类型,包括整型、浮点型、日期型、布尔型以及字符串类型。需要注意的是,对于QL语言来说,其支持的数据类型都带有相应的内建函数——通俗来说,就是系统已经为我们写好的函数,我们直接拿来就能用了。举例来说,如果我们想求一个整数的绝对值,直接调用内建函数abs()即可,例如-6.abs()。更一般地说,调用某种类型的变量的通用形式为:直接在变量后面加上一个点号,然后加上要调用的内建函数即可。同时,我们还可以通过点号将多个函数串联起来,也就是对变量连续进行多种处理,例如,对于一个整型变量a,先求绝对值,再开平方,我们可以将这个处理过程表示为:a.abs().sqrt()。

读者可能已经发现,在查询控制台中,当我们在变量后面输入点号之后,会自动弹出一个含有该类型的变量所有可能的函数列表,这时,我们可以通过鼠标点选所需的函数,具体如下所示:

1.png

另外,当查询控制台检测到潜在的语法错误后,它会在代码行号左边显示一个红色的“x”号,或者在相应的字符下面显示红色的波浪线。例如,当我们给一个字符串变量赋予一个整数值,并调用绝对值和开平方的函数时,查询控制台就会给出相应的提示:

2.png

字符串类型

字符串类型的变量用来存放以双引号开头和结尾的字符序列,即字符串。例如:

from string s
where s = "hello"
select s

其中,在from语句中,我们定义了一个字符串类型的变量s,然后,我们在where语句中,将字符串”hello”赋值给了变量s,最后,我们在select语句中返回变量s的值。如果在查询控制台运行上述代码的话,运行结果将为:

hello

注意,上面的运行结果中,并没有出现双引号。这是因为,双引号是一个特殊字符:字符串通常使用双引号"…"来表示开始和结束,所以双引号本身不会显示出来。读到这里,读者可能会问:如果字符串本身恰好包含一个"字符的话,那该怎么表示呢?这个时候,就该转义字符\上场了。具体来说,只要在双引号前面加上一个反斜杠,双引号就不再表示字符串的开始或结束位置的指示符,而是表示双引号自身了,具体如下所示:

from string s
where s = "he\"llo"
select s

现在,上述代码的运行结果会变为:

he"llo

您可能还会问:如果要显示表示转义字符的反斜杠的话,该怎么办呢?很简单,只要在反斜杠的前面再加上一个反斜杠就行了。下面列出的是常见的转义字符:

n  \" 表示字符"
n  \\ 表示字符\
n  \n 表示换行符
n  \r 表示回车符
n  \t 表示制表符

同时,QL语言还为字符串类型提供了许多内置的函数,按照官方的说法,就是内置谓词,例如charAt()函数,该函数可以接收一个表示字符串下标的整型参数,并返回指定下标处的字符。准确来说,该函数的返回值的类型仍然是字符串类型,只不过只包含单个字符而已。请看下面的示例代码:

from string s
where s = "hello"
select s.charAt(0)

上述代码的运行结果为:

h

从上面的结果可以看出,字符串元素的下标是从0开始算起的。此外,字符串类型内置的函数有二十多个,这里就不一一介绍了,具体可以访问QL的语言规范(https://help.semmle.com/QL/ql-spec/language.html#built-ins-for-string)。

整型与浮点型

简单来说,整型变量用于保存整数,如306;而浮点型变量则用于保存浮点数,也就是带小数位的数,如3.14。例如:

 from float x, int y
 where x = 3.6 and y = 3
 select x.pow(y)

就本例来说,上述代码实际上就是计算3.6的3次方,运行结果为:

46.656000000000006

同样的,整型和浮点型也内建了许多函数,例如,abs()函数等,并且,它们的大部分函数的名称和作用都是相同的,感兴趣的读者可以参阅QL的语言规范(https://help.semmle.com/QL/ql-spec/language.html#built-ins-for-string)。

日期型

日期型变量用于保存公历表示的时间值和日期值,如年、月、日、时、分、秒以及毫秒等,注意,它们的取值都是整数。其中,表示年的整数的取值范围是从-16777216到16777215,表示月的整数的取值范围为从0到11,表示日的整数的取值范围是从1到31,表示时的整数的取值范围是从0到23,表示分的整数的取值范围是从0到59,表示秒的整数的取值范围是从0到59,表示毫秒的整数的取值范围是从0到999。

下面,我们编写一个查询,来计算从今年十月一到2019年12月18日为止已经过去了多少天了,具体如下图所示:

3.png

运行结果如下所示:

4.png

需要注意的是,上面代码中的"01/10/2019"是一个字符串,而函数toDate()是字符串类型的内置函数,其作用是将指定的字符串转换为日期值。同样的,日期型也提供了许多内置的函数,如getMonth()函数可以用来提取日期值中的月份部分,具体如下所示:

5.png

运行上述代码后,提取到的月份如下所示:

6.png

对于日期型数据来说,除了上面介绍的daysTo()和getMonth()函数外,还有多种函数可以供我们使用,感兴趣的读者可以参阅QL的语言规范(https://help.semmle.com/QL/ql-spec/language.html#built-ins-for-string)。

布尔型

布尔型变量用来存放布尔值,即false(假)或者 true(真)。为了便于读者理解,这里举例说明:

from boolean b
where b = false
select b.booleanNot()

在上面的代码中,我们定义了一个布尔型变量b,并将其赋值为false,最后返回对变量b进行逻辑非操作后的值。上述代码的运行结果为:

true

其中,上面的函数booleanNot()的作用,是执行逻辑非运算,也就是取反:真变假,假变真。这里逻辑变量b原来的值为假(false),取反后,自然就变成真(true)了。接下来,我们再来看看booleanAnd()函数,它能够用来实现一个逻辑值与另一个(通过参数传入的)逻辑值的逻辑与运算:

from boolean b
where b = false
select b.booleanAnd(true)

上述代码的运行结果为:

false

这是因为,只有当两个逻辑值都为真时,其逻辑与运算的结果才为真。下面,我们再来看看用于实现逻辑或运算的函数,即booleanOr()。下面,我们举例说明:

from boolean b
where b = false
select b.booleanOr(true)

与上面的函数相似,它也需要传入一个逻辑值或表达式作为其参数。上述代码的运行结果为:

true

对于逻辑或运算来说,只要参加运算的值中有一个为真,那么,其结果就为真。接下来,我们继续考察用来实现异或运算的函数,即booleanXor()函数,演示代码如下所示:

from boolean b
where b = false
select b.booleanXor(true)

上述示例代码的运行结果为:

true

这是因为,对于异或运算来说,只要两个逻辑值不相等,其结果就为真;否则,其结果为假。最后,我们来看一下将逻辑值转换为字符串的函数:toString()函数,具体代码如下所示:

7.png

运行结果如下所示:

8.png

尽管字面上看,与逻辑值中的假值即false是一样的,但是,实际上它们是完全不同的两种数据类型——这里输出的值是一个字符串。

小结

在上一篇文章中,我们为读者介绍了CodeQL平台相关的基本概念,并演示了如何编写和运行简单的QL程序。在本文中,我们进一步为读者介绍了一些基本的数据类型。在下一篇文章中,我们将为读者详细与代码分析紧密相关的一些数据类型。

备注:本系列文章乃本人在学习CodeQL平台过程中所做的笔记,希望能够对大家有点滴帮助——若果真如此的话,本人将备感荣幸。

参考资料:https://help.semmle.com/


文章来源: https://www.4hou.com/technology/22199.html
如有侵权请联系:admin#unsafe.sh