文章目录
构建AST语法树
- pycparser解析C代码构建AST语法树;
- pycparser是纯python实现的基于C99的解析器;
- 不使用C标准的头文件,而是自己构建一套虚拟的头文件,在pycparser/utils/fake_libc_include 目录下;
- 在分析C代码时,必须先预处理,比如注释掉标准头文件、size_t不支持的语法等;
- python环境中安装pycparser, pip install pycparser;
编写C代码
如下C代码已经将标准头文件注释;
c
//#include <stdio.h>
//#include <malloc.h> // 内存管理
//#include <string.h> // 字符串的头文件
//#include <math.h>
//#include <ctype.h> // 处理字符的判断
typedef struct {
int size;
union {
int age;
int size;
struct {
int id;
}mem1;
}data;
}Variable;
// 声明一个结构体数组,并初始化
Variable arr[] = {{3, {{100}}}};
int idx = 0;
// 函数定义
void testLauf(){
if(arr[idx].data.mem1.id < 200){
printf("running...");
}
}
分析C代码
基于pycparser 分析该样例C代码,并解析testLauf函数中的if条件内容;
python
from pycparser import c_ast, parse_file
# 构建语法树
ast = parse_file(r"E:\jack.c", use_cpp=True, cpp_path="cpp", cpp_args=["-Ipycparser/utils/fake_libc_include"])
def process_func_def(node):
# 处理函数体
process_compound_or_single(node.body)
def process_compound_or_single(node):
# 遍历{}中的每个语句
for item in node.block_items:
if isinstance(item, c_ast.If):
r = get_expression_text(item.cond)
print("r:", r)
stack = []
#
def get_expression_text(node):
# *****************************
if isinstance(node, c_ast.StructRef):
if node.type == "." and get_expression_text(node.field):
return get_expression_text(node.name) + f".{get_expression_text(node.field)}"
else:
return get_expression_text(node.name)
# *****************************
elif isinstance(node, c_ast.ArrayRef):
return f"{get_expression_text(node.name)}[{get_expression_text(node.subscript)}]"
if hasattr(node, "name"): # isinstance(node, c_ast.ID) and
return node.name
elif hasattr(node, "value"): # isinstance(node, c_ast.Constant) and
return node.value
elif hasattr(node, "op"):
if isinstance(node, c_ast.BinaryOp):
left = get_expression_text(node.left)
right = get_expression_text(node.right)
return f"{left} {node.op} {right}"
# 遍历FileAst 节点的所有的子节点
for node in ast.ext:
if isinstance(node, c_ast.FuncDef):
process_func_def(node)
python代码运行输出r: arr[idx].data.mem1.id < 200
CLang方案
windows系统:
bash
# 安装 MSYS2:https://www.msys2.org/
# 在 MSYS2 终端中:
pacman -Syu
pacman -S --needed base-devel mingw-w64-x86_64-toolchain
# 或单独安装 clang
pacman -S mingw-w64-x86_64-clang mingw-w64-x86_64-clang-analyzer