https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104789

--- Comment #7 from Rémi Verschelde <rverschelde at gmail dot com> ---
Took me a while, but I was able to make a proper reduced testcase by cutting
down the Godot case to the very minimal.

It's a bit convoluted (and the code doesn't make any sense anymore), but the
complexity seems to trigger the false positive I intended to report originally.

```
$ cat godot-stringop.cpp
#include <cstdint>
#include <vector>

uint32_t components = 3;

void commit_temp_packets() {
        // Should be sufficient?
        if (components > 3) { return; }

        uint8_t header[8];
        uint32_t header_bytes = 0;
        for (uint32_t i = 0; i < components; i++) {
                header_bytes += 2;
        }

        uint32_t max_shifts[3] = { 0, 0, 0 };

        for (uint32_t i = 1; i < 2; i++) {
                for (uint32_t j = 0; j < components; j++) {
                        max_shifts[j] = 1;
                }
        }
        header_bytes += 2;

        // Should definitely be sufficient.
        if (header_bytes > 7) { return; }

        while (header_bytes % 4 != 0) {
                header[header_bytes++] = 0;
        }

        std::vector<uint8_t> data;

        for (uint32_t i = 0; i < header_bytes; i++) {
                data.push_back(header[i]);
        }

        uint32_t bit_buffer = 0;
        uint32_t bits_used = 0;

        for (uint32_t i = 1; i < 2; i++) {
                for (uint32_t j = 0; j < components; j++) {
                        bit_buffer |= 1 << bits_used;
                        bits_used += max_shifts[j] + 1;
                        while (bits_used >= 8) {
                                uint8_t byte = bit_buffer & 0xFF;
                                data.push_back(byte);
                                bit_buffer >>= 8;
                                bits_used -= 8;
                        }
                }
        }
}

$ g++ godot-stringop.cpp -c -Werror=all -O3
godot-stringop.cpp: In function ‘void commit_temp_packets()’:
godot-stringop.cpp:29:40: error: writing 1 byte into a region of size 0
[-Werror=stringop-overflow=]
   29 |                 header[header_bytes++] = 0;
      |                 ~~~~~~~~~~~~~~~~~~~~~~~^~~
godot-stringop.cpp:10:17: note: at offset 8 into destination object ‘header’ of
size 8
   10 |         uint8_t header[8];
      |                 ^~~~~~
godot-stringop.cpp:29:40: error: writing 1 byte into a region of size 0
[-Werror=stringop-overflow=]
   29 |                 header[header_bytes++] = 0;
      |                 ~~~~~~~~~~~~~~~~~~~~~~~^~~
godot-stringop.cpp:10:17: note: at offset [9, 11] into destination object
‘header’ of size 8
   10 |         uint8_t header[8];
      |                 ^~~~~~
cc1plus: some warnings being treated as errors
```

Interestingly, there are no changes to `header_bytes` or `components` after
line 29, yet the code that follows seems needed to trigger the warning.

Reply via email to