Hello Pelle,
First, thank you for Pelles C — it has just carried a full port of CFITSIO
4.7.0 (NASA's FITS library, 59 sources), zlib, libpng and FFTW 3.3.11 to a
clean finish, so the report below comes from a codebase your compiler
otherwise handles admirably.
SUMMARY
-------
Pelles C 14.50.0 for Windows x64, compiling the attached self-contained
program (about one screen of code), translates the loop
for (i = 0; i < 200; i += 1) {
data = (unsigned char)(i % 256);
}
(over a local unsigned char data[200]) into a loop body whose FIRST
instruction is ud2 , so the program dies with exception 0xC000001D on the
first iteration. The store that follows the trap reads al , which no
instruction in the function ever writes — the value computation has been
deleted entirely. The statement is fully defined ISO C: i is in [0,200),
so i % 256 is well defined and non-negative, the conversion to unsigned
char is well defined, and the store is in bounds.
ENVIRONMENT
-----------
Pelles C 14.50.0, Windows 10 x64 (build 19045)
pocc -Tx64-coff -Ot -W1 -std:C17 -Ze pelle_repro.c
polink -machine:x64 -subsystem:console pelle_repro.obj kernel32.lib
OBSERVED (same source, three settings)
--------------------------------------
-Ot RESULT : EXCEPTION 0xC000001D
-Os RESULT : EXCEPTION 0xC000001D
(no -O...) RESULT : SURVIVED checksum 19900 (expect 19900)
DISASSEMBLY (podump /disasm of the -Ot object, the loop in full)
----------------------------------------------------------------
[0050] 0F0B ud2
[0052] 4863D3 movsxd rdx,ebx
[0055] 888414EC000000 mov byte ptr [rsp+rdx+0ECh],al
[005C] 83C301 add ebx,1
[005F] 81FBC8000000 cmp ebx,0C8h
[0065] 7CE9 jl 0050
NOTES THAT MAY HELP LOCATE IT
-----------------------------
1. The mistranslation is sensitive to the surrounding frame: the identical
loop in a different function (static buffer, checksum in a separate
loop) compiles correctly at -Ot on the same machine. The attached
reproducer therefore keeps the exact frame of the function in which the
fault was first observed — the same locals in the same order, and calls
through a volatile function pointer where the original code called into
a library. Simplifying the frame may make the fault vanish.
2. The pattern (unsigned char)(expr % 256) appears in a dozen other files
of the same project that compile correctly, consistent with note 1.
3. Discovered because a unit test of the CFITSIO port died with
"CRT: unhandled exception" before its first library call; an
__try/__except wrapper reported 0xC000001D, and podump named the ud2.
A SECOND, UNRELATED ISSUE, MENTIONED FOR COMPLETENESS
-----------------------------------------------------
The same project also hit what the evidence indicates is a stack-slot
assignment fault at -Ot in one large function of CFITSIO's imcompress.c:
two live locals (a 4-byte char array, address escaping through a pointer
array, and a 12-byte char array) appear to have shared storage, so a
12-byte strcpy destroyed the 4-byte string; rearranging the locals into
one union cured it. An isolated replica of the declarations does NOT
reproduce it — the full function seems to be needed — so I am not
attaching that one until it has a reproducer worth your time. I can supply
the full analysis on request.
With thanks and best regards,
Kelly
Attachment: pelle_repro.c