diff --git a/.coderabbit.yaml b/.coderabbit.yaml new file mode 100644 index 0000000..6fa2926 --- /dev/null +++ b/.coderabbit.yaml @@ -0,0 +1,2 @@ +reviews: + max_files: 300 \ No newline at end of file diff --git a/Benchmark_C_CPP/.gitignore b/Benchmark_C_CPP/.gitignore new file mode 100644 index 0000000..1e08c7d --- /dev/null +++ b/Benchmark_C_CPP/.gitignore @@ -0,0 +1,3 @@ +.vscode/ +*build/ +Debug*/ \ No newline at end of file diff --git a/Benchmark_C_CPP/README.md b/Benchmark_C_CPP/README.md new file mode 100644 index 0000000..0d5cc2b --- /dev/null +++ b/Benchmark_C_CPP/README.md @@ -0,0 +1,111 @@ +# Benchmark_C_CPP +本仓库是 `Codesense` 产线 C/C++ 模块(`Saga` 和 `EasyVet`)的测试组件,可用于评估我方引擎以及相关竞品的分析能力。 + +`Benchmark_C_CPP` 测试组件主要按照被分析程序特征、程序分析能力和应用场景等三方面进行组织,分别划分 `Features`、`Abilities` 和 `Applications` 等三个部分。这三个部分可以看作是相互独立的测试用例集,各有不同的侧重点。 + +> 注意:本测试组件长期维护,根据项目的开发进展实时进行更新。未来还需要将各级标准(如 CWE)考虑进来。 + +## 被分析程序特征(Features) +本部分按被分析程序的特征进行组织。程序的结构具有多样性,例如使用的数据类型多样、控制结构多样、语言特性多样等等,因此对静态分析的影响也不同,需要进一步分类以细化测试用例的设计。 + +### 数据类型(DataType) ++ 数组(Arrays) + - 数据流存入数组的成员后取出 + - 数据流存入数组下标 `A`,取下标 `B` + - 数组中的成员 `A` 和 `B` 为别名 + - 大数组和二维数组中的别名 ++ 浮点(Floats) ++ 结构体(Structs) + - 数据流通过结构体成员进行传播 + - 结构体成员 `A` 和 `B` 存在别名关系,污染源传播到 `A`,`B` 传播到汇聚点 + - 结构体对象的指针 `A` 和 `B` 存在别名关系,通过 `A` 和 `B` 的同一个成员传播数据流 + - 多级嵌套的结构体 ++ 全局变量和静态变量(Global) + - 全局变量和静态变量作为路径的条件 ++ 类型转换(Cast) + +### 可终止性(Termination) ++ 循环(Loop) + - 数据流路径上存在多个大循环(和条件无关) + - 数据流路径上存在多个大循环(和条件有关) + - 当循环满足某一个条件时传播数据流 ++ 递归(Recursion) + +### 约束类型(Constraint) ++ 按位运算约束(Bitwise) ++ 线性运算(Linear) ++ 非线性运算约束(NonLinear) + +### 数据流类型(Dataflow) ++ 显式流(Explicit) ++ 隐式流(Implicit) + +### 复杂语言特性(Language) ++ 智能指针(SmartPtr) ++ lambda 表达式(Lambda) + - lambda表达式引起的调用(路径条件等导致对象或指针取值不同) ++ 函数指针(FuncPtr) + - lambda表达式、std::function、函数指针引起的调用(路径条件等导致对象或指针取值不同) ++ 三目运算符(Ternary) + - 数据流经过三目运算符的分支 ++ 引用(Reference) + - 利用C++引用来构造别名 ++ 构造函数(Constructor) + - 隐式地调用了某些构造函数 + - 隐式地调用了某些析构函数 ++ 指针运算(PointerArith) ++ 异常处理机制(Exception):try-catch 等 ++ 宏定义(Macro) ++ 模板(Template) + +## 程序分析能力(Abilities) +本部分按程序分析引擎中的分析能力进行组织。不同程序分析引擎提供的分析能力具有多样性,例如别名分析、各种敏感性分析等,按照引擎的分析能力对测试用例进行分类可以判断程序分析引擎具备哪些分析能力。 + +### 数据流分析(Dataflow) ++ 别名分析(Aliasing) ++ 常量传播(ConstantProp) + +### 过程间分析(InterProcedure) ++ 标准(Regular) + - 污染源和汇聚点在同一函数 + - 污染源和汇聚点在不同函数 ++ 调用图(CallGraph) ++ 摘要(Summary) ++ 参数(Param) + - 函数的不同参数之间为别名,在调用过程中进行隐式传播 + - 函数参数为指针,函数内修改了指针的值 + +### 敏感性分析(Sensitivity) ++ 流敏感(Flow) ++ 对象敏感(Object) ++ 上下文敏感(Context) + - 数据流路径上经过同一函数的不同调用 + - 数据流的条件经过同一函数的不同调用 ++ 域敏感(Field) ++ 路径敏感(Path) + - 污染源和汇聚点在不同分支,数据流的路径条件满足/冲突 + - 在其中一个分支数据流断开,数据流的路径条件满足/冲突 + +### 环境建模(Env) ++ 标准库(Std) + - 库函数使程序终止,阻止了数据流传播 + - 汇聚点在库函数内(`printf`、`strlen` 等) + - 污染源从库函数返回(`malloc`、`scanf` 等) + - 数据流经过库函数传播(`strcpy` 等) + - 库函数可能引起的路径条件(`strlen` 等) + - 数据流保存入 C++ STL 容器后返回 + - 数学函数的建模引起数据流传播或作为条件(`fabs`、`sin`、`cos`、`sqrt` 等) ++ 第三方库(Third) + - qt 库 + +### 其他分析能力(Others) + +## 应用场景(Applications) +本部分按应用场景进行组织。不同程序分析引擎在不同应用场景下的表现不同,使用不同应用场景下的真实程序可以反应程序分析引擎的真实水平,包括缺陷检测能力、性能等。本部分测试用例均为真实项目,可供测试部门进行使用,待未来进一步完善。 + +## 测试用例命名规范 +测试用例的命名体现各级测试用例的分类名与对测试用例设计思路的描述。例如:`Features_DataType_Array_Cond.c` 表示 `Features-DataType` 目录(命名的前两个单词)下的测试用例,该测试用例的特点是使用了数组(命名的第三个单词),且数组操作出现在路径条件上(命名的第四个单词)。 + +测试用例中,主要存在正例和反例两类函数,这两个函数是进行静态分析的主体。正例函数命名为 `[filename]_good`,反例函数命名为 `[filename]_bad`。正例和反例的设计原则是根据对库博、蜚语等竞品和我方引擎的理解来设计,看怎么样尽可能暴露双方的缺陷。其中,正例的代码运行无缺陷,因此静态分析工具报告的问题都是误报;反例的设计遵循的原则是代码运行有缺陷,因此静态分析工具如果没有报出警告,则是漏报。 + +其它函数命名也遵循类似的原则,比如可以将 source 和 sink 单独提出,添加一个函数外壳,并命名为 `[filename]_source` 和 `[filename]_sink`。 \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Abilities/Dataflow/Abilities_Dataflow_Aliasing_2.c b/Benchmark_C_CPP/src/Abilities/Dataflow/Abilities_Dataflow_Aliasing_2.c new file mode 100644 index 0000000..099b998 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Dataflow/Abilities_Dataflow_Aliasing_2.c @@ -0,0 +1,14 @@ +//#include "benchmark.h" + +void Abilities_Dataflow_Aliasing_2_update(int *ptr1, int *ptr2) { + *ptr1 = 5; + *ptr2 = 0; +} + +int Abilities_Dataflow_Aliasing_2_main() { + int data = 10; + int *aliasPtr = &data; + Abilities_Dataflow_Aliasing_2_update(&data, aliasPtr); + int temp = 10/data; //Sink:CWE369除零错误 + return 0; +} diff --git a/Benchmark_C_CPP/src/Abilities/Dataflow/Abilities_Dataflow_Aliasing_Reference_1.c b/Benchmark_C_CPP/src/Abilities/Dataflow/Abilities_Dataflow_Aliasing_Reference_1.c new file mode 100644 index 0000000..c9e81c0 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Dataflow/Abilities_Dataflow_Aliasing_Reference_1.c @@ -0,0 +1,41 @@ +//指针别名分析 + 流敏感指针分析 +#include "benchmark.h" +void Abilities_Dataflow_Aliasing_Reference_1_good_Snk(int ***p, int ***q) { + if(**p){ + int c = ***q; //NO NPD + }else{ + int a = 1; + **p = &a; + int c = ***q; //NO NPD + } +} + +void Abilities_Dataflow_Aliasing_Reference_1_bad_Snk(int **p, int **q) { + if(*p){ + int c = **q; + }else{ + int a = 1; + *p = &a; + int c = **q; // Sink: 空指针解引用 (Null Pointer Dereference, CWE476) x与y不属于指针别名 + } +} + +int Abilities_Dataflow_Aliasing_Reference_1_good_main() { + int *a = NULL; + int **x = &a; + int **y = &a; + int ***w = &x; + + Abilities_Dataflow_Aliasing_Reference_1_good_Snk(&y, w); + return 0; +} + +int Abilities_Dataflow_Aliasing_Reference_1_bad_main() { + int *a = NULL; //Source: 指针a为null + int *x = a; + int *y = a; + int **w = &x; + Abilities_Dataflow_Aliasing_Reference_1_bad_Snk(&y, w); + return 0; +} + diff --git a/Benchmark_C_CPP/src/Abilities/Dataflow/Abilities_Dataflow_ConstantProp.c b/Benchmark_C_CPP/src/Abilities/Dataflow/Abilities_Dataflow_ConstantProp.c new file mode 100644 index 0000000..3213ddc --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Dataflow/Abilities_Dataflow_ConstantProp.c @@ -0,0 +1,53 @@ +#include "benchmark.h" +#include + +int *Abilities_Dataflow_ConstantProp_source() { + int *data = NULL; // Source: 空指针null + return data; +} + +int Abilities_Dataflow_ConstantProp_sink(int *data) { + return *data; // Sink: 空指针解引用 (Null Pointer Dereference, CWE476) +} + +int Abilities_Dataflow_ConstantProp_good(int *data, int value) { + int a = 10; + + if(value > 0) + a += 5; + else + a -= 5; + + if(a > 20) + Abilities_Dataflow_ConstantProp_sink(data); + + return 0; +} + +int Abilities_Dataflow_ConstantProp_bad(int *data, int value) { + int a = 10; + + if(value > 0) + a += 5; + else + a -= 5; + + if(a > 5) + Abilities_Dataflow_ConstantProp_sink(data); + + return 0; +} + +int Abilities_Dataflow_ConstantProp_good_main() { + int input; + scanf("%d", &input); + int* data = Abilities_Dataflow_ConstantProp_source(); + return Abilities_Dataflow_ConstantProp_good(data, input); +} + +int Abilities_Dataflow_ConstantProp_bad_main() { + int input; + scanf("%d", &input); + int* data = Abilities_Dataflow_ConstantProp_source(); + return Abilities_Dataflow_ConstantProp_bad(data, input); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Abilities/Env/Abilites_Env_Std_Move.cpp b/Benchmark_C_CPP/src/Abilities/Env/Abilites_Env_Std_Move.cpp new file mode 100644 index 0000000..aa418c6 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Env/Abilites_Env_Std_Move.cpp @@ -0,0 +1,49 @@ +#include +#include + +class Resource { +public: + void performTask() { + std::cout << "Performing a critical task." << std::endl; + } +}; + +int Abilites_Env_Std_Move_bad(int param) { + auto resource = std::make_unique(); + auto mayAccessResource = [resource = std::move(resource)](int x) -> bool { //source: resource移动到lambda中 + x = x * 3; + if(x > 0){ + return true; + }else{ + return false; + } + }; + + if (mayAccessResource(param)) { + resource->performTask(); // sink: Null pointer dereference; 因为resource已经被移动到lambda中 + } else { + std::cout << "Access denied or resource not available." << std::endl; + } + + return 0; +} + +int Abilites_Env_Std_Move_good(int param) { + auto resource = std::shared_ptr(); //共享资源,而不会遇到所有权被移动的问题。 + auto mayAccessResource = [resource = std::move(resource)](int x) -> bool { + x = x * 3; + if(x > 0){ + return true; + }else{ + return false; + } + }; + + if (mayAccessResource(param)) { + resource->performTask(); + } else { + std::cout << "Access denied or resource not available." << std::endl; + } + + return 0; +} diff --git a/Benchmark_C_CPP/src/Abilities/Env/Abilites_Env_Std_Vector.cpp b/Benchmark_C_CPP/src/Abilities/Env/Abilites_Env_Std_Vector.cpp new file mode 100644 index 0000000..c9b7a2e --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Env/Abilites_Env_Std_Vector.cpp @@ -0,0 +1,40 @@ +#include +#include + +class Widget { +public: + void doWork() const { + std::cout << "Widget is doing work." << std::endl; + } +}; + +int Abilites_Env_Std_Vector_bad() { + std::vector widgets{new Widget(), nullptr, new Widget()}; // Souce: widgets contains nullptr + + for (auto w : widgets) { + w->doWork(); // Sink: NPD + } + + for(auto& w : widgets) { + delete w; + } + widgets.clear(); + + return 0; +} + +int Abilites_Env_Std_Vector_good() { + std::vector widgets{new Widget(), nullptr, new Widget()}; // Souce: widgets contains nullptr + + for (auto w : widgets) { + if(w) + w->doWork(); // Sink: NPD + } + + for(auto& w : widgets) { + delete w; + } + widgets.clear(); + + return 0; +} diff --git a/Benchmark_C_CPP/src/Abilities/Env/Abilities_Env_MathLib.c b/Benchmark_C_CPP/src/Abilities/Env/Abilities_Env_MathLib.c new file mode 100644 index 0000000..3f074e4 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Env/Abilities_Env_MathLib.c @@ -0,0 +1,105 @@ +#include "benchmark.h" +int Abilities_Env_MathLib_bad0(int* p) +{ + float x, y; + scanf("%f%f", &x, &y); + + if(cos(x) + y > 0.7) { + return *p; // Sink: 空指针解引用 (Null Pointer Dereference, CWE476) + } + return 0; +} + +int Abilities_Env_MathLib_good0(int* p) +{ + float x, y; + scanf("%f", &x); + y = x; + float epsilon = 0.00001f; + if(fabs(x - y) > epsilon) { + return *p; //NO NPD 条件不成立 + } + return 0; +} + +int Abilities_Env_MathLib_bad1(int* p) +{ + double x; + scanf("%lf", &x); + double epsilon = 0.000001; + double y = pow(x, 3); + if (fabs(y - 27) < epsilon) { + return *p; // Sink: 空指针解引用 (Null Pointer Dereference, CWE476) + } + return 0; +} + +int Abilities_Env_MathLib_good1(int* p) +{ + double x; + scanf("%lf", &x); + + double y = pow(x, 4); + if(y < 0.0) { + return *p; //NO NPD 条件不成立 + } + return 0; +} + +int Abilities_Env_MathLib_bad2(int* p) { + double n; + scanf("%lf", &n); + + double sqRoot = sqrt(n); + double epsilon = 0.000001; + if (fabs(sqRoot = 5) < epsilon) { + return *p; // Sink: 空指针解引用 (Null Pointer Dereference, CWE476) + } + return 0; +} + +int Abilities_Env_MathLib_good2(int* p) +{ + double n; + scanf("%lf", &n); + + double sqRoot = sqrt(n); + if (n > 0.0 && sqRoot < 0.0) { + return *p; //NO NPD 条件不成立 + } + return 0; +} + +int Abilities_Env_MathLib_bad3(int* p) +{ + double angle; + scanf("%lf", &angle); + double sinVal = sin(angle); + if(sinVal == 0.5) { + return *p; // Sink: 空指针解引用 (Null Pointer Dereference, CWE476) + } + return 0; +} +int Abilities_Env_MathLib_good3(int* p) +{ + double angle; + scanf("%lf", &angle); + double sinVal = sin(angle); + if(sinVal > 1.0) { + return *p; //NO NPD 条件不成立 + } + return 0; +} + + +int Abilities_Env_MathLib_main() { + int *p = NULL; //Source: 空指针null + Abilities_Env_MathLib_bad0(p); + Abilities_Env_MathLib_good0(p); + Abilities_Env_MathLib_bad1(p); + Abilities_Env_MathLib_good1(p); + Abilities_Env_MathLib_bad2(p); + Abilities_Env_MathLib_good2(p); + Abilities_Env_MathLib_bad3(p); + Abilities_Env_MathLib_good3(p); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Abilities/Env/Abilities_Env_Qt.cpp b/Benchmark_C_CPP/src/Abilities/Env/Abilities_Env_Qt.cpp new file mode 100644 index 0000000..27a2a77 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Env/Abilities_Env_Qt.cpp @@ -0,0 +1,72 @@ +#include "benchmark.h" +#include +#include +#include +void Abilities_Env_QList_good() +{ + int *source = nullptr; + QList list; + list.append(source); + list.append((int*)alloca(100)); + int * source2 = list.back(); + int sink = *source2; // 没有空指针解引用 + (void)sink; +} + +void Abilities_Env_QList_bad() +{ + int *source = nullptr; + QList list; + list.append(source); + int * source2 = list.back(); + int sink = *source2; // 空指针解引用 + (void)sink; +} + +void Abilities_Env_QVector_bad() +{ + QVector vector; + int *source = nullptr; + vector.push_back(source); + int sink = *vector[0]; // 空指针解引用 + (void)sink; +} + +void Abilities_Env_QVector_good() +{ + QVector vector; + int *source = nullptr; + vector.push_back(source); + vector.push_back((int*)alloca(100)); + int sink = *vector[1]; // 空指针解引用 + (void)sink; +} + +void Abilities_Env_QMap_bad() +{ + QMap qmap; + int *source = nullptr; + qmap[0] = source; + int sink = *qmap[0]; // 空指针解引用 + (void)sink; +} + +void Abilities_Env_QMap_good() +{ + QMap qmap; + int *source = nullptr; + qmap[1] = source; + qmap[2] = (int*)alloca(100); + int sink = *qmap[2]; // 没有空指针解引用,qmap[2]不为空 + (void)sink; +} + +void Abilities_Env_Qt_main() +{ + Abilities_Env_QList_good(); + Abilities_Env_QList_bad(); + Abilities_Env_QVector_bad(); + Abilities_Env_QVector_good(); + Abilities_Env_QMap_bad(); + Abilities_Env_QMap_good(); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Abilities/Env/Abilities_Env_Std_Container.cpp b/Benchmark_C_CPP/src/Abilities/Env/Abilities_Env_Std_Container.cpp new file mode 100644 index 0000000..c5f7fd0 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Env/Abilities_Env_Std_Container.cpp @@ -0,0 +1,135 @@ +#include "benchmark.h" +#include +#include +#include +using namespace std; +void Abilities_Env_Std_vector_bad1() +{ + vector container; + int *source = NULL; + int *temp = (int*)malloc(4); + container.push_back(source); + container.push_back(temp); + int sink = *container[0]; // 空指针解引用 + (void)sink; + free(temp); +} +void Abilities_Env_Std_vector_bad2() +{ + vector container; + int *source = NULL; + int* temp = (int*)malloc(4); + container.push_back(source); + container.push_back(temp); + int sink = *container.front(); // 空指针解引用 + (void)sink; + free(temp); +} + + +void Abilities_Env_Std_vector_bad3() +{ + vector container; + int *source = NULL; + int* temp = (int*)malloc(4); + container.push_back(source); + int sink = *container.back(); // 空指针解引用 + (void)sink; + free(temp); +} + +void Abilities_Env_Std_vector_bad4() +{ + vector container; + int *source = NULL; + int* temp = (int*)malloc(4); + container.push_back(source); + container.push_back(temp); + int sink ; + for(auto ptr : container) + { + sink = *ptr; // 空指针解引用 + } + (void)sink; + free(temp); +} + +void Abilities_Env_Std_set_bad() +{ + set container; + int *source = NULL; + int* temp = (int*)malloc(4); + container.insert(source); + container.insert(temp); + int sink ; + for(auto ptr : container) + { + sink = *ptr; // 空指针解引用 + } + (void)sink; + free(temp); +} + +void Abilities_Env_Std_vector_good1() +{ + vector container; + int *source = NULL; + int* temp = (int*)malloc(4); + container.push_back(source); + container.push_back(temp); + int sink = *container[1]; // 没有空指针解引用 + (void)sink; + free(temp); +} + +void Abilities_Env_Std_vector_good2() +{ + vector container; + int *source = NULL; + int* temp = (int*)malloc(4); + container.push_back(source); + container.push_back(temp); + int sink = *container.back(); // 没有空指针解引用 + (void)sink; + free(temp); +} + +void Abilities_Env_Std_map_bad() +{ + map container; + int *source = NULL; + int* temp = (int*)malloc(4); + container[0] = source; + container[1] = source; + container[2] = temp; + int sink = *container[0]; // 空指针解引用 + (void)sink; + free(temp); +} + +void Abilities_Env_Std_map_good() +{ + map container; + int *source = NULL; + int* temp = (int*)malloc(4); + container[0] = source; + container[1] = source; + container[2] = temp; + int sink = *container[2]; // 没有空指针解引用 + (void)sink; + free(temp); +} + + +void Abilities_Env_Std_main() +{ + Abilities_Env_Std_vector_bad1(); + Abilities_Env_Std_vector_bad2(); + Abilities_Env_Std_vector_bad3(); + Abilities_Env_Std_vector_bad4(); + Abilities_Env_Std_vector_good1(); + Abilities_Env_Std_vector_good2(); + Abilities_Env_Std_set_bad(); + Abilities_Env_Std_map_bad(); + Abilities_Env_Std_map_good(); +} diff --git a/Benchmark_C_CPP/src/Abilities/Env/Abilities_Env_Std_Span.cpp b/Benchmark_C_CPP/src/Abilities/Env/Abilities_Env_Std_Span.cpp new file mode 100644 index 0000000..f1689e5 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Env/Abilities_Env_Std_Span.cpp @@ -0,0 +1,37 @@ +#include // Required for std::span +#include +struct A { + explicit A(int& i) : data(&i, 1) { // Initialize data to span over i + } + void foo() const { + data[0]++; // Directly increment the first (and only) element of the span + } + std::span data; // Keep using std::span +}; + +int Abilities_Env_Std_Span_good() { + int i = -1; + A a{i}; // a.data spans over i + i = 0; + a.foo(); // Increments i to 1 + return 1 / i; // Returns 1 since i is now 1 +} + + +struct B { + int* data; // Use a pointer to int instead of std::span + + explicit B(int& i) : data(&i) { // Initialize data to point to i + } + + void foo() const { + (*data)++; // Increment the integer pointed by data + } +}; + +int Abilities_Env_Std_Span_bad() { + int i = -1; + B b{i}; // a.data points to i + b.foo(); // Increments i to 0 + return 1 / i; // dived by zero +} diff --git a/Benchmark_C_CPP/src/Abilities/Env/Abilities_Env_Strcpy.c b/Benchmark_C_CPP/src/Abilities/Env/Abilities_Env_Strcpy.c new file mode 100644 index 0000000..73a6177 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Env/Abilities_Env_Strcpy.c @@ -0,0 +1,49 @@ +#include +#include "benchmark.h" +void Abilities_Env_Strcpy_cond_bad() +{ + char *src = (char*)malloc(1000*sizeof(char)); + //src = "Hello World!"; + scanf("%s",src); + src[999] = '\0'; + char *dest = (char*)malloc(1000*sizeof(char)); + strcpy(dest, src); + int *source = NULL; + if(strlen(src) == 5) + { + source = (int*)alloca(1000); + } + int sink; + if(strlen(dest) != 5 ) + sink = *source; // 当strlen(src) != 5 时,有空指针解引用 + (void)sink; + free(src); + free(dest); +} + +void Abilities_Env_Strcpy_cond_good() +{ + char *src = (char*)malloc(1000*sizeof(char)); + //src = "Hello World!"; + scanf("%s",src); + src[999] = '\0'; + char *dest = (char*)malloc(1000*sizeof(char)); + strcpy(dest, src); + int *source = NULL; + if(strlen(src) == 5) + { + source = (int*)alloca(1000); + } + int sink; + if(strlen(dest) == 5) + sink = *source; // 没有空指针解引用 + (void)sink; + free(src); + free(dest); +} + +int main() +{ + Abilities_Env_Strcpy_cond_bad(); + Abilities_Env_Strcpy_cond_good(); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Abilities/Env/Abilities_Env_Teriminator.c b/Benchmark_C_CPP/src/Abilities/Env/Abilities_Env_Teriminator.c new file mode 100644 index 0000000..6668e27 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Env/Abilities_Env_Teriminator.c @@ -0,0 +1,49 @@ +#include "benchmark.h" + +void Abilities_Env_Teriminator_Wrapper() +{ + exit(1); +} +void Abilities_Env_Teriminator_Inter_good1(int argnum) +{ + int source = 0 ; // divided zero source + if(argnum) // if argnum == 0 + Abilities_Env_Teriminator_Wrapper(); + int sink = 3/source; // divided zero sink, + (void)sink; +} +void Abilities_Env_Teriminator_Inter_bad1(int argnum) +{ + int source = 0 ; // divided zero source + Abilities_Env_Teriminator_Wrapper(); + int sink = 3/source; // divided zero sink + (void)sink; +} + +void Abilities_Env_Teriminator_Intra_bad1(int argnum) +{ + int source = 0 ; // divided zero source + if(argnum) // if argnum == 0 + exit(1); + int sink = 3/source; // divided zero sink, + (void)sink; +} +void Abilities_Env_Teriminator_Intra_good1(int argnum) +{ + int source = 0 ; // divided zero source + exit(1); + int sink = 3/source; // divided zero sink + (void)sink; +} + + + +void Abilities_Env_Teriminator_main() +{ + int x; + scanf("%d",&x); + Abilities_Env_Teriminator_Inter_good1(x); + Abilities_Env_Teriminator_Inter_bad1(x); + Abilities_Env_Teriminator_Intra_good1(x); + Abilities_Env_Teriminator_Intra_bad1(x); +} diff --git a/Benchmark_C_CPP/src/Abilities/Env/Abilities_Env_sink_stdlib.c b/Benchmark_C_CPP/src/Abilities/Env/Abilities_Env_sink_stdlib.c new file mode 100644 index 0000000..3163bda --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Env/Abilities_Env_sink_stdlib.c @@ -0,0 +1,60 @@ +#include "benchmark.h" +#include "string.h" + +void Abilities_Env_sink_stdlib_printf_bad1() +{ + char *source = malloc(100); // malloc + scanf("%s", source); + free(source); // free + printf("%s", source); // use after free(bad) +} + +void Abilities_Env_sink_stdlib_printf_good1() +{ + char *source = malloc(100); // malloc + scanf("%s", source); + printf("%s", source); // use before free(good) + free(source); // free +} + +void Abilities_Env_sink_stdlib_strlen_bad1() +{ + char *source = NULL; + //scanf("%s", &s); + int len = strlen(source); // sink in strlen() + (void)len; +} + +#define SZ 10 + +void Abilities_Env_sink_stdlib_memcpy_bad() +{ + + int i ; + scanf("%d", &i); + char dest[SZ],src[SZ+SZ]; + if(0 + +void Abilities_InterProcedural_Param_3_free(int *param0, int *param1) +{ + free(param0); + + free(param1); //cwe-415, double free。报告点位在这里还是在第18行的函数调用点处,不同的检测工具可能有不同的处理。 +} + +int Abilities_InterProcedural_Param_3_bad_main() +{ + int *ptr; + + ptr = (int *)malloc(sizeof(int)); + + if(ptr == NULL) return -1; + + Abilities_InterProcedural_Param_3_free(ptr, ptr); //cwe-415, double free。报告点位在这里还是在第7行,不同的检测工具可能有不同的处理。 + + return 0; +} + +int Abilities_InterProcedural_Param_3_good_main() +{ + int *ptr0, *ptr1; + + ptr0 = (int *)malloc(sizeof(int)); + + if(ptr0 == NULL) return -1; + + ptr1 = (int *)malloc(sizeof(int)); + + if(ptr1 == NULL) return -1; + + Abilities_InterProcedural_Param_3_free(ptr0, ptr1); + + return 0; +} diff --git a/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_Param_4.c b/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_Param_4.c new file mode 100644 index 0000000..1281796 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_Param_4.c @@ -0,0 +1,43 @@ +int Abilities_InterProcedural_Param_4_divide(int *param0, int *param1) +{ + int tmp; + + *param0 = 0; + + tmp = *param1; + + return 1/tmp; //cwe-369, divide by zero。报告点位在这里还是在第22行的函数调用点处,不同的检测工具可能有不同的处理。 +} + +int Abilities_InterProcedural_Param_4_bad_main() +{ + int data, *ptr0, *ptr1; + + data = 123; + + ptr0 = &data; + + ptr1 = &data; + + data = Abilities_InterProcedural_Param_4_divide(ptr0, ptr1); //cwe-369, divide by zero。报告点位在这里还是在第9行的,不同的检测工具可能有不同的处理。 + + return data; +} + + +int Abilities_InterProcedural_Param_4_good_main() +{ + int data0, data1, *ptr0, *ptr1; + + data0 = 0; + + data1 = 1; + + ptr0 = &data0; + + ptr1 = &data1; + + data0 = Abilities_InterProcedural_Param_4_divide(ptr0, ptr1); + + return data0; +} diff --git a/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_Regular_1.c b/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_Regular_1.c new file mode 100644 index 0000000..faa2de6 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_Regular_1.c @@ -0,0 +1,21 @@ +#include "benchmark.h" +#include + +int *Abilities_InterProcedural_Regular_1_source() { + int *data = 0; // Source: 空指针null + return data; +} + +int Abilities_InterProcedural_Regular_1_sink(int *data) { + return *data; // Sink: 空指针解引用 (Null Pointer Dereference, CWE476) +} + +int Abilities_InterProcedural_Regular_1_bad(int *data) { + int res = Abilities_InterProcedural_Regular_1_sink(data); + return res; +} + +int Abilities_InterProcedural_Regular_1_bad_main() { + int* data = Abilities_InterProcedural_Regular_1_source(); + return Abilities_InterProcedural_Regular_1_bad(data); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_Regular_2.c b/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_Regular_2.c new file mode 100644 index 0000000..decdbe3 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_Regular_2.c @@ -0,0 +1,19 @@ +#include + +int Abilities_InterProcedural_Regular_2_return(int flag) +{ + return flag == 0? 0 : -1; +} + +int Abilities_InterProcedural_Regular_2_bad_main() +{ + int arr[5] = {0, 1, 2, 3, 4}; + + int index, flag; + + scanf("%d", &flag); + + index = Abilities_InterProcedural_Regular_2_return(flag); + + return arr[index]; //cwe-125, out-of-bounds read +} diff --git a/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_Regular_3.c b/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_Regular_3.c new file mode 100644 index 0000000..05125f2 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_Regular_3.c @@ -0,0 +1,22 @@ +#include + +int *Abilities_InterProcedural_Regular_3_return(int flag, int *param0, int *param1) +{ + return flag == 0 ? param0 : param1; +} + + +int Abilities_InterProcedural_Regular_3_bad_main() +{ + int data, flag, *ptr; + + data = 1; + + scanf("%d", &flag); + + ptr = Abilities_InterProcedural_Regular_3_return(flag, (int*)0, &data); //Source, 实参(int*)0 + + *ptr = 2; //Sink, NPD, cwe-476 + + return data; +} diff --git a/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_callGraph_1.c b/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_callGraph_1.c new file mode 100644 index 0000000..318c086 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_callGraph_1.c @@ -0,0 +1,21 @@ +int *Abilities_InterProcedural_callGraph_1_returnNull(int i) +{ + return (int *)0; +} + +int Abilities_InterProcedural_callGraph_1_bad_main() +{ + int data, *ptr; + + int *(*fun)(int); + + data = 2; + + fun = Abilities_InterProcedural_callGraph_1_returnNull; + + ptr = fun(data); + + data = *ptr; + + return data; +} diff --git a/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_callGraph_2.c b/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_callGraph_2.c new file mode 100644 index 0000000..49244da --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_callGraph_2.c @@ -0,0 +1,35 @@ +#include + +int Abilities_InterProcedural_callGraph_2_returnZero() +{ + return 0; +} + +int Abilities_InterProcedural_callGraph_2_returnNegative() +{ + return -1; +} + +int Abilities_InterProcedural_callGraph_2_bad_main() +{ + int arr[5] = {0, 1, 2, 3, 4}; + + int flag, index; + + int (*fptr)(); + + scanf("%d", &flag); + + if(flag == 0) + { + fptr = Abilities_InterProcedural_callGraph_2_returnZero; + } + else + { + fptr = Abilities_InterProcedural_callGraph_2_returnNegative; + } + + index = fptr(); + + return arr[index]; //cwe-125, out-of-bounds read +} diff --git a/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_callGraph_3_addition.cpp b/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_callGraph_3_addition.cpp new file mode 100644 index 0000000..a2662b2 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_callGraph_3_addition.cpp @@ -0,0 +1,7 @@ +#include "Abilities_InterProcedural_callGraph_3_addition.h" + +int Addition::calculate(int i) +{ + return value + i; +} + diff --git a/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_callGraph_3_addition.h b/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_callGraph_3_addition.h new file mode 100644 index 0000000..09c38e0 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_callGraph_3_addition.h @@ -0,0 +1,18 @@ +#ifndef _CG_BASE_H + +#define _CG_BASE_H + +#include "Abilities_InterProcedural_callGraph_3_base.h" + +#endif + +class Addition: public Base +{ + public: + + Addition() = default; + + Addition(int v): Base(v){} + + int calculate(int i) override; +}; diff --git a/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_callGraph_3_base.h b/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_callGraph_3_base.h new file mode 100644 index 0000000..c28e64e --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_callGraph_3_base.h @@ -0,0 +1,25 @@ +#ifndef _CG_BASE_H + +#define _CG_BASE_H + +#endif + +class Base +{ + public: + + Base() = default; + + Base(int v) : value(v) + { + } + + virtual int calculate(int i) = 0; + + virtual ~Base() = default; + + protected: + + int value = 0; +}; + diff --git a/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_callGraph_3_division.cpp b/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_callGraph_3_division.cpp new file mode 100644 index 0000000..192d3be --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_callGraph_3_division.cpp @@ -0,0 +1,7 @@ +#include "Abilities_InterProcedural_callGraph_3_division.h" + +int Division::calculate(int i) +{ + return value / i; +} + diff --git a/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_callGraph_3_division.h b/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_callGraph_3_division.h new file mode 100644 index 0000000..8b31976 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_callGraph_3_division.h @@ -0,0 +1,18 @@ +#ifndef _CG_BASE_H + +#define _CG_BASE_H + +#include "Abilities_InterProcedural_callGraph_3_base.h" + +#endif + +class Division: public Base +{ + public: + + Division() = default; + + Division(int v): Base(v){} + + int calculate(int i) override; +}; diff --git a/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_callGraph_3_main.cpp b/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_callGraph_3_main.cpp new file mode 100644 index 0000000..af424b6 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_callGraph_3_main.cpp @@ -0,0 +1,27 @@ +#include "Abilities_InterProcedural_callGraph_3_base.h" +#include "Abilities_InterProcedural_callGraph_3_addition.h" +#include "Abilities_InterProcedural_callGraph_3_division.h" + +#include + +int Abilities_InterProcedural_callGraph_3_main() +{ + int flag; + + Base *b; + + std::cin >> flag; + + if(flag == 0) + { + b = new Addition(123); + } + else + { + b = new Division(456); + } + + flag = b->calculate(0); + + return flag; +} diff --git a/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_summary_1.c b/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_summary_1.c new file mode 100644 index 0000000..bf44f8f --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/InterProcedural/Abilities_InterProcedural_summary_1.c @@ -0,0 +1,64 @@ +int Abilities_InterProcedural_summary_1_divideByZero(int i) +{ + int mod = i%4; + + return i/mod; +} + +int Abilities_InterProcedural_summary_1_main() +{ + int i, j; + + for(i = 1; i < 100; i++) + { + j = i + 3; + + j = Abilities_InterProcedural_summary_1_divideByZero(j); + } + + Abilities_InterProcedural_summary_1_divideByZero(201); + + Abilities_InterProcedural_summary_1_divideByZero(202); + + Abilities_InterProcedural_summary_1_divideByZero(203); + + Abilities_InterProcedural_summary_1_divideByZero(204); + + Abilities_InterProcedural_summary_1_divideByZero(205); + + Abilities_InterProcedural_summary_1_divideByZero(206); + + Abilities_InterProcedural_summary_1_divideByZero(207); + + Abilities_InterProcedural_summary_1_divideByZero(208); + + Abilities_InterProcedural_summary_1_divideByZero(209); + + Abilities_InterProcedural_summary_1_divideByZero(301); + + Abilities_InterProcedural_summary_1_divideByZero(302); + + Abilities_InterProcedural_summary_1_divideByZero(303); + + Abilities_InterProcedural_summary_1_divideByZero(304); + + Abilities_InterProcedural_summary_1_divideByZero(305); + + Abilities_InterProcedural_summary_1_divideByZero(306); + + Abilities_InterProcedural_summary_1_divideByZero(307); + + Abilities_InterProcedural_summary_1_divideByZero(308); + + Abilities_InterProcedural_summary_1_divideByZero(309); + + + for(; i > 0; i--) + { + j = i + 5; + + j = Abilities_InterProcedural_summary_1_divideByZero(j); + } + + return j; +} diff --git a/Benchmark_C_CPP/src/Abilities/InterProcedural/README.md b/Benchmark_C_CPP/src/Abilities/InterProcedural/README.md new file mode 100644 index 0000000..e69de29 diff --git a/Benchmark_C_CPP/src/Abilities/Others/Other_Crash.cpp b/Benchmark_C_CPP/src/Abilities/Others/Other_Crash.cpp new file mode 100644 index 0000000..f366007 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Others/Other_Crash.cpp @@ -0,0 +1 @@ +static void a() { __builtin_bit_cast(unsigned long long, &a) | 1; } \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Abilities/Others/Others_ConstraintSolve_SymSym_RelOps.c b/Benchmark_C_CPP/src/Abilities/Others/Others_ConstraintSolve_SymSym_RelOps.c new file mode 100644 index 0000000..fcb0370 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Others/Others_ConstraintSolve_SymSym_RelOps.c @@ -0,0 +1,53 @@ +#include "benchmark.h" + +void Others_ConstraintSolve_SymSym_RelOps_good0(int x, int y, int z) +{ + int *r = (int *)0; + if (x == y) + { + if (z > x) + { + if (z < y) // condition: x == y && z > x && z < y + { + *r = 42; // Null Pointer Dereference not reachable + } + } + } +} + +void Others_ConstraintSolve_SymSym_RelOps_good1(int x, int y, int z) { + int *r = (int *)0; + if (x != y) return; // x == y + if (z <= x) return; // z > x + if (z >= y) return; // z < y + // condition: x == y && z > x && z < y + // if use eager garbage-collect, the condition will be empty + *r = 42; // Null Pointer Dereference not reachable + // (void)(x + y + z); // keep the constraints alive. +} + +void Others_ConstraintSolve_SymSym_RelOps_good2(int x, int y, int z) { + int *r = (int *)0; + if (x >= y) return; // x < y + if (y >= z) return; // y < z + y = 10; // symbol $y dies + if (x <= z) return; // x > z + // condition: x < y && y < z && x > z + // if use garbage-collect, the condition may be x > z + *r = 42; // Null Pointer Dereference not reachable +} + +void Others_ConstraintSolve_SymSym_RelOps_good3(int x, int y, int z, int w) { + int *r = (int *)0; + if (w < x) return; // w >= x + if (x < y) return; // x >= y + if (y < z) return; // y >= z + // condition: w >= x && x >= y && y >= z + x = 10; + y = 10; + // both $x and $y die + // if simplifying this system of constraints to w >= z && y >= z, lose w >= z + if (w >= z) return; // w < z + // condition: w >= x && x >= y && y >= z && w < z + *r = 42; // Null Pointer Dereference not reachable +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Abilities/Others/Others_ConstraintSolve_UnionInt.c b/Benchmark_C_CPP/src/Abilities/Others/Others_ConstraintSolve_UnionInt.c new file mode 100644 index 0000000..af0a3cf --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Others/Others_ConstraintSolve_UnionInt.c @@ -0,0 +1,27 @@ +#include "benchmark.h" +#include "stdbool.h" + +struct a +{ + int b; + int c; +}; + +union d +{ + struct a e; +}; + +void Others_ConstraintSolve_UnionInt_good() +{ + union d g = {}; + int *r = (int *)0; + if (-g.e.b && g.e.c) //条件冲突 NO NPD + { + *r = 42; // Null Pointer Dereference + } +} + +int Others_ConstraintSolve_UnionInt_main(){ + Others_ConstraintSolve_UnionInt_good(); +} diff --git a/Benchmark_C_CPP/src/Abilities/Others/README.md b/Benchmark_C_CPP/src/Abilities/Others/README.md new file mode 100644 index 0000000..6724f32 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Others/README.md @@ -0,0 +1,9 @@ +# 约束类型 + +## Range-based solver may not support + +* `Others_ConstraintSolver_UnionInt.c` : 属于CSA求解器会误报的情况,[issue链接](https://github.com/llvm/llvm-project/issues/60026)。(不确定CSA启用Z3 solver选项是否可以避免) +* `Others_ConstraintSolve_SymSym_RelOps.c`: good1中的约束range-based solver无法求解,后面又发现CSA求解器中激进的垃圾回收会导致bug,[good1相关说明](https://github.com/llvm/llvm-project/issues/62215),[good2相关说明](https://discourse.llvm.org/t/range-based-solver-and-eager-symbol-garbage-collection/74670)。(目前修复该bug的PR仍未合并) + +## Crash case +* `Other_Crash.cpp`: https://github.com/llvm/llvm-project/issues/71174 \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Context_Pointer_1.c b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Context_Pointer_1.c new file mode 100644 index 0000000..29eeeb9 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Context_Pointer_1.c @@ -0,0 +1,30 @@ +#include "benchmark.h" +#include + +int *Abilities_Sensitivity_Context_Pointer_Callee(int *p) { + return p; +} + +int Abilities_Sensitivity_Context_Pointer_bad(int a, int b) { + int *x, *y; + x = Abilities_Sensitivity_Context_Pointer_Callee(&a); + y = Abilities_Sensitivity_Context_Pointer_Callee(&b); + return 100 / (*x + *y - 30); +} + +int Abilities_Sensitivity_Context_Pointer_good(int a, int b) { + int *x, *y; + x = Abilities_Sensitivity_Context_Pointer_Callee(&a); + y = Abilities_Sensitivity_Context_Pointer_Callee(&b); + return 100 / (*x + *y - 20); +} + +int Abilities_Sensitivity_Context_Pointer_bad_main() { + int a = 20, b = 10; + return Abilities_Sensitivity_Context_Pointer_bad(a, b); +} + +int Abilities_Sensitivity_Context_Pointer_good_main() { + int a = 20, b = 10; + return Abilities_Sensitivity_Context_Pointer_good(a, b); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Context_Pointer_2.c b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Context_Pointer_2.c new file mode 100644 index 0000000..6498668 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Context_Pointer_2.c @@ -0,0 +1,46 @@ +#include "benchmark.h" +#include + +// The information from the two callsites is merged at the entry so that +// *p and *q are considered to alias in both calling contexts. +int Abilities_Sensitivity_Context_Pointer_Callee_bad(int **p, int **q) { + int *r; + int local = 10; + *p = &local; + r = *q; + return 100 / (20 - *r); +} + +// The information from the two callsites is merged at the entry so that +// *p and *q are considered to alias in both calling contexts. +int Abilities_Sensitivity_Context_Pointer_Callee_good(int **p, int **q) { + int *r; + int local = 10; + *p = &local; + r = *q; + return 100 / (10 - *r); +} + +int Abilities_Sensitivity_Context_Pointer_Caller1_bad() { + int a = 5, b = 20; + int *p1 = &a, *p2 = &b; + return Abilities_Sensitivity_Context_Pointer_Callee_bad(&p1, &p2); +} + +int Abilities_Sensitivity_Context_Pointer_Caller2_bad() { + int a = 5; + int *q1 = &a; + return Abilities_Sensitivity_Context_Pointer_Callee_bad(&q1, &q1); +} + +int Abilities_Sensitivity_Context_Pointer_Caller1_good() { + int a = 5, b = 20; + int *p1 = &a, *p2 = &b; + return Abilities_Sensitivity_Context_Pointer_Callee_good(&p1, &p2); +} + +int Abilities_Sensitivity_Context_Pointer_Caller2_good() { + int a = 5; + int *q1 = &a; + return Abilities_Sensitivity_Context_Pointer_Callee_good(&q1, &q1); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Context_Regular.c b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Context_Regular.c new file mode 100644 index 0000000..0d1ca02 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Context_Regular.c @@ -0,0 +1,31 @@ +#include "benchmark.h" +#include + +// A context-sensitive analysis could accurately recognize the return value +// based on different path conditions, e.g., ret = 10 or ret = 20. However, +// a context-insensitive analysis could only compute a over-approximation of +// the return value, e.g., ret = 10 or 20. +int Abilities_Sensitivity_Context_Regular_Callee(int x) { + if(x > 0) + return 10; + + return 20; +} + +int Abilities_Sensitivity_Context_Regular_bad() { + int n = Abilities_Sensitivity_Context_Regular_Callee(-1); + return 100 / (n - 20); +} + +int Abilities_Sensitivity_Context_Regular_good() { + int n = Abilities_Sensitivity_Context_Regular_Callee(1); + return 100 / (n - 20); +} + +int Abilities_Sensitivity_Context_Regular_bad_main() { + return Abilities_Sensitivity_Context_Regular_bad(); +} + +int Abilities_Sensitivity_Context_Regular_good_main() { + return Abilities_Sensitivity_Context_Regular_good(); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Field_ArrayIndex.c b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Field_ArrayIndex.c new file mode 100644 index 0000000..3939953 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Field_ArrayIndex.c @@ -0,0 +1,54 @@ +#include "benchmark.h" +#include +#include + +int Abilities_Sensitivity_Field_ArrayIndex_bad1(int n) { + int res = 0, arr[5]; + arr[0] = 1; arr[1] = 2; arr[2] = n; arr[3] = 4; arr[4] = 5; + + if (n > 0 && n < 10) { + res = 10 / (arr[2] - 3); + } + + return res; +} + +int Abilities_Sensitivity_Field_ArrayIndex_bad2(int n) { + int res = 0, arr[5]; + arr[0] = 1; arr[1] = 2; arr[2] = 3; arr[3] = 4; arr[4] = 5; + + if (n > 0 && n < 10) { + res = 10 / (arr[2] - 3); + } + + return res; +} + +int Abilities_Sensitivity_Field_ArrayIndex_good(int n) { + int res = 0, arr[5]; + arr[0] = 1; arr[1] = 2; arr[2] = n; arr[3] = 4; arr[4] = 5; + + if (n > 0 && n < 10) { + res = 10 / (arr[4] - 3); + } + + return res; +} + +int Abilities_Sensitivity_Field_ArrayIndex_bad1_main() { + int input; + scanf("%d\n", &input); + return Abilities_Sensitivity_Field_ArrayIndex_bad1(input); +} + +int Abilities_Sensitivity_Field_ArrayIndex_bad2_main() { + int input; + scanf("%d\n", &input); + return Abilities_Sensitivity_Field_ArrayIndex_bad2(input); +} + +int Abilities_Sensitivity_Field_ArrayIndex_good_main() { + int input; + scanf("%d\n", &input); + return Abilities_Sensitivity_Field_ArrayIndex_good(input); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Field_Container.cpp b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Field_Container.cpp new file mode 100644 index 0000000..e00c247 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Field_Container.cpp @@ -0,0 +1,69 @@ +#include "benchmark.h" +#include +#include + +int Abilities_Sensitivity_Field_Container_bad1(int n) { + int res = 0; + std::vector vec; + vec.push_back(1); + vec.push_back(2); + vec.push_back(n); + vec.push_back(4); + vec.push_back(5); + + if (n > 0 && n < 10) { + res = 10 / (vec[2] - 3); + } + + return res; +} + +int Abilities_Sensitivity_Field_Container_bad2(int n) { + int res = 0; + std::vector vec; + vec.push_back(1); + vec.push_back(2); + vec.push_back(3); + vec.push_back(4); + vec.push_back(5); + + if (n > 0 && n < 10) { + res = 10 / (vec[2] - 3); + } + + return res; +} + +int Abilities_Sensitivity_Field_Container_good(int n) { + int res = 0; + std::vector vec; + vec.push_back(1); + vec.push_back(2); + vec.push_back(n); + vec.push_back(4); + vec.push_back(5); + + if (n > 0 && n < 10) { + res = 10 / (vec[4] - 3); + } + + return res; +} + +int Abilities_Sensitivity_Field_Container_bad1_main() { + int input; + scanf("%d\n", &input); + return Abilities_Sensitivity_Field_Container_bad1(input); +} + +int Abilities_Sensitivity_Field_Container_bad2_main() { + int input; + scanf("%d\n", &input); + return Abilities_Sensitivity_Field_Container_bad2(input); +} + +int Abilities_Sensitivity_Field_Container_good_main() { + int input; + scanf("%d\n", &input); + return Abilities_Sensitivity_Field_Container_good(input); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Field_Struct.c b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Field_Struct.c new file mode 100644 index 0000000..11b01e0 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Field_Struct.c @@ -0,0 +1,40 @@ +#include "benchmark.h" +#include + +typedef struct Node { + struct Node *p1; + struct Node *p2; + int data; +} Node; + +int Abilities_Sensitivity_Field_Struct_bad(Node *n, int a) { + n->p1 = n; + n->p2 = NULL; + n->data = a; + return n->p2->data; +} + +int Abilities_Sensitivity_Field_Struct_good(Node *n, int a) { + n->p1 = n; + n->p2 = NULL; + n->data = a; + return n->p1->data; +} + +int Abilities_Sensitivity_Field_Struct_bad_main() { + int input; + scanf("%d\n", &input); + Node *n = (Node *)malloc(sizeof(Node)); + int r = Abilities_Sensitivity_Field_Struct_bad(n, input); + free(n); + return r; +} + +int Abilities_Sensitivity_Field_Struct_good_main() { + int input; + scanf("%d\n", &input); + Node *n = (Node *)malloc(sizeof(Node)); + int r = Abilities_Sensitivity_Field_Struct_good(n, input); + free(n); + return r; +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Flow_1.c b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Flow_1.c new file mode 100644 index 0000000..6ca2445 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Flow_1.c @@ -0,0 +1,42 @@ +//流敏感指针分析 +#include "benchmark.h" +int Abilities_Sensitivity_Flow_1_Snk(int** p) +{ + return **p; // Sink: 空指针解引用 (Null Pointer Dereference, CWE476) +} + +void Abilities_Sensitivity_Flow_1_bad_Src(int ***p) +{ + *p = NULL; //Source: 指针a为null +} + +void Abilities_Sensitivity_Flow_1_good_Src(int ***p) +{ + int x = 1; + int *a = &x; + *p = &a; +} + +int Abilities_Sensitivity_Flow_1_bad_main() +{ + int* a; + int* b; + int** c; + + c = &a; + c = &b; + Abilities_Sensitivity_Flow_1_bad_Src(&c); + int x = Abilities_Sensitivity_Flow_1_Snk(c); +} + +int Abilities_Sensitivity_Flow_1_good_main() +{ + int* a; + int* b; + int** c; + + c = &a; + c = &b; + Abilities_Sensitivity_Flow_1_good_Src(&c); + int x = Abilities_Sensitivity_Flow_1_Snk(c); +} diff --git a/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Flow_Pointer.c b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Flow_Pointer.c new file mode 100644 index 0000000..00a6d78 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Flow_Pointer.c @@ -0,0 +1,44 @@ +#include "benchmark.h" +#include + +int Abilities_Sensitivity_Flow_Pointer_Sink(int** p) +{ + return **p; // Sink: 空指针解引用 (Null Pointer Dereference, CWE476) +} + +int Abilities_Sensitivity_Flow_Pointer_bad() +{ + int a1 = 0; + int* a = &a1; + int* b = NULL; // Source + int** c; + + c = &a; + printf("%p\n", c); + c = &b; + return Abilities_Sensitivity_Flow_Pointer_Sink(c); +} + +int Abilities_Sensitivity_Flow_Pointer_good() +{ + int a1 = 0; + int* a = &a1; + int* b = NULL; // Source + int** c; + + c = &b; + printf("%p\n", c); + c = &a; + + return Abilities_Sensitivity_Flow_Pointer_Sink(c); +} + +int Abilities_Sensitivity_Flow_Pointer_bad_main() +{ + return Abilities_Sensitivity_Flow_Pointer_bad(); +} + +int Abilities_Sensitivity_Flow_Pointer_good_main() +{ + return Abilities_Sensitivity_Flow_Pointer_good(); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Flow_Regular.c b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Flow_Regular.c new file mode 100644 index 0000000..228207b --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Flow_Regular.c @@ -0,0 +1,30 @@ +#include "benchmark.h" +#include + +int Abilities_Sensitivity_Flow_Regular_bad(int x) { + int m = 100, n; + n = 10; + printf("n = %d\n", n); + n = 100 - x; + return m / n; // If x is 100, divide-by-zeo bug is triggered! +} + +int Abilities_Sensitivity_Flow_Regular_good(int x) { + int m = 100, n; + n = 100 - x; + printf("n = %d\n", n); + n = 10; + return m / n; +} + +int Abilities_Sensitivity_Flow_Regular_bad_main() { + int input; + scanf("%d\n", &input); + return Abilities_Sensitivity_Flow_Regular_bad(input); +} + +int Abilities_Sensitivity_Flow_Regular_good_main() { + int input; + scanf("%d\n", &input); + return Abilities_Sensitivity_Flow_Regular_good(input); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Flow_StrongUpdate.c b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Flow_StrongUpdate.c new file mode 100644 index 0000000..435379f --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Flow_StrongUpdate.c @@ -0,0 +1,45 @@ +#include + +typedef struct Node { + int data; + struct Node* next; +} Node; + + +int Abilities_Sensitivity_Flow_StrongUpdate_bad(Node *a, Node *b, Node *c) { + a->next = c; + a->next = b; // strong update + a->next->data = 5; + return 100 / (a->next->data - 5); +} + +int Abilities_Sensitivity_Flow_StrongUpdate_good(Node *a, Node *b, Node *c) { + a->next = c; + a->next->data = 5; + a->next = b; // strong update + return 100 / (a->next->data - 5); +} + +int Abilities_Sensitivity_Flow_StrongUpdate_bad_main() { + Node *a = (Node *) malloc(4); + Node *b = (Node *) malloc(4); + Node *c = (Node *) malloc(4); + int res = Abilities_Sensitivity_Flow_StrongUpdate_bad(a, b, c); + + free(a); + free(b); + free(c); + return res; +} + +int Abilities_Sensitivity_Flow_StrongUpdate_good_main() { + Node *a = (Node *) malloc(4); a->data = 1; + Node *b = (Node *) malloc(4); b->data = 1; + Node *c = (Node *) malloc(4); c->data = 1; + int res = Abilities_Sensitivity_Flow_StrongUpdate_good(a, b, c); + + free(a); + free(b); + free(c); + return res; +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Object_Regular.cpp b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Object_Regular.cpp new file mode 100644 index 0000000..fe4a22e --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Object_Regular.cpp @@ -0,0 +1,46 @@ +#include + +class Obj { +public: + int data; + + Obj(int n) { + data = n; + } +}; + +int Abilities_Sensitivity_Object_Regular_bad1(int n) { + Obj o1(n); + Obj o2(10); + return 100 / (o1.data - 5); +} + +int Abilities_Sensitivity_Object_Regular_bad2(int n) { + Obj o1(n); + Obj o2(5); + return 100 / (o2.data - 5); +} + +int Abilities_Sensitivity_Object_Regular_good(int n) { + Obj o1(n); + Obj o2(10); + return 100 / (o2.data - 5); +} + +int Abilities_Sensitivity_Object_Regular_bad1_main() { + int input; + std::cin >> input; + return Abilities_Sensitivity_Object_Regular_bad1(input); +} + +int Abilities_Sensitivity_Object_Regular_bad2_main() { + int input; + std::cin >> input; + return Abilities_Sensitivity_Object_Regular_bad2(input); +} + +int Abilities_Sensitivity_Object_Regular_good_main() { + int input; + std::cin >> input; + return Abilities_Sensitivity_Object_Regular_good(input); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Path_Cond1.c b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Path_Cond1.c new file mode 100644 index 0000000..fb62504 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Path_Cond1.c @@ -0,0 +1,48 @@ +#include "benchmark.h" + +int *Abilities_Sensitivity_Path_Cond1_source() { + int *data = NULL; //Source: 空指针null + return data; +} + +int Abilities_Sensitivity_Path_Cond1_sink(int *data) { + return *data; // Sink: 空指针解引用 (Null Pointer Dereference, CWE476) +} + +int Abilities_Sensitivity_Path_Cond1_good(int *data, unsigned cond) { + int *data1 = data; + if(cond >= 0) + data1 = Abilities_Sensitivity_Path_Cond1_source(); + int cond1 = cond; + //Source 和 Sink 分支条件存在冲突 + if(cond1 < 0) { + return Abilities_Sensitivity_Path_Cond1_sink(data1); + } + else return *data; +} + +int Abilities_Sensitivity_Path_Cond1_bad(int *data, unsigned cond) { + int *data1 = data; + if(cond >= 0) + data1 = Abilities_Sensitivity_Path_Cond1_source(); + int cond1 = cond; + //Source 和 Sink 分支条件满足 + if(cond1 > 0) { + return Abilities_Sensitivity_Path_Cond1_sink(data1); + } + else return *data; +} + +int Abilities_Sensitivity_Path_Cond1_good_main(int parm) { + int *data = malloc(4); + if(data == NULL) + return 0; + return Abilities_Sensitivity_Path_Cond1_good(data, parm); +} + +int Abilities_Sensitivity_Path_Cond1_bad_main(int parm) { + int *data = malloc(4); + if(data == NULL) + return 0; + return Abilities_Sensitivity_Path_Cond1_bad(data, parm); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Path_Cond2.c b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Path_Cond2.c new file mode 100644 index 0000000..d771e0e --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Path_Cond2.c @@ -0,0 +1,49 @@ +#include "benchmark.h" + +int *Abilities_Sensitivity_Path_Cond2_source() { + int *data = NULL; //Source: 空指针null + return data; +} + +int Abilities_Sensitivity_Path_Cond2_sink(int *data) { + return *data; // Sink: 空指针解引用 (Null Pointer Dereference, CWE476) +} + +int Abilities_Sensitivity_Path_Cond2_bad(int *data, int cond) { + int *data1 = Abilities_Sensitivity_Path_Cond2_source(); + if(cond < 0) //数据流断开 + data1 = data; + int cond1 = cond; + //Source 和 Sink 分支条件满足 + if(cond1 >= 0) { + return Abilities_Sensitivity_Path_Cond2_sink(data1); + } + else return *data; +} + +int Abilities_Sensitivity_Path_Cond2_good(int *data, unsigned cond) { + int *data1 = Abilities_Sensitivity_Path_Cond2_source(); + if(cond >= 0) //数据流断开 + data1 = data; + int cond1 = cond; + //Source 和 Sink 分支条件冲突 + if(cond1 > 0) { + return Abilities_Sensitivity_Path_Cond2_sink(data1); + } + else return *data; +} + + +int Abilities_Sensitivity_Path_Cond2_bad_main(int parm) { + int *data = malloc(4); + if(data == NULL) + return 0; + return Abilities_Sensitivity_Path_Cond2_bad(data, parm); +} + +int Abilities_Sensitivity_Path_Cond2_good_main(int parm) { + int *data = malloc(4); + if(data == NULL) + return 0; + return Abilities_Sensitivity_Path_Cond2_good(data, parm); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Path_Loop_01.c b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Path_Loop_01.c new file mode 100644 index 0000000..c4b9442 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Path_Loop_01.c @@ -0,0 +1,16 @@ +//#issue 15 循环依赖收集 +#include "benchmark.h" + +void Abilities_Sensitivity_Path_Loop_good_01() +{ + int i; + int * data; + data = NULL; + for(i = 0; i < 1; i++) + { + data = (int *)malloc(100*sizeof(int)); + if (data == NULL) {exit(-1);} + free(data); //Source + } + printf("%d",data[0]); // No (Use after free, exit) +} diff --git a/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Path_switch.c b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Path_switch.c new file mode 100644 index 0000000..2584c29 --- /dev/null +++ b/Benchmark_C_CPP/src/Abilities/Sensitivity/Abilities_Sensitivity_Path_switch.c @@ -0,0 +1,30 @@ +#include "benchmark.h" + +void Abilities_Sensitivity_Path_Switch_good(int cond, int* p) +{ + switch(cond) + { + case 1: + p = &cond; + break; + default: + cond = *p; // NO NPD + } +} +void Abilities_Sensitivity_Path_Switch_bad(int cond, int* p) +{ + switch(cond) + { + case 1: + p = &cond; + break; + default: + cond = *p; // Sink: 空指针解引用 (Null Pointer Dereference, CWE476) + } +} + +int Abilities_Sensitivity_Path_Switch_main(){ + int *p = NULL; // Source: 空指针 + Abilities_Sensitivity_Path_Switch_good(1, p); + Abilities_Sensitivity_Path_Switch_bad(0, p); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Abilities/Sensitivity/README.md b/Benchmark_C_CPP/src/Abilities/Sensitivity/README.md new file mode 100644 index 0000000..e69de29 diff --git a/Benchmark_C_CPP/src/Applications/README.md b/Benchmark_C_CPP/src/Applications/README.md new file mode 100644 index 0000000..e69de29 diff --git a/Benchmark_C_CPP/src/Features/Constraint/Features_Constraint_Bitwise.c b/Benchmark_C_CPP/src/Features/Constraint/Features_Constraint_Bitwise.c new file mode 100644 index 0000000..42e7a06 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Constraint/Features_Constraint_Bitwise.c @@ -0,0 +1,25 @@ +//位运算 +#include "benchmark.h" +int Features_Constraint_Bitwise_bad(int* p) +{ + int a; + scanf("%d", &a); + a = a | 1; + if (a) + return *p; // Sink: 空指针解引用 (Null Pointer Dereference, CWE476) + return 0; +} +int Features_Constraint_Bitwise_good(int* p) +{ + int a; + scanf("%d", &a); + if ((a & 1) && ((a & 1) ^ 1)) + return *p; //NO NPD 条件冲突 + return 0; +} + +int Features_Constraint_Bitwise_Expr_main(){ + int *p = NULL; //Source: 空指针null + Features_Constraint_Bitwise_good(p); + Features_Constraint_Bitwise_bad(p); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/Constraint/Features_Constraint_Bitwise_2.c b/Benchmark_C_CPP/src/Features/Constraint/Features_Constraint_Bitwise_2.c new file mode 100644 index 0000000..9d9c773 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Constraint/Features_Constraint_Bitwise_2.c @@ -0,0 +1,75 @@ +#include "benchmark.h" +#include + +//**************************************************************// +// 除零 (Divide By Zero, CWE369) // +//**************************************************************// + +int Features_Constraint_Bitwise_2_source() { + int input; + scanf("%d", &input); + return input; +} + +// division +int Features_Constraint_Bitwise_2_sink(int dividend, int divisor) { + return dividend / divisor; +} + +int Features_Constraint_Bitwise_2_good1(int b) { + int a = 0, c = b - 4; + if(b & 0b10101 > 4) { // The value of b cannot be 4 + a = Features_Constraint_Bitwise_2_sink(b, c); + } + + return a; +} + +int Features_Constraint_Bitwise_2_good2(int b) { + int a = 0, c = b - 4; + if(b < 4) { // The value of b cannot be 4 + a = Features_Constraint_Bitwise_2_sink(b, c); + } + + return a; +} + +// CSA misses such bug!!! +int Features_Constraint_Bitwise_2_bad1(int b) { + int a = 0, c = b - 4; + if(b & 0b10101 > 1) { // The value of b can be 4 + a = Features_Constraint_Bitwise_2_sink(b, c); + } + + return a; +} + +// CSA misses such bug!!! +int Features_Constraint_Bitwise_2_bad2(int b) { + int a = 0, c = b - 4; + if(b > 2 && b < 5) { // The value of b can be 4 + a = Features_Constraint_Bitwise_2_sink(b, c); + } + + return a; +} + +int Features_Constraint_Bitwise_2_good_main1() { + int src = Features_Constraint_Bitwise_2_source(); + return Features_Constraint_Bitwise_2_good1(src); +} + +int Features_Constraint_Bitwise_2_bad_main1() { + int src = Features_Constraint_Bitwise_2_source(); + return Features_Constraint_Bitwise_2_bad1(src); +} + +int Features_Constraint_Bitwise_2_good_main2() { + int src = Features_Constraint_Bitwise_2_source(); + return Features_Constraint_Bitwise_2_good2(src); +} + +int Features_Constraint_Bitwise_2_bad_main2() { + int src = Features_Constraint_Bitwise_2_source(); + return Features_Constraint_Bitwise_2_bad2(src); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/Constraint/Features_Constraint_Condition_Expr.c b/Benchmark_C_CPP/src/Features/Constraint/Features_Constraint_Condition_Expr.c new file mode 100644 index 0000000..c1f22e3 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Constraint/Features_Constraint_Condition_Expr.c @@ -0,0 +1,33 @@ +//条件运算 +#include "benchmark.h" +int Features_Constraint_Condition_Expr_bad(int* p) +{ + int a; + int b; + int c; + scanf("%d%d", &b, &c); + a = b < c ? c : 0; + if (a) + return *p; // Sink: 空指针解引用 (Null Pointer Dereference, CWE476) + return 0; +} +int Features_Constraint_Condition_Expr_good(int* p) +{ + int a; + int b; + int c; + int d; + scanf("%d%d%d", &b, &c, &d); + a = b < c ? c * c - 19323 : 15 + d * d; + if (a == 0) + return *p; //NO NPD 条件冲突 + return 0; +} + + + +int Features_Constraint_Condition_Expr_main(){ + int *p = NULL; //Source: 空指针null + Features_Constraint_Condition_Expr_good(p); + Features_Constraint_Condition_Expr_bad(p); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/Constraint/Features_Constraint_Linear_Arithmetic.c b/Benchmark_C_CPP/src/Features/Constraint/Features_Constraint_Linear_Arithmetic.c new file mode 100644 index 0000000..4698236 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Constraint/Features_Constraint_Linear_Arithmetic.c @@ -0,0 +1,68 @@ +/** 算术运算 +* 乘法、除法、取余、左移、右移 +*/ + +#include "benchmark.h" +int Features_Constraint_Linear_Arithmetic_bad0(int* p) +{ + int a; + scanf("%d", &a); + if(a < 0){ + a = -a; + } + int x = a * 2; + if (x) + return *p; // Sink: 空指针解引用 (Null Pointer Dereference, CWE476) + return 0; +} + +int Features_Constraint_Linear_Arithmetic_bad1(int* p) +{ + int a, b; + scanf("%d %d", &a, &b); + if (a / b == 2 && a % b == 1) + return *p; // Sink: 空指针解引用 (Null Pointer Dereference, CWE476) + return 0; +} + +int Features_Constraint_Linear_Arithmetic_good1(int* p) +{ + int a; + scanf("%d", &a); + if (a % 2 == 0 && a % 2 == 1) + return *p; //NO NPD 条件冲突 + return 0; +} + +int Features_Constraint_Linear_Arithmetic_bad2(int* p) +{ + unsigned int a; + scanf("%u", &a); + unsigned int shifted = (a << 4) >> 4; + + if (shifted == a) + return *p; // Sink: 空指针解引用 (Null Pointer Dereference, CWE476) + return 0; +} + +int Features_Constraint_Linear_Arithmetic_good2(int* p) +{ + unsigned int a; + scanf("%u", &a); + unsigned int shifted = (a << 4) >> 4; + + if (shifted > a) + return *p; //NO NPD 条件冲突 + return 0; +} + + +int Features_Constraint_Linear_Arithmetic_main(){ + int *p = NULL; //Source: 空指针null + Features_Constraint_Linear_Arithmetic_good0(p); + Features_Constraint_Linear_Arithmetic_bad0(p); + Features_Constraint_Linear_Arithmetic_good1(p); + Features_Constraint_Linear_Arithmetic_bad1(p); + Features_Constraint_Linear_Arithmetic_good2(p); + Features_Constraint_Linear_Arithmetic_bad2(p); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/Constraint/Features_Constraint_Linear_Cmp.c b/Benchmark_C_CPP/src/Features/Constraint/Features_Constraint_Linear_Cmp.c new file mode 100644 index 0000000..f05d975 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Constraint/Features_Constraint_Linear_Cmp.c @@ -0,0 +1,37 @@ +#include "benchmark.h" + +int Features_Constraint_Linear_Cmp_bad(int *p, int n) { + if(n < 0 || n > 10) return 0; + + if (n + 1 > n) { + *p = 1; + return *p; + } + + return 0; +} + +int Features_Constraint_Linear_Cmp_good(int *p, int n) { + if(n < 0 || n > 10) return 0; + + if (n > n + 1) { + *p = 1; + return *p; + } + + return 0; +} + +int Features_Constraint_Linear_Cmp_bad_main(){ + int *p = 0; + int a; + scanf("%d", &a); + return Features_Constraint_Linear_Cmp_bad(p, a); +} + +int Features_Constraint_Linear_Cmp_good_main(){ + int *p = 0; + int a; + scanf("%d", &a); + return Features_Constraint_Linear_Cmp_good(p, a); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/Constraint/Features_Constraint_NonLinear_Arithmetic.c b/Benchmark_C_CPP/src/Features/Constraint/Features_Constraint_NonLinear_Arithmetic.c new file mode 100644 index 0000000..7214b00 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Constraint/Features_Constraint_NonLinear_Arithmetic.c @@ -0,0 +1,22 @@ +#include "benchmark.h" +int Features_Constraint_NonLinear_Arithmetic_bad() +{ + int *p = NULL; + int a; + scanf("%d", &a); + int x = a * a; + if (x) + return *p; // Sink: 空指针解引用 (Null Pointer Dereference, CWE476) + return 0; +} + +int Features_Constraint_NonLinear_Arithmetic_good() +{ + int *p = NULL; + int a; + scanf("%d", &a); + int x = a * a; + if (x && p) + return *p; // Sink: 空指针解引用 (Null Pointer Dereference, CWE476) + return 0; +} diff --git a/Benchmark_C_CPP/src/Features/Constraint/Features_Constraint_NonLinear_Float.c b/Benchmark_C_CPP/src/Features/Constraint/Features_Constraint_NonLinear_Float.c new file mode 100644 index 0000000..d1ec79e --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Constraint/Features_Constraint_NonLinear_Float.c @@ -0,0 +1,33 @@ +#include "benchmark.h" + +int Features_DataType_Float_Arithmetic_bad(double d, int *p) { + if (d * d * d * d * d * d > 1.0) { + *p = 1; // Reachable!!! + return *p; + } + + return 0; +} + +int Features_DataType_Float_Arithmetic_good(double d, int *p) { + if (d * d * d * d * d * d > d * d * d * d * d * d + 1.0) { + *p = 1; // Unreachable!!! + return *p; + } + + return 0; +} + +int Features_DataType_Float_Arithmetic_bad_main() { + double input; + int *p = (int *) 0; + scanf("%lf", &input); + return Features_DataType_Float_Arithmetic_bad(input, p); +} + +int Features_DataType_Float_Arithmetic_good_main() { + double input; + int *p = (int *) 0; + scanf("%lf", &input); + return Features_DataType_Float_Arithmetic_good(input, p); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/Constraint/README.md b/Benchmark_C_CPP/src/Features/Constraint/README.md new file mode 100644 index 0000000..e69de29 diff --git a/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Array.cpp b/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Array.cpp new file mode 100644 index 0000000..1ced41f --- /dev/null +++ b/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Array.cpp @@ -0,0 +1,46 @@ +#include +#include + +class Widget { +public: + void doWork() const { + std::cout << "Widget is doing work." << std::endl; + } +}; + +int Features_DataType_Array_bad() { + Widget* widget1 = new Widget(); + Widget* widget2 = nullptr; // Source: nullptr + Widget* widget3 = new Widget(); + + Widget* widgets[] = {widget1, widget2, widget3}; + + // 使用lambda表达式遍历数组 + std::for_each(std::begin(widgets), std::end(widgets), [](Widget* w) { + w->doWork(); // sink: 如果w是nullptr,这里会产生空指针解引用 + }); + + delete widget1; + delete widget3; + + return 0; +} + +int Features_DataType_Array_good() { + Widget* widget1 = new Widget(); + Widget* widget2 = nullptr; + Widget* widget3 = new Widget(); + + Widget* widgets[] = {widget1, widget2, widget3}; + + // 使用lambda表达式遍历数组 + std::for_each(std::begin(widgets), std::end(widgets), [](Widget* w) { + if(w != nullptr) + w->doWork(); + }); + + delete widget1; + delete widget3; + + return 0; +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Array_Cond.c b/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Array_Cond.c new file mode 100644 index 0000000..655f30f --- /dev/null +++ b/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Array_Cond.c @@ -0,0 +1,41 @@ +#include "benchmark.h" + +int Features_DataType_Array_Cond_bad(int n, int *p) { + int a[10] = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19}; + if (n < 0 || n > 9) + return 0; + + if(a[n] == 11) { + *p = a[n]; // Reachable!!! + return *p; + } + + return 0; +} + +int Features_DataType_Array_Cond_good(int n, int *p) { + int a[10] = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19}; + if (n < 0 || n > 9) + return 0; + + if(a[n] == 21) { + *p = a[n]; // Unreachable!!! + return *p; + } + + return 0; +} + +int Features_DataType_Array_Cond_bad_main() { + int input; + int *p = (int *) 0; + scanf("%d", &input); + return Features_DataType_Array_Cond_bad(input, p); +} + +int Features_DataType_Array_Cond_good_main() { + int input; + int *p = (int *) 0; + scanf("%d", &input); + return Features_DataType_Array_Cond_good(input, p); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Cast_Cond.c b/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Cast_Cond.c new file mode 100644 index 0000000..e22949f --- /dev/null +++ b/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Cast_Cond.c @@ -0,0 +1,143 @@ +#include + +int Features_DataType_Cast_Cond_bad0(int t1) +{ + int t2 = t1 + 3; + if (!t2) + { + int *p = (void *)t2; + *p = 1024; // Sink: 空指针解引用 + } +} + +int Features_DataType_Cast_Cond_good0(int t1) +{ + int t2 = t1 * 3; + if (t2) + { + int *p = (void *)t2; + *p = 1024; + } +} + +int Features_DataType_Cast_Cond_bad1(double t1) +{ + int t2 = (int)t1; //整数与浮点数之间的转换 + t2 = t2 + 3; + if (!t2) + { + int *q = (int *)t2; + return *q; // Sink: 空指针解引用 + } +} + +int Features_DataType_Cast_Cond_good1(double t1) +{ + int t2 = (int)t1; + t2 = t2 + 3; + if (t2) + { + int *q = (int *)t2; + return *q; + } +} + +int Features_DataType_Cast_Cond_bad2(int *p) +{ + unsigned x = (unsigned)p; + x = x * 3; + if (!x) + { + int *q = (int *)x; + return *q; // Sink: 空指针解引用 + } +} + +int Features_DataType_Cast_Cond_good2(int *p) +{ + unsigned x = (unsigned)p; + x = x / 2; + if (x) + { + int *q = (int *)x; + return *q; + } +} + +int Features_DataType_Cast_Cond_bad3(int t1) +{ + char *p = (char *)t1; + if (!p) + { + return *p; // Sink: 空指针解引用 + } +} + +int Features_DataType_Cast_Cond_good3(int t1) +{ + char *p = (char *)t1; + if (p) + { + return *p; + } +} + +int Features_DataType_Cast_Cond_bad4(long longValue) +{ + int* p = NULL; ////Source: 空指针null + void *voidPointer = &longValue; // 将long整数地址转换为void指针 + int *intPointer = (int *)voidPointer; // 将void指针转换为int指针 + if(*intPointer + 1> 0){ + return *p; // Sink: 空指针解引用 + } +} + +int Features_DataType_Cast_Cond_good4(long longValue) +{ + int* p = NULL; ////Source: 空指针null + void *voidPointer = &longValue; // 将long整数地址转换为void指针 + int *intPointer = (int *)voidPointer; // 将void指针转换为int指针 + p = intPointer; + if(p){ + return *p; + } +} + +//浮点数到指针的转换 +int Features_DataType_Cast_Cond_bad5(float f) +{ + int* p = NULL; ////Source: 空指针null + int *intPointer = (int *)(*(int *)&f); // 将浮点数f的位模式直接转换为整数指针 + if(*intPointer + 1> 0){ + return *p; // Sink: 空指针解引用 + } +} + +int Features_DataType_Cast_Cond_good5(float f) +{ + int* p = NULL; ////Source: 空指针null + int *intPointer = (int *)(*(int *)&f); // 将浮点数f的位模式直接转换为整数指针 + p = intPointer; + if(p){ + return *p; + } +} + +int Features_DataType_Cast_Cond_bad6(char* data) +{ + int* p = NULL; ////Source: 空指针null + int *intPointer = (int *)data; // 将字符数组的地址转换为整数指针 + if(*intPointer * 100> 0){ + return *p; // Sink: 空指针解引用 + } +} + +int Features_DataType_Cast_Cond_good6(char* data) +{ + int* p = NULL; ////Source: 空指针null + int *intPointer = (int *)data; // 将字符数组的地址转换为整数指针 + p = intPointer; + if(p){ + return *p; + } +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Float_Arithmetic.c b/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Float_Arithmetic.c new file mode 100644 index 0000000..dcda736 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Float_Arithmetic.c @@ -0,0 +1,33 @@ +#include "benchmark.h" + +int Features_DataType_Float_Arithmetic_bad(double d, int *p) { + if (d > 1.0) { + *p = 1; // Reachable!!! + return *p; + } + + return 0; +} + +int Features_DataType_Float_Arithmetic_good(double d, int *p) { + if (d > d) { + *p = 1; // Unreachable!!! + return *p; + } + + return 0; +} + +int Features_DataType_Float_Arithmetic_bad_main() { + double input; + int *p = (int *) 0; + scanf("%lf", &input); + return Features_DataType_Float_Arithmetic_bad(input, p); +} + +int Features_DataType_Float_Arithmetic_good_main() { + double input; + int *p = (int *) 0; + scanf("%lf", &input); + return Features_DataType_Float_Arithmetic_good(input, p); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Float_Cond.c b/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Float_Cond.c new file mode 100644 index 0000000..448dbab --- /dev/null +++ b/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Float_Cond.c @@ -0,0 +1,48 @@ +#include "benchmark.h" +int Features_DataType_Float_Cond_bad0(int* p) +{ + float a; + scanf("%f", &a); + if (a > 0) + return *p; // Sink: 空指针解引用 (Null Pointer Dereference, CWE476) + return 0; +} + +int Features_DataType_Float_Cond_bad1(int* p) +{ + double a; + scanf("%lf", &a); + if (a > 0) + return *p; // Sink: 空指针解引用 (Null Pointer Dereference, CWE476) + return 0; +} + +int Features_DataType_Float_Cond_bad2(int* p) +{ + float x, y; + scanf("%f%f", &x, &y); + + if(x + y > 0.7) { + return *p; // Sink: 空指针解引用 (Null Pointer Dereference, CWE476) + } + return 0; +} + +int Features_DataType_Float_Cond_bad2(int* p) +{ + double x, y; + scanf("%lf%lf", &x, &y); + + if(x + y > 0.7) { + return *p; // Sink: 空指针解引用 (Null Pointer Dereference, CWE476) + } + return 0; +} + + +int Features_DataType_Float_Cond_main(){ + int *p = NULL; //Source: 空指针null + Features_DataType_Float_Cond_bad0(p); + Features_DataType_Float_Cond_bad1(p); + Features_DataType_Float_Cond_bad2(p); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Global_Array.c b/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Global_Array.c new file mode 100644 index 0000000..38f5f15 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Global_Array.c @@ -0,0 +1,41 @@ +#include "benchmark.h" + +int a[10] = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19}; + +int Features_DataType_Array_Cond_bad(int n, int *p) { + if (n < 0 || n > 9) + return 0; + + if(a[n] == 11) { + *p = a[n]; // Reachable!!! + return *p; + } + + return 0; +} + +int Features_DataType_Array_Cond_good(int n, int *p) { + if (n < 0 || n > 9) + return 0; + + if(a[n] == 21) { + *p = a[n]; // Unreachable!!! + return *p; + } + + return 0; +} + +int Features_DataType_Array_Cond_bad_main() { + int input; + int *p = (int *) 0; + scanf("%d", &input); + return Features_DataType_Array_Cond_bad(input, p); +} + +int Features_DataType_Array_Cond_good_main() { + int input; + int *p = (int *) 0; + scanf("%d", &input); + return Features_DataType_Array_Cond_good(input, p); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Global_Cond1.c b/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Global_Cond1.c new file mode 100644 index 0000000..0397aee --- /dev/null +++ b/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Global_Cond1.c @@ -0,0 +1,49 @@ +#include "benchmark.h" +static double Features_DataType_Global_Cond1_Five = 5.00; +int *Features_DataType_Global_Cond1_source() { + int *data = NULL; //Source: 空指针null + return data; +} + +int Features_DataType_Global_Cond1_sink(int *data) { + return *data; // Sink: 空指针解引用 (Null Pointer Dereference, CWE476) +} + +int Features_DataType_Global_Cond1_bad(int *data) { + int *data1; + if(GlobalInt_Zero == 0) + data1 = Features_DataType_Global_Cond1_source(); + else + data1 = data; + if(fabs(GlobalFloat_Five - Features_DataType_Global_Cond1_Five) < 0.00001) + return Features_DataType_Global_Cond1_sink(data1); + else + return 0; +} + +int Features_DataType_Global_Cond1_bad_main() { + int *data = malloc(4); + if(data == NULL) + return 0; + return Features_DataType_Global_Cond1_bad(data); +} + + +int Features_DataType_Global_Cond1_good(int *data, double parm) { + int *data1; + if(GlobalInt_Zero == parm) + data1 = Features_DataType_Global_Cond1_source(); + else + data1 = data; + if(fabs(parm - Features_DataType_Global_Cond1_Five) < 0.00001) + return Features_DataType_Global_Cond1_sink(data1); + else + return 0; +} + +int Features_DataType_Global_Cond1_good_main(double parm) { + int *data = malloc(4); + if(data == NULL) + return 0; + return Features_DataType_Global_Cond1_good(data, parm); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Global_WithCond.c b/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Global_WithCond.c new file mode 100644 index 0000000..c722ea8 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Global_WithCond.c @@ -0,0 +1,39 @@ +#include "benchmark.h" + +int global = 10; + +int Features_DataType_Global_WithCond_bad(int n, int *p) { + if(n > 10 && n < 20) { + if(n > global) { + *p = 10; + return *p; + } + } + + return 0; +} + +int Features_DataType_Global_WithCond_good(int n, int *p) { + if(n > 10 && n < 20) { + if(n < global) { + *p = 10; + return *p; + } + } + + return 0; +} + +int Features_DataType_Global_WithCond_bad_main() { + int input; + int *p = (int *) 0; + scanf("%d", &input); + return Features_DataType_Global_WithCond_bad(input, p); +} + +int Features_DataType_Global_WithCond_good_main() { + int input; + int *p = (int *) 0; + scanf("%d", &input); + return Features_DataType_Global_WithCond_good(input, p); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Global_WithoutCond.c b/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Global_WithoutCond.c new file mode 100644 index 0000000..e56a15f --- /dev/null +++ b/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Global_WithoutCond.c @@ -0,0 +1,37 @@ +#include "benchmark.h" + +int global = 10; + +int Features_DataType_Global_WithoutCond_bad1() { + int c, res = 0; + c = global - 10; + res = 100 / c; + return res; +} + +int Features_DataType_Global_WithoutCond_bad2() { + int c, res = 0, local = 10; + c = local - 10; + res = 100 / c; + return res; +} + +int Features_DataType_Global_WithoutCond_good() { + int c, res = 0; + c = global - 10; + if (c != 0) + res = 100 / c; + return res; +} + +int Features_DataType_Global_WithoutCond_bad1_main() { + return Features_DataType_Global_WithoutCond_bad1(); +} + +int Features_DataType_Global_WithoutCond_bad2_main() { + return Features_DataType_Global_WithoutCond_bad2(); +} + +int Features_DataType_Global_WithoutCond_good_main() { + return Features_DataType_Global_WithoutCond_good(); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Static_WithoutCond.c b/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Static_WithoutCond.c new file mode 100644 index 0000000..9777d41 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/DataType/Features_DataType_Static_WithoutCond.c @@ -0,0 +1,26 @@ +#include "benchmark.h" + +int Features_DataType_Global_WithoutCond_bad1() { + static int val = 10; + int c, res = 0; + c = val - 10; + res = 100 / c; + return res; +} + +int Features_DataType_Global_WithoutCond_good() { + static int val = 10; + int c, res = 0; + c = val - 10; + if (c != 0) + res = 100 / c; + return res; +} + +int Features_DataType_Global_WithoutCond_bad1_main() { + return Features_DataType_Global_WithoutCond_bad1(); +} + +int Features_DataType_Global_WithoutCond_good_main() { + return Features_DataType_Global_WithoutCond_good(); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/DataType/README.md b/Benchmark_C_CPP/src/Features/DataType/README.md new file mode 100644 index 0000000..e69de29 diff --git a/Benchmark_C_CPP/src/Features/Dataflow/Features_Dataflow_Explicit_flows.c b/Benchmark_C_CPP/src/Features/Dataflow/Features_Dataflow_Explicit_flows.c new file mode 100644 index 0000000..1e4dfa5 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Dataflow/Features_Dataflow_Explicit_flows.c @@ -0,0 +1,49 @@ +#include "benchmark.h" +#include + +//**************************************************************// +// 除零 (Divide By Zero, CWE369) // +//**************************************************************// + +int Features_Dataflow_Explicit_flows_source() { + int input; + scanf("%d", &input); + return input; +} + +// division +int Features_Dataflow_Explicit_flows_sink(int dividend, int divisor) { + return dividend / divisor; +} + +int Features_Dataflow_Explicit_flows_good(int b) { + int a = 0, c; + switch (b) { + case 1: a = b / 2; break; + case 4: c = b - 3; a = Features_Dataflow_Explicit_flows_sink(b, c); break; + default: break; + } + + return a; +} + +int Features_Dataflow_Explicit_flows_bad(int b) { + int a = 0, c; + switch (b) { + case 1: a = b / 2; break; + case 4: c = b - 4; a = Features_Dataflow_Explicit_flows_sink(b, c); break; + default: break; + } + + return a; +} + +int Features_Dataflow_Explicit_flows_good_main() { + int src = Features_Dataflow_Explicit_flows_source(); + return Features_Dataflow_Explicit_flows_good(src); +} + +int Features_Dataflow_Explicit_flows_bad_main() { + int src = Features_Dataflow_Explicit_flows_source(); + return Features_Dataflow_Explicit_flows_bad(src); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/Dataflow/Features_Dataflow_Implicit_flows.c b/Benchmark_C_CPP/src/Features/Dataflow/Features_Dataflow_Implicit_flows.c new file mode 100644 index 0000000..1b2968e --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Dataflow/Features_Dataflow_Implicit_flows.c @@ -0,0 +1,86 @@ +#include "benchmark.h" +#include + +//**************************************************************// +// 除零 (Divide By Zero, CWE369) // +//**************************************************************// + +int Features_Dataflow_Implicit_flows_source() { + int input; + scanf("%d", &input); + return input; +} + +// division +int Features_Dataflow_Implicit_flows_sink(int dividend, int divisor) { + return dividend / divisor; +} + +int Features_Dataflow_Implicit_flows_good1(int b) { + int a = 0, c, d; + + if(b < 0) + d = 1; + else if(b >= 0 && b < 10) + d = 2; + else if(b > 10) + d = 4; + + switch (b) { + case 1: a = d / 2; break; + case 4: c = d - 4; a = Features_Dataflow_Implicit_flows_sink(d, c); break; + } + + return a; +} + +int Features_Dataflow_Implicit_flows_good2(int b) { + int a = 0, c, d; + + if(b < 0) + d = 1; + else if(b >= 0 && b < 10) + d = 2; + else if(b > 10) + d = 3; + + switch (b) { + case 1: a = d / 2; break; + case 14: c = d - 4; a = Features_Dataflow_Implicit_flows_sink(d, c); break; + } + + return a; +} + +int Features_Dataflow_Implicit_flows_bad(int b) { + int a = 0, c, d; + + if(b < 0) + d = 1; + else if(b >= 0 && b < 10) + d = 2; + else if(b > 10) + d = 4; + + switch (b) { + case 1: a = d / 2; break; + case 14: c = d - 4; a = Features_Dataflow_Implicit_flows_sink(d, c); break; + } + + return a; +} + +int Features_Dataflow_Implicit_flows_good1_main() { + int src = Features_Dataflow_Implicit_flows_source(); + return Features_Dataflow_Implicit_flows_good1(src); +} + +int Features_Dataflow_Implicit_flows_good2_main() { + int src = Features_Dataflow_Implicit_flows_source(); + return Features_Dataflow_Implicit_flows_good2(src); +} + +int Features_Dataflow_Implicit_flows_bad_main() { + int src = Features_Dataflow_Implicit_flows_source(); + return Features_Dataflow_Implicit_flows_bad(src); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/Dataflow/README.md b/Benchmark_C_CPP/src/Features/Dataflow/README.md new file mode 100644 index 0000000..e69de29 diff --git a/Benchmark_C_CPP/src/Features/Language/Features_Language_Constructor/Features_Language_Constructor.h b/Benchmark_C_CPP/src/Features/Language/Features_Language_Constructor/Features_Language_Constructor.h new file mode 100644 index 0000000..924ca66 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Language/Features_Language_Constructor/Features_Language_Constructor.h @@ -0,0 +1,11 @@ +#ifndef CWE401_CONSTRUCTOR_MEMORY_LEAK_ABC_H_ +#define CWE401_CONSTRUCTOR_MEMORY_LEAK_ABC_H_ +class ABC +{ + public: + ABC(int i); + ~ABC(); + void print(); + int *data; +}; +#endif \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/Language/Features_Language_Constructor/Features_Language_Constructor0.cpp b/Benchmark_C_CPP/src/Features/Language/Features_Language_Constructor/Features_Language_Constructor0.cpp new file mode 100644 index 0000000..64d2802 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Language/Features_Language_Constructor/Features_Language_Constructor0.cpp @@ -0,0 +1,16 @@ +#include +#include "Features_Language_Constructor.h" +using namespace std; +ABC::ABC(int i) +{ + data = new int; + *data = i; +} +ABC::~ABC( ) +{ + delete data; +} +void ABC::print( ) +{ + cout << *data << endl; +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/Language/Features_Language_Constructor/Features_Language_Constructor1.cpp b/Benchmark_C_CPP/src/Features/Language/Features_Language_Constructor/Features_Language_Constructor1.cpp new file mode 100644 index 0000000..d8e98cc --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Language/Features_Language_Constructor/Features_Language_Constructor1.cpp @@ -0,0 +1,16 @@ +// 测试对于构造函数和析构函数的隐式调用能否正确处理 +#include "Features_Language_Constructor.h" +int Features_Language_Constructor_good( ) //FP: memory-leak +{ + ABC abc(1); //隐式地调用了构造函数ABC + abc.print(); + return 0; //隐式地调用了析构函数~ABC +} + +int Features_Language_Constructor_bad( ) +{ + ABC abc(1); //隐式地调用了构造函数ABC + abc.print(); + delete abc.data; //source: free abc.data + return 0; //sink:隐式地调用了析构函数~ABC,double free abc.data +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/Language/Features_Language_FuncPtr.cpp b/Benchmark_C_CPP/src/Features/Language/Features_Language_FuncPtr.cpp new file mode 100644 index 0000000..51ba3d2 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Language/Features_Language_FuncPtr.cpp @@ -0,0 +1,31 @@ +#include +struct box { + int *p; + + box() { + p = NULL; //source + } + ~box() { + delete p; + } +}; + +void Features_Language_FuncPtr_bad() { + auto fn = [c = box()] {std::cout<<*(c.p);}; // NPD + fn(); +} + +void Features_Language_FuncPtr_good() { + auto fn = [c = box()](int* param) { + if(c.p){ + std::cout<<*(c.p); + }else{ + std::cout<<*param; + } + }; + fn(new int(2)); +} + +int main(){ + Features_Language_FuncPtr_good(); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/Language/Features_Language_Lambda.cpp b/Benchmark_C_CPP/src/Features/Language/Features_Language_Lambda.cpp new file mode 100644 index 0000000..d564de7 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Language/Features_Language_Lambda.cpp @@ -0,0 +1,78 @@ +#include +#include +#include +#include + +int Features_Language_Lambda_bad0(int a) { + int* p = nullptr; // source + auto mayAccessResource = [](int x) -> bool { + x = x * 3; + if(x > 0){ + return true; + }else{ + return false; + } + }; + + if (mayAccessResource(a)) { + return *p; //NPD + } else { + + return 0; + } +} + +int Features_Language_Lambda_good0(int a) { + int* p = new int(1); + auto mayAccessResource = [](int x) -> bool { + x = x * 3; + if(x > 0){ + return true; + }else{ + return false; + } + }; + + if (mayAccessResource(a)) { + int ret = *p; + delete p; + return ret; + } else { + delete p; + return 0; + } +} + + +int Features_Language_Lambda_bad1() { + int* w1 = new int(1); + int* w2 = nullptr; //Source: 空指针 + + // 定义lambda表达式,不检查空指针 + auto displayInt = [](int* w) { + std::cout<<*w; // 如果w是nullptr,这里会触发空指针解引用 + }; + + displayInt(w1); + displayInt(w2); // Sink + + delete w1; // 清理资源,w2是空指针,所以不需要删除 + return 0; +} + +int Features_Language_Lambda_good1() { + int* w1 = new int(1); + int* w2 = nullptr; //Source: 空指针 + + // 定义lambda表达式,检查空指针 + auto displayInt = [](int* w) { + if(w != nullptr) + std::cout<<*w; // 如果w是nullptr,这里会触发空指针解引用 + }; + + displayInt(w1); + displayInt(w2); // Sink + + delete w1; // 清理资源,w2是空指针,所以不需要删除 + return 0; +} diff --git a/Benchmark_C_CPP/src/Features/Language/Features_Language_Macro.c b/Benchmark_C_CPP/src/Features/Language/Features_Language_Macro.c new file mode 100644 index 0000000..5f0ac90 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Language/Features_Language_Macro.c @@ -0,0 +1,25 @@ +#include "benchmark.h" + +#define SAFEFREE(ptr) do { free(ptr); (ptr) = NULL; } while(0) + +#define FREE(ptr) do { if(*ptr != 10){ *ptr = 10;} free(ptr); } while(0) + +int Features_Language_Macro_bad() { + int* ptr = (int*)malloc(sizeof(int)); + *ptr = 10; + + FREE(ptr); // source: free ptr + free(ptr); // sink: double free ptr + + return 0; +} + +int Features_Language_Macro_good() { + int* ptr = (int*)malloc(sizeof(int)); + *ptr = 10; + + SAFEFREE(ptr); // source: free ptr + free(ptr); + + return 0; +} diff --git a/Benchmark_C_CPP/src/Features/Language/Features_Language_Reference.cpp b/Benchmark_C_CPP/src/Features/Language/Features_Language_Reference.cpp new file mode 100644 index 0000000..04c70e4 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Language/Features_Language_Reference.cpp @@ -0,0 +1,27 @@ +void Features_Language_Reference_good_sink(int *&x) +{ + x = new int; + *x = 42; +} + +void Features_Language_Reference_bad_sink(int *&x) +{ + x = nullptr; +} + + +int Features_Language_Reference_bad(){ + int *myPointer = nullptr; // source + foo(myPointer); + int ret = *myPointer; // NPD; + delete myPointer; + return ret; +} + +int Features_Language_Reference_good(){ + int *myPointer = nullptr; + foo(myPointer); + int ret = *myPointer; + delete myPointer; + return ret; +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/Language/Features_Language_SmartPtr.cpp b/Benchmark_C_CPP/src/Features/Language/Features_Language_SmartPtr.cpp new file mode 100644 index 0000000..54bae78 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Language/Features_Language_SmartPtr.cpp @@ -0,0 +1,27 @@ +#include + +class Divider { +public: + int divisor; + + Divider(int divisor) : divisor(divisor) {} + + int divide(int dividend) { + return dividend / this->divisor; + } +}; + +int Features_Language_SmartPtr_bad() { + std::unique_ptr divider = std::make_unique(0); // source + int dividend = 10; + int result = divider->divide(dividend); //sink 除零错误 + return result; +} + +int Features_Language_SmartPtr_good() { + std::unique_ptr divider = std::make_unique(1); + int dividend = 10; + int result = divider->divide(dividend); + return result; +} + diff --git a/Benchmark_C_CPP/src/Features/Language/Features_Language_Template.cpp b/Benchmark_C_CPP/src/Features/Language/Features_Language_Template.cpp new file mode 100644 index 0000000..59ea683 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Language/Features_Language_Template.cpp @@ -0,0 +1,19 @@ +#include + +template +T dereference(T* ptr) { + return *ptr; // 如果ptr为nullptr,则这里会有未定义行为 +} + +int Features_Language_Template_bad() { + int* intPtr = nullptr; // Source + int value = dereference(intPtr); //Sink + return value; +} + +int Features_Language_Template_good() { + int* intPtr = new int(1); + int value = dereference(intPtr); + delete intPtr; + return value; +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/Language/Features_Language_Ternary.c b/Benchmark_C_CPP/src/Features/Language/Features_Language_Ternary.c new file mode 100644 index 0000000..3f5c634 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Language/Features_Language_Ternary.c @@ -0,0 +1,12 @@ +//三目运算符条件搜集 +#include "benchmark.h" +int Features_Language_Ternary_good(int p) { + int *a = p ? &p : 0; //Source: 空指针null, 当p为0时 + return p ? *a : 0; //条件冲突 NO NPD +} + +int Features_Language_Ternary_bad(int p) { + int *a = p ? 0 : &p; //Source: 空指针null,当p不为0时 + return p ? *a : 0; // Sink: 空指针解引用 (Null Pointer Dereference, CWE476) +} + diff --git a/Benchmark_C_CPP/src/Features/Language/Features_Language_Ternary_Cond1.c b/Benchmark_C_CPP/src/Features/Language/Features_Language_Ternary_Cond1.c new file mode 100644 index 0000000..ac108d7 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Language/Features_Language_Ternary_Cond1.c @@ -0,0 +1,46 @@ +#include "benchmark.h" + +int *Features_Language_Ternary_Cond1_source() { + int *data = NULL; //Source: 空指针null + return data; +} + +int Features_Language_Ternary_Cond1_sink(int *data) { + return *data; // Sink: 空指针解引用 (Null Pointer Dereference, CWE476) +} + +int Features_Language_Ternary_Cond1_bad(int *data, int cond) { + int array[100]; + int *data_array = &array[1]; + //条件为0时存在Source到Sink的数据流 + int *data1 = cond < 0 ? data + : ( cond == 0 ? Features_Language_Ternary_Cond1_source() + : data_array); + return cond == 0 ? Features_Language_Ternary_Cond1_sink(data1) + : 0; +} + +int Features_Language_Ternary_Cond1_bad_main(int parm) { + int *data = malloc(4); + if(data == NULL) + return 0; + return Features_Language_Ternary_Cond1_bad(data, parm); +} + +int Features_Language_Ternary_Cond1_good(int *data, int cond) { + int array[100]; + int *data_array = &array[1]; + //不存在Source到Sink的数据流 + int *data1 = cond < 0 ? data + : ( cond == 0 ? Features_Language_Ternary_Cond1_source() + : data_array); + return cond > 0 ? Features_Language_Ternary_Cond1_sink(data1) + : 0; +} + +int Features_Language_Ternary_Cond1_good_main(int parm) { + int *data = malloc(4); + if(data == NULL) + return 0; + return Features_Language_Ternary_Cond1_good(data, parm); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/Language/Features_Language_TryCatch.cpp b/Benchmark_C_CPP/src/Features/Language/Features_Language_TryCatch.cpp new file mode 100644 index 0000000..4f90322 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Language/Features_Language_TryCatch.cpp @@ -0,0 +1,31 @@ +#include +#include +int Features_Language_TryCatch_bad() { + int* ptr = nullptr; // source + + try { + throw std::runtime_error("Failed to complete initialization."); + ptr = new int(10); + *ptr = 10; + } catch (const std::exception& e) { + //do nothing + } + + return *ptr; //Sink: null pointer dereference +} + +int Features_Language_TryCatch_good() { + int* ptr = nullptr; + + try { + throw std::runtime_error("Failed to complete initialization."); + ptr = new int(10); + *ptr = 10; + } catch (const std::exception& e) { + if (ptr == nullptr) { + ptr = new int(10); + *ptr = 10; + } + } + return *ptr; +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/Language/README.md b/Benchmark_C_CPP/src/Features/Language/README.md new file mode 100644 index 0000000..5325154 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Language/README.md @@ -0,0 +1,4 @@ +# 构造函数(Constructor) + +## 隐式地调用构造函数和析构函数 +* `Features_Language_Constructor_main.cpp`, `Features_Language_Constructor.cpp`, `Features_Language_Constructor.h`: 考察隐式地调用构造函数和析构函数,如果报出memory-leak,属于FP。同时考察多文件的处理。 \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/Termination/Features_Termination_Loop_Big_Loop.c b/Benchmark_C_CPP/src/Features/Termination/Features_Termination_Loop_Big_Loop.c new file mode 100644 index 0000000..d734527 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Termination/Features_Termination_Loop_Big_Loop.c @@ -0,0 +1,37 @@ +#include "benchmark.h" + +#define LARGE_NUMBER 10000 + +//**************************************************************// +// 除零 (Divide By Zero, CWE369) // +//**************************************************************// + +int Features_Termination_Loop_Big_Loop_good(int n) { + int i = 1, res; + for(; i <= LARGE_NUMBER; i++) { + res = n / i; + printf("result = %d\n", res); + } + + return res; +} + +int Features_Termination_Loop_Big_Loop_bad(int n) { + int i = 1, res; + for(; i <= LARGE_NUMBER; i++) { + res = n / (i - 1000); + printf("result = %d\n", res); + } + + return res; +} + +int Features_Termination_Loop_Big_Loop_good_main() { + int divident = 100; + return Features_Termination_Loop_Big_Loop_good(divident); +} + +int Features_Termination_Loop_Big_Loop_bad_main() { + int divident = 100; + return Features_Termination_Loop_Big_Loop_bad(divident); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/Termination/Features_Termination_Loop_Big_Loop_irrelevance.c b/Benchmark_C_CPP/src/Features/Termination/Features_Termination_Loop_Big_Loop_irrelevance.c new file mode 100644 index 0000000..7c9fde6 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Termination/Features_Termination_Loop_Big_Loop_irrelevance.c @@ -0,0 +1,31 @@ +#include "benchmark.h" + +#define LARGE_NUMBER 10000 + +void a(int *e) { + *e = (0 == e); +} + +void Features_Termination_Loop_Big_Loop_irrelevance_good() { + int d[4]; + for (int c =0 ; c < LARGE_NUMBER; c++) //数据流路径上存在多个大循环(和条件无关) + ; + a(d); +} + +void Features_Termination_Loop_Big_Loop_irrelevance_bad_sink(int *e) { + *e = (0 == e); // Sink: 空指针解引用 +} + +void Features_Termination_Loop_Big_Loop_irrelevance_bad() { + int* d = NULL; //Source: 空指针null + for (int c =0 ; c < LARGE_NUMBER; c++) + ; + Features_Termination_Loop_Big_Loop_irrelevance_bad_sink(d); +} + +int Features_Termination_Loop_Big_Loop_irrelevance_main(){ + Features_Termination_Loop_Big_Loop_irrelevance_good(); + Features_Termination_Loop_Big_Loop_irrelevance_bad(); + return 0; +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/Termination/Features_Termination_Loop_InfiniteLoop_1.c b/Benchmark_C_CPP/src/Features/Termination/Features_Termination_Loop_InfiniteLoop_1.c new file mode 100644 index 0000000..4bd13e8 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Termination/Features_Termination_Loop_InfiniteLoop_1.c @@ -0,0 +1,83 @@ +#include "benchmark.h" +#include + +void Features_Termination_Loop_InfiniteLoop_1_good(unsigned i) { + if(i >= 30) return; + + while (1) { + printf("Current value of i: %d\n", i); + i++; + + if (i % 5 == 0) { + printf("Take some actions...\n"); + } + + if (i < 20) { + continue; + } + + if (i == 30) { + printf("Loop end!\n"); + break; + } + } +} + +// The parameter i must be unsigned because unsigned integer overflow is defined behavior, +// whereas signed integer overflow is not. +void Features_Termination_Loop_InfiniteLoop_1_bad1(unsigned i) { + while (1) { + printf("Current value of i: %d\n", i); + i++; + + if (i % 5 == 0) { + printf("Take some actions...\n"); + } + + if (i < 20) { + continue; + } + + if (i == 30) { + printf("Loop end!\n"); + break; + } + } +} + +void Features_Termination_Loop_InfiniteLoop_1_bad2(unsigned i) { + while (1) { + printf("Current value of i: %d\n", i); + i++; + + if (i % 5 == 0) { + printf("Take some actions...\n"); + } + + if (i < 20) { + continue; + } + + if (i == 30) { + printf("Loop end!\n"); + } + } +} + +void Features_Termination_Loop_InfiniteLoop_1_good_main() { + unsigned input; + scanf("%d", &input); + Features_Termination_Loop_InfiniteLoop_1_good(input); +} + +void Features_Termination_Loop_InfiniteLoop_1_bad1_main() { + unsigned input; + scanf("%d", &input); + Features_Termination_Loop_InfiniteLoop_1_bad1(input); +} + +void Features_Termination_Loop_InfiniteLoop_1_bad2_main() { + unsigned input; + scanf("%d", &input); + Features_Termination_Loop_InfiniteLoop_1_bad2(input); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/Termination/Features_Termination_Loop_InfiniteLoop_2.c b/Benchmark_C_CPP/src/Features/Termination/Features_Termination_Loop_InfiniteLoop_2.c new file mode 100644 index 0000000..29abc8e --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Termination/Features_Termination_Loop_InfiniteLoop_2.c @@ -0,0 +1,54 @@ +#include "benchmark.h" +#include + +void Features_Termination_Loop_InfiniteLoop_2_bad(unsigned i) { + while (i > 10) { + printf("Current value of i: %d\n", i); + i++; + + if (i % 5 == 0) { + printf("Take some actions...\n"); + } + + if (i < 20) { + continue; + } + + if (i < 25) { + printf("Loop end!\n"); + break; + } + } +} + +void Features_Termination_Loop_InfiniteLoop_2_good(unsigned i) { + while (i > 10) { + printf("Current value of i: %d\n", i); + i++; + + if (i % 5 == 0) { + printf("Take some actions...\n"); + } + + if (i < 20) { + continue; + } + + if (i > 25) { + printf("Loop end!\n"); + break; + } + } +} + +void Features_Termination_Loop_InfiniteLoop_2_bad_main() { + unsigned input; + scanf("%u", &input); + Features_Termination_Loop_InfiniteLoop_2_bad(input); +} + +void Features_Termination_Loop_InfiniteLoop_2_good_main() { + unsigned input; + scanf("%u", &input); + Features_Termination_Loop_InfiniteLoop_2_good(input); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/Termination/Features_Termination_Loop_Range_Based_Loop.cpp b/Benchmark_C_CPP/src/Features/Termination/Features_Termination_Loop_Range_Based_Loop.cpp new file mode 100644 index 0000000..eb13557 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Termination/Features_Termination_Loop_Range_Based_Loop.cpp @@ -0,0 +1,28 @@ +#include +#include + +struct A { + explicit A(int& i) : data(&i) { // Store the address of i + } + void foo() const { + for (auto& i : std::array{data}) // Create a temporary array of pointers for iteration + (*i)++; // Dereference the pointer to increment the value + } + int* data; // Pointer to an int +}; + +int Features_Termination_Loop_Range_Based_Loop_good() { + int i = -1; + A a{i}; // Pass i by reference + i = 0; + a.foo(); // Increments i to 1 + return 1 / i; // Returns 1 since i is now 1 +} + +int Features_Termination_Loop_Range_Based_Loop_bad() { + int i = -1; + A a{i}; // Pass i by reference + i = -1; + a.foo(); // Increments i to 0 + return 1 / i; // 除零 (Divide By Zero, CWE369) +} diff --git a/Benchmark_C_CPP/src/Features/Termination/Features_Termination_Recursion.c b/Benchmark_C_CPP/src/Features/Termination/Features_Termination_Recursion.c new file mode 100644 index 0000000..a08867c --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Termination/Features_Termination_Recursion.c @@ -0,0 +1,32 @@ +#include "benchmark.h" + +int factorial(int n) { + if(n <= 0) { + return 1; + } else { + return n * factorial(n - 1); + } +} + +int Features_Termination_Recursion_bad(int* p) +{ + int a; + scanf("%d", &a); + if (factorial(a) == 5040) // factorial(7) + return *p; // Sink: 空指针解引用 (Null Pointer Dereference, CWE476) + return 0; +} +int Features_Termination_Recursion_good(int* p) +{ + int a; + scanf("%d", &a); + if (factorial(a) < 0) + return *p; //NO NPD 条件冲突 + return 0; +} + +int Features_Constraint_Recursive_main(){ + int *p = NULL; //Source: 空指针null + Features_Termination_Recursion_good(p); + Features_Termination_Recursion_bad(p); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/Termination/Features_Termination_Recursion_InfiniteRecursion_1.c b/Benchmark_C_CPP/src/Features/Termination/Features_Termination_Recursion_InfiniteRecursion_1.c new file mode 100644 index 0000000..89dd07c --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Termination/Features_Termination_Recursion_InfiniteRecursion_1.c @@ -0,0 +1,44 @@ +#include "benchmark.h" +#include + +void Features_Termination_Recursion_InfiniteRecursion_1_good(int n) { + printf("Current value of n: %d\n", n); + + if (n % 5 == 0) { + printf("Take some actions...\n"); + } + + if (n < 20) { + Features_Termination_Recursion_InfiniteRecursion_1_good(n + 1); + } + + if (n == 30) { + printf("Recursion end!\n"); + return; + } +} + +void Features_Termination_Recursion_InfiniteRecursion_1_bad(int n) { + printf("Current value of n: %d\n", n); + + if (n % 5 == 0) { + printf("Take some actions...\n"); + } + + Features_Termination_Recursion_InfiniteRecursion_1_bad(n + 1); + + if (n == 30) { + printf("Recursion end!\n"); + return; + } +} + +void Features_Termination_Recursion_InfiniteRecursion_1_good_main() { + int n = 0; + Features_Termination_Recursion_InfiniteRecursion_1_good(n); +} + +void Features_Termination_Recursion_InfiniteRecursion_1_bad_main() { + int n = 0; + Features_Termination_Recursion_InfiniteRecursion_1_bad(n); +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/Termination/Features_Termination_Small_Loop_irrelevance.c b/Benchmark_C_CPP/src/Features/Termination/Features_Termination_Small_Loop_irrelevance.c new file mode 100644 index 0000000..9c91cd2 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Termination/Features_Termination_Small_Loop_irrelevance.c @@ -0,0 +1,24 @@ +#include "benchmark.h" +int Features_Termination_Small_Loop_irrelevance_good(int x) { + int result = 0; + int *p = &x; + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 1; j++) { + p == 0; + result = *p; //FP: Null Pointer Dereference + } + } + return result; +} + +int Features_Termination_Small_Loop_irrelevance_bad(int x) { + int result = 0; + int *p = NULL; //Source: 空指针null + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 1; j++) { + p == 0; + result = *p; //Null Pointer Dereference + } + } + return result; +} \ No newline at end of file diff --git a/Benchmark_C_CPP/src/Features/Termination/README.md b/Benchmark_C_CPP/src/Features/Termination/README.md new file mode 100644 index 0000000..22bef18 --- /dev/null +++ b/Benchmark_C_CPP/src/Features/Termination/README.md @@ -0,0 +1,13 @@ +# 循环 + +## 数据流路径上存在多个大循环(和条件无关) + +* `Features_Termination_Loop_Big_Loop_irrelevance.c`: 如果存在大循环的路径,是否会选择跳过分析该路径。 + > If the widen-loops option is not set then we model only 4 iterations of loops and then the analyzer stops on that path by putting a sink node. [CSA issue链接](https://github.com/llvm/llvm-project/issues/58621)。 + >CSA如果打开widen-loops选项,不会出现FP + +* `Features_Termination_Loop_irrelevance.c`: 简单的嵌套循环,CSA如果打开widen-loops选项,会出现FP,[issue链接](https://github.com/llvm/llvm-project/issues/58644) + +* `Features_Termination_Loop_Range_Based_Loop.cpp`: 考察range-based for loop的支持情况,如果默认所有range-based for loop都存在0-iteration的情况,那么在该样例中就会出现FP。[issue链接](https://github.com/llvm/llvm-project/issues/64584) + +# 递归 \ No newline at end of file diff --git a/Benchmark_C_CPP/src/benchmark.h b/Benchmark_C_CPP/src/benchmark.h new file mode 100644 index 0000000..1e55ddf --- /dev/null +++ b/Benchmark_C_CPP/src/benchmark.h @@ -0,0 +1,18 @@ +#ifndef _BENCHMARK_H_ +#define _BENCHMARK_H_ + +#ifdef __cplusplus +#include +#include +#include +#else +#include +#include +#include +#endif + + +int GlobalInt_Zero = 0; +float GlobalFloat_Five = 5.0; + +#endif \ No newline at end of file