llvm / llvm/llvm-project

[CSA] False negatives in short bounded loops

Open
#214,227 3 comments 0 reactions 0 assignees View on GitHub
clang:static analyzer false-negative
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

Hi, I found a family of false negatives in short bounded loops. Definite bugs at a later iteration, or diagnostics emitted when a function exits after a short bounded loop, disappear with the default configuration and reappear when the same loop is explored more precisely.

## Array-bound reproducer

```c
int data[4];

void write_past_end_in_bounded_loop(void) {
for (int i = 0; i <= 4; ++i)
data[i] = i;
}
```

Default analysis emits no warning:

```sh
clang --analyze \
-Xclang -analyzer-checker=security.ArrayBound \
bounded_loop_array.c
```

Enabling loop unrolling reports the definite fifth-iteration overflow:

```sh
clang --analyze \
-Xclang -analyzer-checker=security.ArrayBound \
-Xclang -analyzer-config -Xclang unroll-loops=true \
bounded_loop_array.c
```

```text
bounded_loop_array.c:5:5: warning: Out of bound access to memory after the end of 'data'
```

Running the same program with AddressSanitizer confirms a global-buffer-overflow immediately after the 16-byte `data` object.

## Leak reproducer

```cpp
void leak_after_bounded_loop() {
new int(42);
for (int i = 0; i < 4; ++i) {
}
}
```

The default `cplusplus.NewDeleteLeaks` analysis emits no warning. With `unroll-loops=true`, it emits `Potential memory leak` at the loop. Bounds 0 through 3 retain the report under the default configuration; the report disappears starting at bound 4.

The same late-iteration cutoff affects a deterministic division case: a counter initialized to five is decremented to zero before division, but the diagnostic appears only when the initial value is reduced to three or less.

CSA reproduction for the leak case:

```sh
clang++ --analyze \
-Xclang -analyzer-checker=cplusplus.NewDeleteLeaks \
bounded_loop_leak.cpp
```

Comparison run:

```sh
clang++ --analyze \
-Xclang -analyzer-checker=cplusplus.NewDeleteLeaks \
-Xclang -analyzer-config -Xclang unroll-loops=true \
bounded_loop_leak.cpp
```

## Comparison with related programs

For the array-bound case, a related reported program reaches the same invalid access before the default loop cutoff:

```c
int data[4];

void write_past_end_in_shorter_loop(void) {
for (int i = 0; i <= 3; ++i)
data[i + 1] = i; // warning when i == 3
}
```

The missed program moves the definite invalid access to the later bounded-loop iteration:

```c
int data[4];

void write_past_end_in_bounded_loop(void) {
for (int i = 0; i <= 4; ++i)
data[i] = i; // no warning by default; warning with unroll-loops=true
}
```

For the leak case, the direct discarded allocation is reported:

```cpp
void direct_leak() {
new int(42); // warning
}
```

Adding the short bounded loop after the allocation suppresses the default leak report:

```cpp
void leak_after_bounded_loop() {
new int(42);
for (int i = 0; i < 4; ++i) {
} // no warning by default; warning with unroll-loops=true
}
```

## Expected result

It would be useful for the default analyzer to preserve enough state for small statically bounded loops to diagnose definite bugs reached before or at the loop limit. At minimum, it would help if this default loop-exploration cutoff did not silently suppress unrelated end-of-function leak reports or definite fourth/fifth-iteration errors.

## Verification

CSA version:

```text
clang version 24.0.0git (https://github.com/llvm/llvm-project.git 1cb7e838cd47ecad4050948c0c907ecb1f466ac3)
```

Contributor guide

Open the contributing guide

Research direction

Start by running the CSA commands against bounded_loop_array.c and bounded_loop_leak.cpp, comparing default analysis with unroll-loops=true. Trace the analyzer's bounded-loop exploration and end-of-function reporting, then verify that the default configuration reports the definite array overflow, leak, and division case without suppressing existing diagnostics.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, cpp
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.