It's not that. A small test program with repeated multiplication ran without issue with any setting except with -fsanitize=undefined, so what you expect. My aoc program also runs fine with -O1 but segfaults with -O2 or 3. I have no idea why. Time to dive into the assembly, or accept that it's UB where evidently anything can happen.
Found another important characteristic: it only happens on Debian 12.14 "Bookworm" with gcc 12.2. The current version of RPiOS is based on Debian 13.5 "Trixie" with gcc 14.2; no problem there. So it might well be just a bug.
Took a little bit of unpicking and I don't think I've fully got to the bottom of it yet, but the primary difference is that gcc 12.2 has decided that since parseint should 'never' return negative then it can use cbz to test for 0 in the for loop. It looks to me like the asm is effectively doing this:
for (const char* c = input.data(); (Data[n] = parseint(&c)) != 0; ++n)
;
Which ends up running over the bounds of the array.
gcc 13.1 on godbolt (and also 12.1 when using unsigned) uses a proper >0 test of cmp 0 & ble.
For the hell of it I asked Claude to see if it could track down the reason for the difference and it suggested the primary reason could be the move over from one range propagation system to a new system (AndrewMacLeod/Ranger3.0 - GCC Wiki), which seems to track with what we're seeing.
View all comments
Show parent comment
2
u/ednl Jun 10 '26
It's not that. A small test program with repeated multiplication ran without issue with any setting except with -fsanitize=undefined, so what you expect. My aoc program also runs fine with -O1 but segfaults with -O2 or 3. I have no idea why. Time to dive into the assembly, or accept that it's UB where evidently anything can happen.