FastCGI-Archives / fcgi2

FastCGI.com fcgi2 Development Kit fork from http://repo.or.cz/fcgi2.git + last snapshot
Other
219 stars 73 forks source link

Modern printf format length modifiers lead to garbage output #64

Open LeSpocky opened 1 year ago

LeSpocky commented 1 year ago

C99 introduced new length modifiers. In addition to the well known and supported 'l', 'L', and 'h' we have 'hh', 'll', 'j', 'z', and 't' now. (See https://en.cppreference.com/w/c/io/fprintf for reference for example.) Those are not supported by fcgi, however the compiler supporting C99 or newer happily allows to use them without warning. The output is cut off however at the unknown length modifier.

Code example:

#include <fcgi_stdio.h>
#include <stddef.h>

int main( int argc, char *argv[] )
{
    size_t zcntp = 0;

    while ( FCGI_Accept() >= 0 )
    {
        printf( "Content-type: text/html\r\n" 
                "\r\n" );

        puts( "<html><head><title>test fastcgi</title></head><body>" );
        printf( "<p>size_t count (printf): %zu.</p>\n", ++zcntp );
        puts( "</body></html>" );

        fprintf( stderr, "zcntp: %zu\n", zcntp );
    }

    FCGI_Finish();

    return 0;
}

In the printf() statement the output is cut off at the '%' and you'll never see the .</p>\n in the output. The output to stderr is also cut off like this without printing any number: "zcntp: "

mcarbonneaux commented 1 year ago

for me is not dependant of fcgi, is dependant of the compiler you use.

LeSpocky commented 1 year ago

for me is not dependant of fcgi, is dependant of the compiler you use.

Not really. It depends on what C dialect you instruct your compiler to use and what's the default of the compiler. Speaking of GCC, according to https://stackoverflow.com/a/14737642 and the manual C11 (implying the older C99) is default since GCC 5.5 which was released in 2017.

I would assume most C code written today uses at least some features of C99. So from my point of view a library not supporting an over 20 years old language standard, is buggy.

(FWIW, I do not expect anyone to fix this. You can consider the ticket be the public documentation of what happens, so other users can find the information and don't have to dig by themselves.)

mcarbonneaux commented 1 year ago

is what is say, is dependent of the compiler/compiler options or define that interfere on compiler compliance. perhaps the automake/autoconfig system used by fcgi build set bad options to the compiler... or set some define (in includes) that interfere on C compliance of the compiler...

you tried to do something like that:

export CFLAGS="-std=c99"
export CC="gcc"

make 

cf: https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html

LeSpocky commented 1 year ago

It's not about the options used to build fcgi itself. This works, I don't care about those. It is about the options I build my own application with, which I link against libfcgi then.

The special thing libfcgi does is replacing stuff by its own implementations which is usually in the libc. This is the way to go explained in fcgi documentation especially if you migrate cgi code to libfcgi. You should not include stdio.h but fcgi_stdio.h as written here: https://fastcgi-archives.github.io/fcgi2/doc/fcgi-devel-kit.htm#S3

If I build my own application with C99 or newer now (Note: this is default with any recent compiler, gcc switched to C11 by default with version 5 released back in 2015), and link that application to libfcgi, the compiler will happily do so without complaining. If I use the above mentioned C99 format specifiers in my app code, libfcgi will produce wrong results at runtime.

In other words: if I start a new webapp today and build and link it against a probably pre-built libfcgi (like libfcgi-dev from Debian) with default compiler options, I will sooner or later run into this problem.

I see several solutions to this:

I don't say this is easy and I don't demand a fix from anyone. However I still consider this a problem users of fcgi should be aware of. :smiley: