#1214·littlefs

Strange code in lfs_ctz_traverse triggering clang-analyzer-security.ArrayBound

Author: elupusCreated Jun 22, 2026Updated Jun 22, 2026

I was investigating the warning below (which looks to be a false positive) in lfs_ctz_traverse. I saw something confusing:

int count = 2 - (index & 1);
...
for (int i = 0; i < count-1; i++) {
...
}

As far as my human compiler thinks, count can only ever take the value of 2 or 1. And the for loop will only ever run if count is larger or equal to 2. Which in practice means, this is identical to: if (count == 2) so the loop is mostly confusing?

It seems clang-tidy get confused by this too. I don't fully grasp what the intent here is.

/littlefs/lfs.c:3058:16: warning: Out of bound access to memory after the end of 'heads' [clang-analyzer-security.ArrayBound]
 3058 |         head = heads[count-1];
      |                ^~~~~~~~~~~~~~
/littlefs/lfs.c:3024:9: note: Assuming 'size' is not equal to 0
 3024 |     if (size == 0) {
      |         ^~~~~~~~~
/littlefs/lfs.c:3024:5: note: Taking false branch
 3024 |     if (size == 0) {
      |     ^
/littlefs/lfs.c:3030:5: note: Loop condition is true.  Entering loop body
 3030 |     while (true) {
      |     ^
/littlefs/lfs.c:3032:13: note: Assuming 'err' is 0
 3032 |         if (err) {
      |             ^~~
/littlefs/lfs.c:3032:9: note: Taking false branch
 3032 |         if (err) {
      |         ^
/littlefs/lfs.c:3036:13: note: Assuming 'index' is not equal to 0
 3036 |         if (index == 0) {
      |             ^~~~~~~~~~
/littlefs/lfs.c:3036:9: note: Taking false branch
 3036 |         if (index == 0) {
      |         ^
/littlefs/lfs.c:3047:13: note: Assuming 'err' is 0
 3047 |         if (err) {
      |             ^~~
/littlefs/lfs.c:3047:9: note: Taking false branch
 3047 |         if (err) {
      |         ^
/littlefs/lfs.c:3051:25: note: Assuming the condition is true
 3051 |         for (int i = 0; i < count-1; i++) {
      |                         ^~~~~~~~~~~
/littlefs/lfs.c:3051:9: note: Loop condition is true.  Entering loop body
 3051 |         for (int i = 0; i < count-1; i++) {
      |         ^
/littlefs/lfs.c:3053:17: note: Assuming 'err' is 0
 3053 |             if (err) {
      |                 ^~~
/littlefs/lfs.c:3053:13: note: Taking false branch
 3053 |             if (err) {
      |             ^
/littlefs/lfs.c:3051:25: note: Assuming the condition is true
 3051 |         for (int i = 0; i < count-1; i++) {
      |                         ^~~~~~~~~~~
/littlefs/lfs.c:3051:9: note: Loop condition is true.  Entering loop body
 3051 |         for (int i = 0; i < count-1; i++) {
      |         ^
/littlefs/lfs.c:3053:17: note: Assuming 'err' is 0
 3053 |             if (err) {
      |                 ^~~
/littlefs/lfs.c:3053:13: note: Taking false branch
 3053 |             if (err) {
      |             ^
/littlefs/lfs.c:3051:25: note: Assuming the condition is false
 3051 |         for (int i = 0; i < count-1; i++) {
      |                         ^~~~~~~~~~~
/littlefs/lfs.c:3051:9: note: Loop condition is false. Execution continues on line 3058
 3051 |         for (int i = 0; i < count-1; i++) {
      |         ^
/littlefs/lfs.c:3058:16: note: Access of 'heads' at index 2, while it holds only 2 'unsigned int' elements
 3058 |         head = heads[count-1];
      |                ^~~~~~~~~~~~~~

Source: littlefs-project/littlefs