AST-Framework 产品的白盒工具在进行代码分析之前,需要做一些前置的数据采集用于后续项目基本信息的输出,包括:项目使用的编程语言、项目使用的开发框架、代码行数等信息。经过调研,发现了一款成熟度很高的代码统计工具 Tokei,本文将重点介绍如何在 AST-Framework 产品的 sast-plugin 插件中集成 Tokei,实现项目的代码统计。
Tokei 官方文档及用法
Tokei 是一个用于统计代码文件数据的开源工具,通过 Tokei 可以查看代码仓库中文件的数量、文件总行数、代码行数、注释行数和空行数量。Tokei 从2015年开源至今,项目已经非常成熟,拥有 7k 的star,支持 217 种语言、统计结果准确度、统计速度等指标都非常优秀,下面介绍 tokei 的基本用法。
安装方法
MacOS 通过 brew install tokei
命令安装 tokei 工具,然后执行 tokei <dir>
获取<dir>目录中代码文件的统计数据,包括:每种语言的文件数、总行数、代码行数、评论行数和空行数。
更多操作系统的安装方法及手动安装方法请访问官方文档🔗
配置文件
Tokei 的配置文件为tokei.toml
或 .tokeirc
,默认从执行tokei命令的目录、用户的HOME目录或配置文件目录中搜索并使用配置文件,搜索顺序为从左到右。配置文件格式如下:1
2
3
4
5
6
7
8# The width of the terminal output in columns.
columns = 80
# Sort languages based on the specified column.
sort = "lines"
# If set, tokei will only show the languages in `types`.
types = ["Python"]
# Any doc strings (e.g. `"""hello"""` in python) will be counted as comments.
treat_doc_strings_as_comments = true
使用方法
基本用法
1 | USAGE: |
查看特定项目的代码文件统计数据
用法:tokei <target code dir>
1 | $ tokei . |
查看多个项目的代码文件统计数据
用法:tokei <dir1> <dir2> <dir3>
或 tokei <dir1>,<dir2>,<dir3>
1 | $ tokei AstApi AstSpy |
查看排除特定目录/文件后的代码文件统计数据
很多时候我们并不需要统计一些类型的文件,比如:Java 编译后生成的 .class 文件、Python 运行后创建的 .pyc 文件等,在 git 代码仓库中,可以通过 .gitignore
文件进行排除。
tokei 作为一款成熟的工具,支持复用已有的排除策略,直接排除代码无关或我们不关注的目录/文件,tokei 在扫描时,解析.gitignore
和 .ignore
文件并使用文件中定义的排除策略,此外,也支持通过命令行参数( --exclude
)的方式额外指定排除策略,语法与 gitignore 语法相同。
1 | tokei IastEngine --exclude .classs |
统计结果排序
tokei 默认按照编程语言进行排序,也支持通过 --sort
参数指定排序字段,12.0.0 版本支持的排序字段包括:blanks, code, comments, lines1
tokei ./IastEngine --sort code
查看每个文件的统计数据
tokei 默认输出用户指定目录或文件的代码统计结果,白盒做应用框架预分析时,不仅需要知道项目中使用的语言分布,还需要知道都有哪些文件,方便直接根据特征解析文件,提取使用的框架。我们可以通过--files
参数来返回每个文件的结果,同时拿到语言分析和对应的代码文件路径。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 tokei ./foo --files
=====================================================================================================================
Language Files Lines Code Comments Blanks
=====================================================================================================================
Apache Velocity 19 10018 9558 25 435
---------------------------------------------------------------------------------------------------------------------
./src/site/xdoc/manual/customloglevels.xml.vm 347 340 0 7
---------------------------------------------------------------------------------------------------------------------
XML 584 54251 43766 9010 1475
---------------------------------------------------------------------------------------------------------------------
./log4j-taglib/pom.xml 205 184 20 1
---------------------------------------------------------------------------------------------------------------------
YAML 10 322 284 1 37
---------------------------------------------------------------------------------------------------------------------
./log4j-spring-boot/src/test/resources/application.yml 5 5 0 0
=====================================================================================================================
Total 3083 388247 245182 103556 39509
======================================================================================================================
统计结果输出值文件
tokei 支持将统计结果输出至文件中,目前支持的文件格式包括:json
、yaml
、cbor
,可通过 --output
参数指定输出的数据格式1
2
3 tokei ./foo --output json
tokei ./foo --output yaml
tokei ./foo --output cbor
sast-plugin集成tokei工具
sast-plugin 中只需要调用 tokei 命令,将结果转换为 golang 对象即可,代码示例如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52package statistic
import (
"bytes"
"os/exec"
"gopkg.in/yaml.v3"
)
type CodeStatistic struct {
Total struct {
Blanks int `yaml:"blanks"`
Children struct {
Java []struct {
Name string `yaml:"name"`
Stats struct {
Blanks int `yaml:"blanks"`
Blobs struct {
} `yaml:"blobs"`
Code int `yaml:"code"`
Comments int `yaml:"comments"`
} `yaml:"stats"`
} `yaml:"Java"`
Markdown []struct {
Name string `yaml:"name"`
Stats struct {
Blanks int `yaml:"blanks"`
Blobs struct {
} `yaml:"blobs"`
Code int `yaml:"code"`
Comments int `yaml:"comments"`
} `yaml:"stats"`
} `yaml:"Markdown"`
} `yaml:"children"`
Code int `yaml:"code"`
Comments int `yaml:"comments"`
Inaccurate bool `yaml:"inaccurate"`
Reports []interface{} `yaml:"reports"`
} `yaml:"Total"`
}
func StatisticalCode(codeDir string) (*CodeStatistic, error) {
var stdout, stderr bytes.Buffer
cmd := exec.Command("tokei", codeDir, "--output", "json")
cmd.Stdout = &stdout // 标准输出
cmd.Stderr = &stderr // 标准错误
cmd.Run()
codeStatistic = CodeStatistic{}
yaml.Unmarshal(stdout.Bytes(), &codeStatistic)
return nil
}
相关链接
- https://github.com/XAMPPRocky/tokei
- https://github.com/VulScanSpace/AST-Framework
- https://github.com/VulScanSpace/io.ast.plugins
进击的DevSecOps,持续分享SAST/IAST/RASP的技术原理及甲方落地实践。如果你对 SAST、IAST、RASP方向感兴趣,可以扫描下方二维码关注公众号,获得更及时的内容推送。