Bruno Haible <[email protected]> writes:
> Using the modified test program:
>
> #include <stdio.h>
> int
> main (void)
> {
> fprintf (stdout, "%s", NULL);
> fprintf (stdout, "\n");
> return 0;
> }
>
> On GNU/Linux:
>
> $ gcc foo.c
> $ ./a.out
> Segmentation fault (core dumped)
> $ nm a.out | grep ' U '
> U fputc@GLIBC_2.2.5
> U fputs@GLIBC_2.2.5
> U __libc_start_main@GLIBC_2.34
>
> So, due to GCC optimizations, using NULL as argument for %s is unreliable
> even on systems with glibc.
Interesting. Based on the comment above the function that performs this
optimization, this seems like a bug [1]:
/* Fold a call to the {,v}fprintf{,_unlocked} and __{,v}printf_chk builtins.
FP, FMT, and ARG are the arguments to the call. We don't fold calls with
more than 3 arguments, and ARG may be null in the 2-argument case.
Return NULL_TREE if no simplification was possible, otherwise return the
simplified form of the call as a tree. FCODE is the BUILT_IN_*
code of the function to be simplified. */
Later below, it looks like there is an attempt to check if the argument
is NULL:
/* If the format specifier was "%s", call __builtin_fputs (arg, fp). */
else if (strcmp (fmt_str, target_percent_s) == 0)
{
if (!arg || ! POINTER_TYPE_P (TREE_TYPE (arg)))
return false;
>> However, it appears the m4/*printf.m4 files do not check for the
>> behavior so we cannot depend on it.
>>
>> Bruno, do you recall if this was intentional? Or do you think it should
>> be added?
>
> It is intentional, because that glibc feature is not specified by POSIX.
> It should not be added, because you can't rely on it anyway, due to GCC
> optimizations.
Yes, even if it is a bug every GCC version behaves that way. So lets
leave it as is.
Collin
[1] https://github.com/gcc-mirror/gcc/blob/master/gcc/gimple-fold.cc#L3755