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

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

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

在前面的文章中,我们首先为读者展示了如何通过LGTM查询控制台来编写和运行分析JavaScript和TypeScript代码的查询。然后,讲解了CodeQL的JavaScript标准库中用于从文本级别和词法级别分析源代码的常用类及其谓词。在本文中,我们继续讲解CodeQL的JavaScript标准库中的其他类和谓词。
声明与绑定模式
我们知道,变量都是通过声明语句(类DeclStmt)进行声明的,而声明语句主要有三种:var语句(由类VarDeclStmt表示),const语句(由类ConstDeclStmt表示)和let语句(由类LetStmt表示)。并且,每个声明语句都含有一个或多个声明符,具体由类VariableDeclarator表示。
每个声明符由谓词VariableDeclarator.getBindingPattern()返回的绑定模式和VariableDeclarator.getInit()返回的可选初始化表达式组成。
通常情况下,绑定模式就是一个简单的标识符,如var x=42。然而,在ECMAScript2015及其更高的版本中,它也可以是更复杂的模式,如var [x, y] = arr。
实际上,各种绑定模式都是由类BindingPattern及其子类表示的:
· varref:L值位置的简单标识符,例如var x中的x,或x=42中的x
· Parameter:函数或catch子句的参数
· ArrayPattern:数组模式,例如,[x,y]=arr语句中的左边部分
· ObjectPattern:对象模式,例如{x, y: z} = o语句中的左边部分
下面是一个查询示例,它用于查找多次声明同一个变量的声明语句:
import javascript
 
from DeclStmt ds, VariableDeclarator d1, VariableDeclarator d2, Variable v, int i, int j
where d1 = ds.getDecl(i) and
    d2 = ds.getDecl(j) and
    i
下面是上面的代码的运行结果:

由于这个问题很少见,因此,我们只在lgtm.com上的angular/angular.js项目找到了一个含有该问题的实例。
需要注意的是,这里及后面几个查询中都使用了not ... isMinified()。其作用是排除了在压缩型代码中找到的结果。如果我们删除and not ds.getTopLevel().isMinified(),并重新运行该查询,则会报告Meteor/Meteor项目中的压缩型代码中找到的两个结果。
属性
对象字面量中的属性是由类Property表示的,它也是ASTNode的子类,但既不是Expr的子类,也不是STMT的子类。
类Property有两个子类,即ValueProperty和PropertyAccessor类,它们分别表示常规值属性和getter/setter属性。同时,类PropertyAccessor又有两个子类:PropertyGetter和PropertySetter类,它们分别表示getter和setter。
谓词Property.getName()和Property.getInit()用于访问已定义的属性的名称及其初始值。对于PropertyAccessor及其子类来说,可以覆写getInit()使其返回getter/setter函数。
下面,我们将通过一个例子来介绍如何查询属性。在这里,该查询用于查找包含两个同名属性的对象表达式,但不包括压缩型代码中的结果:
import javascript
 
from ObjectExpr oe, Property p1, Property p2, int i, int j
where p1 = oe.getProperty(i) and
    p2 = oe.getProperty(j) and
    i
上述示例的运行结果如下图所示:

我们看到,许多项目都含有带有两个同名属性的对象表达式。
模块
分析JavaScript代码的标准库支持使用ECMAScript2015模块,以及遗留的CommonJS模块和AMD风格的各种模块。其中,类ES2015Module、NodeModule和AMDModule分别用于表示上面所说的这三种类型的模块,并且这它们都继承自公共超类Module。
与模块定义相关的重要成员谓词包括:
· Module.getName():获取模块的名称,注意,它获取的名称只是模块名称的主干部分,而不包括扩展名。
· Module.getAnImportedModule():获取本模块(通过import或require)导入的其他模块。
· Module.getAnExportedSymbol():获取本模块导出的符号的名称。
此外,分析JavaScript代码的标准库还提供了一个Import类,用于处理ECMAScript2015风格的import语句以及CommonJS/AMD风格的require语句;此外,通过该类的成员谓词Import.getImportedModule,还可以访问导入的模块,如果可以静态地确定该模块的话。
名称绑定
为了对名称绑定进行建模,用于处理JavaScript代码的标准库使用了4个概念:作用域、变量、变量声明和变量访问,分别由类Scope、Variable、VarDecl和VarAccess表示。
作用域
在ECMAScript 5中,共有三种作用域:全局作用域(每个程序一个)、函数作用域(每个函数一个)和catch子句作用域(每个catch子句一个)。这三种作用域分别由类GlobalScope、FunctionScope和CatchScope作用域表示。ECMAScript 2015为let-bound变量增加了块作用域,这些作用域也是通过类作用域(Scope)、类表达式作用域(ClassExprScope)和模块作用域(ModuleScope)表示的。
用于表示类作用域的Scope类提供了以下应用编程接口:
· Scope.getScopeElement() 返回指向该作用域的AST节点;对于GlobalScope,尚未定义。
· Scope.getOuterScope()返回该作用域的词法封闭作用域。
· Scope.getAnInnerScope()返回一个词法上嵌套在此作用域内的作用域。
· Scope.getVariable(name)、Scope.getAVariable()返回在该作用域内(隐式或显式)声明的变量。
变量
Variable类可用于对JavaScript程序中的所有变量进行建模,包括全局变量、局部变量和参数(函数和catch子句),无论它们是否显式声明的。
重要的是,不要把变量与其声明搞混了:局部变量可能有多个声明,而全局变量和隐式声明的局部参数变量根本不需要进行声明。

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

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