3

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!

Tom Zych
  • 13,329
  • 9
  • 36
  • 53
  • 6
    Upgrade your compiler to [GCC 5](http://gcc.gnu.org/gcc-5/) and use `gcc -Wall -Wextra -g -std=c11` ; you might also need to upgrade your `libc` which practically means updating your Linux distribution to a recent one – Basile Starynkevitch Jan 09 '16 at 16:37
  • Anything post gcc 4.6 will warn about `gets` with warnings enabled as explained above. – David C. Rankin Jan 09 '16 at 16:39
  • 1
    @DavidC.Rankin But this is gcc 4.7.2 and it doesn’t warn, even with the set of flags that Basile provided above. – Tom Zych Jan 09 '16 at 16:42
  • It’s really strange that 4.7 doesn’t warn about this ... I know 4.7 is pretty old, but we’ve known about the problem with `gets()` since the 80’s. Did they really not think to add a warning? Shucks, I seem to remember getting compiler warnings about it years ago. – Tom Zych Jan 09 '16 at 16:52
  • 3
    It's not about the compiler but about your C library. GCC doesn't ship with a C library. Current versions of glibc ship with a gets annotated with a deprecation attribute. (And there's something going on at link time too, you also get a warning from the linker.) – Mat Jan 09 '16 at 16:55
  • 1
    I get the warning on my system with gcc 4.8.4. `/usr/include/stdio.h` has `__attribute_deprecated__` on its declaration of `gets`. Does your `/usr/include/stdio.h` have that? – Keith Thompson Jan 09 '16 at 22:27
  • @KeithThompson: Interesting! It does not. See edited question for full reply. – Tom Zych Jan 09 '16 at 23:00
  • What version of Debian are you running? What does `dpkg -S /usr/include/stdio.h` say? – Keith Thompson Jan 10 '16 at 01:16
  • @KeithThompson: Oho! Wheezy, and the package is libc6-dev:i386. `apt-cache show` reveals that my libc6-dev was based on **eglibc**, the Embedded GNU C library, a now-abandoned project. Apparently Debian switched to this in 2009 and used it for Debian 6 and 7, but is now back to glibc. Perhaps the eglibc project removed the warning? Can’t find anything. This may be the “fork” I was thinking of, though it wasn’t exactly a fork. – Tom Zych Jan 10 '16 at 02:05
  • And you don't get the separate link-time error either? The linker `ld` is part of the `binutils` package. I don't know how it decides to warn that `gets` "is dangerous and should not be used" (even after searching the source for that message). – Keith Thompson Jan 10 '16 at 02:26
  • @KeithThompson No, the linker doesn't emit any warnings. – Tom Zych Jan 10 '16 at 02:39

1 Answers1

5

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.

kfx
  • 8,136
  • 3
  • 28
  • 52
  • Just the standard library that Debian installed, haven’t done anything special. And the install was done less than two years ago. I suppose I should report it as a bug to Debian. – Tom Zych Jan 09 '16 at 17:20
  • gcc prints the warning in response to an annotation in glibc's `stdio.h`. – Keith Thompson Jan 09 '16 at 22:24
  • @KeithThompson Actually, gcc prints a *different* warning — see my edit. Perhaps there’s a special attribute such as `__dangerous__` or perhaps it’s *ad hoc* code. – Tom Zych Jan 10 '16 at 00:56
  • There's one warning printed by the compiler in response to the annotation on the declaration of `gets`, and a distinct warning produced by the linker. – Keith Thompson Jan 10 '16 at 01:23
  • Seems that the library was just built that way, for some reason. See my second edit to the question for details. Thanks for the answer. – Tom Zych Jan 10 '16 at 16:30