Search code examples
ccompiler-warningsgcc-warninggetsgcc4.7

How to make gcc 4.7 warn about use of the infamous gets() function?


I saw yet another question about C where the code was using gets(), and I commented with the usual warning about never using gets() except when you want to demonstrate how to break security.

This time, I decided to check if my compiler issued a warning about the use of gets(). Of course I expected it would. Has to, right? Even if you don’t specify any warnings?

Imagine my surprise when I found that, not only does the compiler not warn by default, but I couldn’t even figure out how to make it warn!

The compiler in question is gcc 4.7.2 on Debian, and here’s the code I used:

#include <stdio.h>

int main(void)
{
    char s[10];

    gets(s);
    puts(s);

    return 0;
}

Tried gcc g.c. Compiles with no warnings. Runs. Gets a segfault if you enter too much text.

Tried with all the standard warnings I normally put in a makefile:

gcc -W -Wall -Wno-long-long -Wshadow -Wlarger-than-1000 \
-Wpointer-arith -Wbad-function-cast -Wcast-qual -Wcast-align \
-Wconversion -Waggregate-return -Wmissing-prototypes \
-Wmissing-declarations -Wpadded -Wredundant-decls -Wnested-externs g.c

Same result.

Tried with -std=c11. Even that didn’t generate a warning, which is pretty weird, considering gets() doesn’t even exist in C11. Tried c99 too. No warning.

So what’s going on here? Why doesn’t this very widely used compiler warn me when I use the most deprecated function in the entire C language?


EDIT: Acting on Keith Thompson’s suggestion below, I checked for a deprecation attribute in stdio.h. It was not there. I then copied the header file and experimented. Adding either of these strings (which I found in other headers) to the end of the declaration did generate a warning:

__attribute_deprecated__
__attribute__ ((__deprecated__))

The warning:

‘gets’ is deprecated (declared at /usr/include/stdiotz.h:632) [-Wdeprecated-declarations]

To summarize the responses I’ve seen so far, it appears that the version of libc on my system doesn’t include the warning, which does exist in later versions. This is strange, since the warning has existed in some form since at least 1996. I vaguely recall that libc has been forked at least once, so perhaps the warning was left out of one branch significantly later than in other branches.

I think I will ask on the Debian mailing lists about this, and perhaps report it as a bug, depending on what I learn.


EDIT 2: I’ve looked at some source code. glibc has had the warning since 2007 at least, in libio/iogets.c. eglibc 2.13, the one I have, has exactly the same warning code:

#ifdef _LIBC
link_warning (gets, "the `gets' function is dangerous and should not be used.")
#endif

I suppose _LIBC wasn’t defined when the library was compiled. Why, I don’t know. I’m not sure what the purpose of _LIBC is.

So, the answer seems to come down to “It’s the library, and for whatever reason, in their wisdom, the Debian developer responsible for it compiled it that way.” We may never know why.

Not going to report it as a bug, since I’m using oldstable. Might bring it up if it’s still that way after my next upgrade.

Thanks, everyone, for your informative responses!


Solution

  • It's not the GCC that includes this warning message, it's the GLIBC.

    It's unlikely that you're using too old version of GLIBC: the warning has been around at least since 1996. See the line 67 of this GLIBC code on GitHub for an example (note the date: 15 Dec 1996):

    link_warning (gets, "the `gets' function is dangerous and should not be used.")
    

    Most likely you're using a different C library.