Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions SAGA_CheckerCase/ABUSE_COMMA.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
#include <stdio.h>
#include <stdlib.h>

/**
* Demonstrates a for-loop where the comma operator in the loop condition produces unintended behavior.
*
* The condition `a < 10, b < 10` evaluates only `b < 10` for loop continuation, so `a < 10` does not affect iteration.
*/
void ABUSE_COMMA_BAD()
{

Expand All @@ -19,6 +24,12 @@ void ABUSE_COMMA_BAD()
}

}
/**
* Iterate two integer counters in lockstep while both are less than 10 using a logical conjunction.
*
* Initializes `a` and `b` to 0 and increments both on each iteration; the loop continues only while
* both `a < 10` and `b < 10`, avoiding misuse of the comma operator in the loop condition.
*/
void ABUSE_COMMA_GOOD()
{

Expand Down
11 changes: 11 additions & 0 deletions SAGA_CheckerCase/ARRAY_COMPARE.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
#include <stdio.h>
#include <stdlib.h>

/**
* Demonstrates an incorrect comparison where an array identifier is compared to 0 instead of its element.
*
* Initializes three arrays and sets a[0] to 1 when its first element equals 0. The second conditional mistakenly
* compares the array name `b` (pointer) to 0, so its assignment is not executed and `b[0]` remains 0.
*/
void ARRAY_COMPARE_BAD()
{
unsigned int a[3] = {0};
Expand All @@ -20,6 +26,11 @@ void ARRAY_COMPARE_BAD()
b[0] = 10;
}

/**
* Update the first elements of two local arrays when they are zero.
*
* If a[0] equals 0, sets a[0] to 1. If b[0] equals 0, sets b[0] to 10.
*/
void ARRAY_COMPARE_GOOD()
{
unsigned int a[3] = {0};
Expand Down
23 changes: 23 additions & 0 deletions SAGA_CheckerCase/ARRAY_VS_SINGLETON_S.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,43 @@
#include <stdio.h>
#include <stdlib.h>

/**
* Write the value 123 into `s` at the specified index.
*
* @param s Pointer to the first element of the target array; writing occurs at `s[index]`.
* @param index Index into the array where `123` is stored; behavior is undefined if `s` does not point to storage for that index.
*/
void ARRAY_VS_SINGLETON_S_BAD(int *s,int index)
{
s[index] = 123; // 缺陷点:单一对象被当做数组使用
}
/**
* Demonstrates incorrect usage by passing the address of a single `int` to a function that treats it as an array.
*
* Calls ARRAY_VS_SINGLETON_S_BAD(&c, 9), which may cause an out-of-bounds write.
*/
void ARRAY_VS_SINGLETON_S_BAD_CALL()
{
int c;
ARRAY_VS_SINGLETON_S_BAD(&c, 9);
}

/**
* Store the value 123 into the array element at the given index.
* @param s Pointer to the first element of an `int` array with at least `index + 1` elements.
* @param index Zero-based position within the array to write the value.
*
* Behavior is undefined if `s` is NULL or `index` is out of bounds for the provided array.
*/
void ARRAY_VS_SINGLETON_S_GOOD(int *s,int index)
{
s[index] = 123; // 修复点:正常使用堆上的数组
}
/**
* Allocate a 10-element int array, invoke ARRAY_VS_SINGLETON_S_GOOD with index 9, and free the array.
*
* If memory allocation fails, the function returns without calling ARRAY_VS_SINGLETON_S_GOOD.
*/
void ARRAY_VS_SINGLETON_S_GOOD_CALL()
{
int *c = malloc(10 * sizeof(int));
Expand Down
12 changes: 12 additions & 0 deletions SAGA_CheckerCase/ASSERT_EFFECT.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,24 @@
#include <stdlib.h>
#include <assert.h>
int getValue();
/**
* Demonstrates an unsafe modification performed inside an assertion.
*
* Calls getValue(), then increments the retrieved value inside the assertion
* expression. If the assertion fails the program aborts. When assertions are
* disabled (for example by defining NDEBUG), the increment does not occur.
*/
void ASSERT_EFFECT_BAD()
{
int x = getValue();
assert(++x); // 缺陷点:在断言中进行修改操作
}

/**
* Assert that the value returned by getValue() plus one is non-zero, performing the increment before the assertion.
*
* This function retrieves an integer from getValue(), computes x + 1 into a temporary variable, and asserts that the result is non-zero to avoid side effects inside the assertion expression.
*/
void ASSERT_EFFECT_GOOD()
{
int x = getValue();
Expand Down
15 changes: 15 additions & 0 deletions SAGA_CheckerCase/BAD_ALLOC_ARITHMETIC_S.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,27 @@
#include <stdio.h>
#include <stdlib.h>

/**
* Demonstrates incorrect pointer arithmetic on a malloc-allocated pointer followed by free.
*
* Allocates `a` bytes with malloc, advances the returned pointer by `b`, and then frees the advanced pointer.
* Freeing a pointer that is not the value returned by malloc results in undefined behavior when `b` is nonzero.
*
* @param a Number of bytes requested from malloc.
* @param b Offset (in bytes) added to the allocated pointer before calling free; nonzero values can make the free invalid.
*/
void BAD_ALLOC_ARITHMETIC_S_BAD(int a, int b)
{
char *p = malloc(a) + b; // 缺陷点:可能由于圆括号放错位置,导致分配不足或分配过度以及非正常的指针算术运算
free(p);
}

/**
* Allocate (a + b) bytes on the heap and immediately free the allocation.
*
* @param a First number of bytes to include in the allocation size.
* @param b Second number of bytes to include in the allocation size.
*/
void BAD_ALLOC_ARITHMETIC_S_GOOD(int a, int b)
{
char *p = malloc(a + b); // 修复点:避免错误的指针算数运算
Expand Down
18 changes: 18 additions & 0 deletions SAGA_CheckerCase/BAD_ALLOC_STRLEN_S.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@
#include <stdlib.h>
#include <string.h>

/**
* Demonstrates an incorrect string allocation that may under-allocate buffer space.
*
* If `name` is non-NULL, this function allocates memory using `malloc(strlen(name+1))`
* (an incorrect size calculation). The allocation is immediately freed; if a string copy
* were performed into the allocated buffer, it could cause a buffer overflow. If `name`
* is NULL, the function does nothing.
*
* @param name Input string; may be NULL. When non-NULL, memory is allocated using an incorrect size calculation.
*/
void BAD_ALLOC_STRLEN_S_BAD(char* name)
{
char *new_name = NULL;
Expand All @@ -21,6 +31,14 @@ void BAD_ALLOC_STRLEN_S_BAD(char* name)
}
}

/**
* Allocate and free a buffer sized to hold a copy of the input C-string including the terminating null byte.
*
* If `name` is non-NULL, this function allocates `strlen(name) + 1` bytes intended for a copy of `name`
* and then frees the allocated buffer.
*
* @param name Null-terminated input string to copy; if NULL the function performs no action.
*/
void BAD_ALLOC_STRLEN_S_GOOD(char* name)
{
char *new_name = NULL;
Expand Down
15 changes: 15 additions & 0 deletions SAGA_CheckerCase/BAD_COMPARE_MEMCMP_S.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@
#include <stdlib.h>
#include <string.h>

/**
* Illustrates an incorrect comparison of two strings using strcmp.
*
* This function calls strcmp(s, "blah") and enters the if-block only when the
* result is equal to 1, which is a flawed assumption about memcmp/strcmp
* semantics (these functions return a value greater than, equal to, or less
* than zero to indicate ordering).
*
* @param s Null-terminated string to compare against the literal "blah".
*/
void BAD_COMPARE_MEMCMP_S_BAD(const char *s)
{
if (strcmp(s, "blah") == 1) //缺陷点:错误的认为 memcmp 类函数返回值为定值
Expand All @@ -18,6 +28,11 @@ void BAD_COMPARE_MEMCMP_S_BAD(const char *s)
}
}

/**
* Execute a placeholder action when the input string is lexicographically greater than "blah".
*
* @param s Null-terminated string to compare against "blah".
*/
void BAD_COMPARE_MEMCMP_S_GOOD(const char *s)
{
if (strcmp(s, "blah") > 0) //修复点:memcmp 类函数返回值应为正数情况
Expand Down
14 changes: 14 additions & 0 deletions SAGA_CheckerCase/BAD_COMPARE_NOTOP_S.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
#include <stdio.h>
#include <stdlib.h>

/**
* Demonstrates a flawed comparison where the logical NOT is applied to `x` before the equality test.
*
* @param x Left operand; `!x` is evaluated and then compared to `y`, which can lead to unintended results due to operator precedence.
* @param y Right operand compared against the result of `!x`.
*/
void BAD_COMPARE_NOTOP_S_BAD(int x, int y)
{
if (!x == y) //缺陷点:运算优先级先进行 !x 在做比较 可能是用户意料之外的
Expand All @@ -17,6 +23,14 @@ void BAD_COMPARE_NOTOP_S_BAD(int x, int y)
}
}

/**
* Execute the inner block when the two integer values are not equal.
*
* Evaluates whether x and y differ and runs the enclosed statements only if x != y.
*
* @param x First integer to compare.
* @param y Second integer to compare.
*/
void BAD_COMPARE_NOTOP_S_GOOD(int x, int y)
{
if (!(x == y)) //修复点:使用括号明确优先级
Expand Down
18 changes: 17 additions & 1 deletion SAGA_CheckerCase/BAD_COMPARE_NULL_S.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@
#include <stdio.h>
#include <stdlib.h>

/**
* Demonstrates an incorrect comparison of a pointer with NULL using a relational operator.
*
* This function contains a flawed check that compares the pointer `x` to `NULL` using a
* relational operator (>=) rather than an equality check; it is intended to illustrate
* an unsafe/incorrect NULL comparison pattern.
*
* @param x Pointer to an integer; may be `NULL`.
*/
void BAD_COMPARE_NULL_S_BAD(int *x)
{
if (x >= NULL) //缺陷点:与 NULL 做了不相等比较
Expand All @@ -17,10 +26,17 @@ void BAD_COMPARE_NULL_S_BAD(int *x)
}
}

/**
* Execute the function's action if the provided pointer is NULL.
*
* Checks whether the pointer `x` is equal to `NULL` and performs the conditional action when it is.
*
* @param x Pointer to an int to test for NULL.
*/
void BAD_COMPARE_NULL_S_GOOD(int *x)
{
if (x == NULL) //修复点:与 NULL 做相等和不相等比较
{
/* do something */
}
}
}
14 changes: 14 additions & 0 deletions SAGA_CheckerCase/BAD_COMPARE_STR_S.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@
#include <stdlib.h>
#include <string.h>

/**
* Compare the pointer value of `other` with the string literal "expected" and execute the conditional block if they are the same address.
*
* This performs an address (pointer) comparison against the literal rather than comparing string contents.
* @param other Pointer to a NUL-terminated string to compare.
*/
void BAD_COMPARE_STR_S_GOOD(const char *other)
{
if(other == "expected") //缺陷点:指针(地址)与字符串常量作比较
Expand All @@ -18,6 +24,14 @@ void BAD_COMPARE_STR_S_GOOD(const char *other)
}
}

/**
* Check whether `other` equals "expected" and execute action if equal.
*
* Compares the content of `other` to the string literal "expected" using `strcmp`
* and enters the conditional block if they are equal.
*
* @param other Input string to compare against "expected".
*/
void BAD_COMPARE_STR_S_BAD(const char *other)
{
if(strcmp(other, "expected") == 0) //修复点:使用 strcmp 函数比较字符串内容
Expand Down
11 changes: 11 additions & 0 deletions SAGA_CheckerCase/BAD_FILE_OPEN_S.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
#include <stdio.h>
#include <stdlib.h>

/**
* Demonstrates opening "/proc/stat" and unconditionally closing the FILE pointer.
*
* Opens "/proc/stat" for reading and then calls fclose without checking whether fopen succeeded; if fopen returns NULL, calling fclose on a NULL pointer leads to undefined behavior.
*/
void BAD_FILE_OPEN_S_BAD()
{
FILE *fd;
Expand All @@ -17,6 +22,12 @@ void BAD_FILE_OPEN_S_BAD()
fclose(fd); //缺陷点:关闭的文件符 fd 可能打开失败
}

/**
* Open "/proc/stat" for reading, perform processing if opened, and close the file.
*
* Attempts to open "/proc/stat"; if the open fails the function returns immediately.
* If the file is opened successfully, performs processing (placeholder) and then closes the file.
*/
void BAD_FILE_OPEN_S_GOOD()
{
FILE *fd;
Expand Down
16 changes: 15 additions & 1 deletion SAGA_CheckerCase/BAD_FLOAT_RET.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,26 @@
#include <stdio.h>
#include <stdlib.h>

/**
* Compute the average of two integers using integer arithmetic; fractional part may be lost.
*
* @param a First integer operand.
* @param b Second integer operand.
* @returns The average of `a` and `b` as an `int`; any fractional component is discarded.
*/
int BAD_FLOAT_RET_BAD(int a, int b)
{
return (int)(0.5 + ((a + b) / 2)); // 缺陷点:除数和被除数都不为浮点型,结果被截断为整数,可能会丢失精度
}

/**
* Compute the average of two integers and return it rounded to the nearest integer.
*
* @param a First integer operand.
* @param b Second integer operand.
* @returns The average of `a` and `b`, rounded to the nearest `int`.
*/
int BAD_FLOAT_RET_GOOD(int a, int b)
{
return (int)(0.5 + ((double)a + b) / 2); // 修复点:被除数为浮点型
}
}
14 changes: 14 additions & 0 deletions SAGA_CheckerCase/BAD_FREE_S.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,27 @@

struct S { int a[4]; };

/**
* Demonstrates an incorrect deallocation of stack memory.
*
* Attempts to free memory that resides on the stack, which results in undefined behavior.
*
* @param s Unused parameter.
*/
void BAD_FREE_S_BAD(struct S *s)
{
int stackarray[3];
int *p = stackarray;
free(p); // 缺陷点:释放了栈上的内存
}

/**
* Allocate an array of four integers on the heap and immediately free it.
*
* @param s Pointer to a struct S (unused).
*
* @note Allocation result is not checked for NULL.
*/
void BAD_FREE_S_GOOD(struct S *s)
{
int *stackarray = malloc(sizeof(int)*4);
Expand Down
Loading