Skip to content

Commit fa1fbb5

Browse files
committed
Add edge case regression tests for --generate-function-body const handling
The existing tests provided basic const handling coverage, but several complex scenarios were not comprehensively tested. This PR addresses the following edge cases: 1. **Triple pointer const handling** - `int * const **` (const at middle level) 2. **Double const qualification** - `const int * const` (both pointer and data const) 3. **Array of pointers to const** - `const int **` / `const int *arr[]` 4. **Const function pointers** - `func_ptr_t * const` 5. **Nested struct const pointers** - Mixed const/non-const in nested structures 6. **Combined qualifiers** - `volatile const int *` (volatile + const interaction) 7. **Const array parameters** - `const int[]` (array parameter const protection) 8. **Pointer to const struct** - `const struct test_struct *` (struct-level const) 9. **Systematic const variations** - Comprehensive test of const at each pointer level Co-authored-by: Kiro autonomous agent Fixes: #1948
1 parent 76dd20f commit fa1fbb5

File tree

18 files changed

+488
-0
lines changed

18 files changed

+488
-0
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#include <assert.h>
2+
3+
// Edge case: array of pointers where each pointer points to const data
4+
// const int *arr[] - array elements are pointers to const int
5+
void havoc_array_of_pointers_to_const(const int **arr, int size);
6+
7+
int main(void)
8+
{
9+
int a = 10, b = 20, c = 30;
10+
const int *arr[] = {&a, &b, &c};
11+
12+
assert(a == 10);
13+
assert(b == 20);
14+
assert(c == 30);
15+
assert(*arr[0] == 10);
16+
assert(*arr[1] == 20);
17+
assert(*arr[2] == 30);
18+
19+
// Havoc the array - pointers can change but const data should be preserved
20+
havoc_array_of_pointers_to_const(arr, 3);
21+
22+
// The underlying int values should remain unchanged due to const
23+
assert(a == 10);
24+
assert(b == 20);
25+
assert(c == 30);
26+
27+
// But the array pointers could point elsewhere, so these may fail
28+
assert(*arr[0] == 10);
29+
assert(*arr[1] == 20);
30+
assert(*arr[2] == 30);
31+
32+
return 0;
33+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
CORE
2+
main.c
3+
--generate-function-body havoc_array_of_pointers_to_const --generate-function-body-options havoc,params:.*
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^\[main.assertion.1\] .* assertion a == 10: SUCCESS$
7+
^\[main.assertion.2\] .* assertion b == 20: SUCCESS$
8+
^\[main.assertion.3\] .* assertion c == 30: SUCCESS$
9+
^\[main.assertion.4\] .* assertion \*arr\[0\] == 10: SUCCESS$
10+
^\[main.assertion.5\] .* assertion \*arr\[1\] == 20: SUCCESS$
11+
^\[main.assertion.6\] .* assertion \*arr\[2\] == 30: SUCCESS$
12+
^\[main.assertion.7\] .* assertion a == 10: SUCCESS$
13+
^\[main.assertion.8\] .* assertion b == 20: SUCCESS$
14+
^\[main.assertion.9\] .* assertion c == 30: SUCCESS$
15+
^\[main.assertion.10\] .* assertion \*arr\[0\] == 10 FAILURE$
16+
^\[main.assertion.11\] .* assertion \*arr\[1\] == 20: FAILURE$
17+
^\[main.assertion.12\] .* assertion \*arr\[2\] == 30: FAILURE$
18+
--
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#include <assert.h>
2+
3+
// Edge case: const array parameter
4+
// const int arr[] is equivalent to const int *arr
5+
void havoc_const_array(const int arr[], int size);
6+
7+
int main(void)
8+
{
9+
int data[] = {1, 2, 3, 4, 5};
10+
11+
assert(data[0] == 1);
12+
assert(data[1] == 2);
13+
assert(data[2] == 3);
14+
assert(data[3] == 4);
15+
assert(data[4] == 5);
16+
17+
// Array parameter with const should not allow modification of elements
18+
havoc_const_array(data, 5);
19+
20+
// All should succeed due to const
21+
assert(data[0] == 1);
22+
assert(data[1] == 2);
23+
assert(data[2] == 3);
24+
assert(data[3] == 4);
25+
assert(data[4] == 5);
26+
27+
return 0;
28+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
CORE
2+
main.c
3+
--generate-function-body havoc_const_array --generate-function-body-options havoc,params:.*
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\[main.assertion.1\] .* assertion data\[0\] == 1: SUCCESS$
7+
^\[main.assertion.2\] .* assertion data\[1\] == 2: SUCCESS$
8+
^\[main.assertion.3\] .* assertion data\[2\] == 3: SUCCESS$
9+
^\[main.assertion.4\] .* assertion data\[3\] == 4: SUCCESS$
10+
^\[main.assertion.5\] .* assertion data\[4\] == 5: SUCCESS$
11+
^\[main.assertion.6\] .* assertion data\[0\] == 1: SUCCESS$
12+
^\[main.assertion.7\] .* assertion data\[1\] == 2: SUCCESS$
13+
^\[main.assertion.8\] .* assertion data\[2\] == 3: SUCCESS$
14+
^\[main.assertion.9\] .* assertion data\[3\] == 4: SUCCESS$
15+
^\[main.assertion.10\] .* assertion data\[4\] == 5: SUCCESS$
16+
^VERIFICATION SUCCESSFUL$
17+
--
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#include <assert.h>
2+
3+
// Edge case: both pointer and pointed-to data are const
4+
// const int * const means neither the pointer nor the data can be modified
5+
void havoc_const_pointer_to_const(const int *const param);
6+
7+
int main(void)
8+
{
9+
int x = 55;
10+
const int *const ptr = &x;
11+
12+
assert(x == 55);
13+
assert(*ptr == 55);
14+
15+
// With both const qualifiers, havoc should not modify anything
16+
havoc_const_pointer_to_const(ptr);
17+
18+
// Both should succeed since everything is const
19+
assert(x == 55);
20+
assert(*ptr == 55);
21+
22+
return 0;
23+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
main.c
3+
--generate-function-body havoc_const_pointer_to_const --generate-function-body-options havoc,params:.*
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\[main.assertion.1\] .* assertion x == 55: SUCCESS$
7+
^\[main.assertion.2\] .* assertion \*ptr == 55: SUCCESS$
8+
^\[main.assertion.3\] .* assertion x == 55: SUCCESS$
9+
^\[main.assertion.4\] .* assertion \*ptr == 55: SUCCESS$
10+
^VERIFICATION SUCCESSFUL$
11+
--
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#include <assert.h>
2+
3+
// Edge case: const function pointer
4+
// int (* const fp)(void) means the function pointer itself is const
5+
typedef int (*func_ptr_t)(void);
6+
7+
int test_function(void)
8+
{
9+
return 42;
10+
}
11+
12+
void havoc_const_function_pointer(func_ptr_t *const func_ptr);
13+
14+
int main(void)
15+
{
16+
func_ptr_t fp = test_function;
17+
func_ptr_t *const const_fp_ptr = &fp;
18+
19+
// The function pointer itself should not be modifiable
20+
havoc_const_function_pointer(const_fp_ptr);
21+
22+
// Since the pointer to the function pointer is const,
23+
// the function pointer itself should remain unchanged
24+
assert(fp == test_function);
25+
26+
return 0;
27+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
--generate-function-body havoc_const_function_pointer --generate-function-body-options havoc,params:.*
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\[main.assertion.1\] .* assertion fp == test_function: SUCCESS$
7+
^VERIFICATION SUCCESSFUL$
8+
--
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#include <assert.h>
2+
3+
// Edge case: nested struct with mixed const pointer qualifiers
4+
struct inner
5+
{
6+
const int *const_ptr; // pointer to const
7+
int *normal_ptr; // normal pointer
8+
};
9+
10+
struct outer
11+
{
12+
struct inner *const const_inner_ptr; // const pointer to struct
13+
struct inner *normal_inner_ptr; // normal pointer to struct
14+
const struct inner *const_struct_ptr; // pointer to const struct
15+
};
16+
17+
void havoc_nested_struct_const_pointers(struct outer *s);
18+
19+
int main(void)
20+
{
21+
int x = 100, y = 200, z = 300, w = 400;
22+
23+
struct inner inner1 = {&x, &y};
24+
struct inner inner2 = {&z, &w};
25+
struct outer outer_struct = {&inner1, &inner2, &inner1};
26+
27+
// Initial state
28+
assert(x == 100);
29+
assert(y == 200);
30+
assert(z == 300);
31+
assert(w == 400);
32+
assert(*outer_struct.const_inner_ptr->const_ptr == 100);
33+
assert(*outer_struct.const_inner_ptr->normal_ptr == 200);
34+
35+
havoc_nested_struct_const_pointers(&outer_struct);
36+
37+
// Values pointed to by const pointers should be preserved
38+
assert(x == 100); // pointed to by const_ptr
39+
assert(z == 300); // pointed to by const_ptr in inner2
40+
41+
// Values pointed to by normal pointers may be modified
42+
assert(y == 200); // may fail - pointed to by normal_ptr
43+
assert(w == 400); // may fail - pointed to by normal_ptr
44+
45+
return 0;
46+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
CORE
2+
main.c
3+
--generate-function-body havoc_nested_struct_const_pointers --generate-function-body-options havoc,params:.*
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^\[main.assertion.1\] .* assertion x == 100: SUCCESS$
7+
^\[main.assertion.2\] .* assertion y == 200: SUCCESS$
8+
^\[main.assertion.3\] .* assertion z == 300: SUCCESS$
9+
^\[main.assertion.4\] .* assertion w == 400: SUCCESS$
10+
^\[main.assertion.5\] .* assertion \*outer_struct.const_inner_ptr->const_ptr == 100: SUCCESS$
11+
^\[main.assertion.6\] .* assertion \*outer_struct.const_inner_ptr->normal_ptr == 200: SUCCESS$
12+
^\[main.assertion.7\] .* assertion x == 100: SUCCESS$
13+
^\[main.assertion.8\] .* assertion z == 300: SUCCESS$
14+
^\[main.assertion.9\] .* assertion y == 200: FAILURE$
15+
^\[main.assertion.10\] .* assertion w == 400: FAILURE$
16+
--

0 commit comments

Comments
 (0)