I am not using Pelles C 10.006, I am using Pelles C 11.00
I am also not using any project file, I am invoking the binary tools directly from the cmdline.
At this point, how you choose to interpret what precisely this bug is, is irrelevant. The fact is, I will show that certain changes to code, which
should not result in any changes in output, nevertheless do so. Where
precisely the error lies is not a matter of concern to me, it suffices that I have identified the narrow area and steps for reproducing it.
The warnings about terminating nuls in buffers are irrelevant, I have constructed and initialized this array very specifically to set up this example.
Let me lay out the behavior exhibited by variants of this code very carefully. Here is the initial version of my build script, a very small one constructed specifically for showing this bug:
@echo off
set PC=C:\Program Files\PellesC
set PATH=%PATH%;%PC%\Bin
pocc /std:C17 /Tx64-coff /Ze /Zx /J /I "%PC%\Include" test.c
polink /MACHINE:X64 /SUBSYSTEM:CONSOLE "/LIBPATH:%PC%\Lib" "/LIBPATH:%PC%\Lib\Win64" test.obj
Note the
lack of the
/Ot flag when compiling.
And this is the code I am using, specifically to demonstrate this bug:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void addintlen( char *form )
{
size_t l = strlen(form);
char spec = form[ l - 1 ];
strcpy( form+l-1, "l" );
//form[ l + sizeof("l") - 2 ] = spec;
//form[ l + sizeof("l") - 1 ] = '\0';
};
int main ( int argc, char *argv[ argc ] )
{
char buf[4] = "%i\0\0";
addintlen( buf );
fputs( "String in buf is: \"", stdout );
fwrite( buf, 1, 4, stdout );
fputs( "\"\n", stdout );
return EXIT_SUCCESS;
};
Note that the two given lines are commented-out.
I will now lay out several variants on compiler flags and source code modifications, and show how they change the output.
The
expected output is:
String in buf is: "%l "Now, under four scenarios, the output is:
- No changes: String in buf is: "%l "
- The line #pragma intrinsic( strcpy ) added to the source: String in buf is: "%l "
- The flag /Ot added to compiler options: String in buf is: "%l "
- The flat /Ot added to compiler options and line #pragma function( strcpy ) added to source: String in buf is: "%l "
Note that in this case, all outputs are the same.
Now, as before, but this time, those two commented-out lines are un-commented. The expected output for all of them would be:
String in buf is: "%li "Now, build and run with the same four scenarios as before:
- No changes: String in buf is: "%li "
- The line #pragma intrinsic( strcpy ) added to the source: String in buf is: "%li "
- The flag /Ot added to compiler options: String in buf is: "l "
- The flag /Ot added to compiler options and line #pragma function( strcpy ) added to source: String in buf is: "%li "
Note the change in that
third case, where speed optimization is enabled, and the compiler has not been forbidden from inlining
strcpy(). The output changes compared to other scenarios, when it should not. This mere fact is sufficient proof that a bug is present.