codeQL静态分析

参考文档:https://www.cnblogs.com/Cl0ud/p/15803314.html

https://www.cnblogs.com/hac425/p/14556110.html

https://www.freebuf.com/articles/web/283795.html

官方文档:https://codeql.github.com/codeql-standard-libraries/cpp/

codeql功能

把源代码转化成一个可查询的数据库,通过 Extractor 模块对源代码工程进行关键信息分析提取,构成一个关系型数据库,codeql的处理对象并不是源代码本身,而是中间生成的AST抽象语法树数据库,后续查询操作都在这个数据库中进行

项目编译

databases栏加载test数据库

在/ql/cpp/ql/src下创建一个test.ql来编写ql查询语句

1
2
3
4
5
6
7
8
9
#创建数据库
codeql database create databaseName --source-root=D:/xxljob --language=java

#更新数据库
codeql database upgrade databaseName

#执行扫描规则
codeql database analyze databasePath codeql-repo/java --format=csv --output=result.csv
#eg:codeql database analyze ./libtiff1_dbjob /root/Codeql/ql/codeql/cpp/ql/src/Security/CWE --format=csv --output=result.csv

codeql语法

1
2
3
4
import cpp
from FunctionCall fc
where fc.getTarget().getName().matches("cancel%")
select fc.getEnclosingFunction(), fc //fc.getEnclosingFunction() 获取包含该调用(cancel开头)的函数

递归

找到宏变量MAX_LENGTH的函数调用链

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <stdio.h>
#include <string.h>


#define BUFFER_SIZE 64
#define MAX_LENGTH 100


int printAndReturnLength(const char *str) {
char buffer[BUFFER_SIZE];


strncpy(buffer, str, BUFFER_SIZE - 1);
buffer[BUFFER_SIZE - 1] = '\0';


printf("String (up to %d chars): %s\n", BUFFER_SIZE - 1, buffer);


size_t length = strlen(str);
return (length > MAX_LENGTH) ? MAX_LENGTH : length;
}

int print(const char *str) {
char buffer[BUFFER_SIZE];


strncpy(buffer, str, BUFFER_SIZE - 1);
buffer[BUFFER_SIZE - 1] = '\0';


printf("String (up to %d chars): %s\n", BUFFER_SIZE - 1, buffer);


size_t length = strlen(str);
return (length > MAX_LENGTH) ? MAX_LENGTH : length;
}

void callPrintAndReturnLength(const char *str) {
int length = printAndReturnLength(str);


printf("Length of the string (up to %d): %d\n", MAX_LENGTH, length);


if (length > MAX_LENGTH) {
printf("Warning: String length exceeds the assumed maximum length of %d.\n", MAX_LENGTH);
}
}



void mainFunction(const char *str) {
printf("Entering mainFunction\n");



callPrintAndReturnLength(str);
print(str);



printf("Exiting mainFunction\n");
}

int main() {

char testString[MAX_LENGTH + 1] = "Hello, Nested Function Calls with Macros!";

testString[MAX_LENGTH] = '\0';


mainFunction(testString);



return 0;
}

./codeql database create demo_db –language=cpp –source-root=demo/ -c “gcc demo.c -o demo”

用两个谓词封装方法

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
import cpp

predicate functionUsesMacro(Function f) {
exists(MacroInvocation mi |
mi.getMacroName() = "BUFFER_SIZE" and
mi.getEnclosingFunction() = f
)
}

predicate callsChain(Function callee, Function caller) {
// Base case: caller calls the callee directly
exists(FunctionCall fc |
fc.getTarget() = callee and
fc.getEnclosingFunction() = caller
) or
// Recursive case: continue tracing further up the call chain
exists(Function intermediate |
callsChain(callee, intermediate) and
exists(FunctionCall fc2 |
fc2.getTarget() = intermediate and
fc2.getEnclosingFunction() = caller
)
)
}

from Function start, Function caller
where
functionUsesMacro(start) and
(
caller = start or
callsChain(start, caller)
)
select caller, "Function in the chain."

最后以树结构返回,上面的函数调用下面的函数


codeQL静态分析
https://j1ya-22.github.io/2025/01/09/codeQL静态分析/
作者
j1ya
发布于
2025年1月9日
许可协议