[libc++] gets removed from C11

Please review the enclosed patch which guards against the removal of gets from <stdio.h> in C11 and addresses:

http://llvm.org/bugs/show_bug.cgi?id=16369

The current patch is known to be correct only on __APPLE__. I need help from those testing libc++ on other platforms. Specifically, <__config> now has:

+#ifdef __APPLE__
+#define _LIBCPP_HAS_GETS
+#endif

which causes <cstdio> to expose gets:

+#ifdef _LIBCPP_HAS_GETS
using ::gets;
+#endif

I need to know what other platforms (and possibly under what circumstances) should define _LIBCPP_HAS_GETS. Patches to <__config> in reply to this request for a review are welcome. It would be nice to not break others when checking in the fix for http://llvm.org/bugs/show_bug.cgi?id=16369.

Thanks,
Howard

gets.patch (2.62 KB)

Why not to remove ::gets ?

Two reasons, in order of importance:

1. libc++ currently has clients using it.
2. gets is required by C++11, which references C99, not C11.

Howard

Two reasons, in order of importance:

1. libc++ currently has clients using it.

The early they fail, the better :slight_smile:

2. gets is required by C++11, which references C99, not C11.

I heard it was deprecated in C++

In any case, using gets() is crazy.

Conforming implementations must provide deprecated features.

Howard

I wonder if this approach is backwards. A <stdio.h> should provide
gets unless it's in C11 mode. No C++ mode is C11, so if the
implementation fails to provide gets in C++, then it's broken. Perhaps
we should blacklist the broken implementations instead of whitelist
the known-working ones?

+1

BTW, which libc we are talking about?

glibc looks good [1]

[1] http://sourceware.org/git/?p=glibc.git;a=blob;f=libio/stdio.h;h=28c98e9163758e56585ff94787a802fe0b54a325;hb=c3a87236702cb73be1dada3438bbd3c3934e83f8#l631

Not to me. They remove the function in C++14 mode, for some reason.

Removing gets() only breaks API, not ABI. If someone really wants
(WTF?) to use it he can declare it in sources.

AFAIK, each of C++ libraries does not support entire standards (C++03, C++11)
and gets() is not the goal worth striving for.

It even does not worth such a long discussion.
If it stopped work, just throw it away and forget about it. It's toxic.

Consider this: Ultimately, the fewer customization flags the better. And eventually gets() will disappear everywhere. When that happens, use of _LIBCPP_HAS_GETS will disappear too, and so it can be removed since no platform will be defining it.

As each platform drops gets(), and thus stops defining _LIBCPP_HAS_GETS, we will discover at that time if any clients on that platform have been testing _LIBCPP_HAS_GETS and actually need it to be defined. Each platform can deal with that as part of their plan on removing gets().

If we reverse the flag, _LIBCPP_DOES_NOT_HAVE_GETS will be used by everyone when gets() disappears everywhere. This will make it harder to remove from libc++ because since every platform uses it, every platform's clients could also be testing against _LIBCPP_DOES_NOT_HAVE_GETS.

Howard

gets should not disappear if <stdio.h> is included in C++98 or C++11
mode. If it does, that's a bug; it isn't platforms slowly adopting a
feature. glibc had that bug for two months (as far as I can tell, it
never made it into a glibc release), and have already fixed it:

  http://sourceware.org/git/?p=glibc.git;a=commitdiff;h=c6e013c15e0091edc49affd6ce26562845000dcd

Punishing all platforms for a glibc bug which is already fixed (and
was never in a glibc release) doesn't seem reasonable, not matter how
bad we all agree "gets" is.

Maybe declare gets yourself, #if __GLIBC__ == 2 && __GLIBC_MINOR__ ==
15. This approximately matches how libstdc++ works around the glibc
bug.

Separately, we should push for 'gets' to be removed from C++14
(someone needs to file a national body comment for that), and then
libc++ should provide its using declaration whenever __cplusplus <=
201103L (with a workaround for the broken glibc version as above). If
we don't do this, then we're going to need to work around the glibc
bug in C++14 mode too (where, again, it doesn't declare gets).

Please review the enclosed patch which guards against the removal of gets from <stdio.h> in C11 and addresses:

http://llvm.org/bugs/show_bug.cgi?id=16369

The current patch is known to be correct only on __APPLE__. I need help from those testing libc++ on other platforms. Specifically, <__config> now has:

+#ifdef __APPLE__
+#define _LIBCPP_HAS_GETS
+#endif

which causes <cstdio> to expose gets:

+#ifdef _LIBCPP_HAS_GETS
using ::gets;
+#endif

I need to know what other platforms (and possibly under what circumstances) should define _LIBCPP_HAS_GETS. Patches to <__config> in reply to this request for a review are welcome. It would be nice to not break others when checking in the fix for http://llvm.org/bugs/show_bug.cgi?id=16369.

I wonder if this approach is backwards. A <stdio.h> should provide
gets unless it's in C11 mode. No C++ mode is C11, so if the
implementation fails to provide gets in C++, then it's broken. Perhaps
we should blacklist the broken implementations instead of whitelist
the known-working ones?

Consider this: Ultimately, the fewer customization flags the better. And eventually gets() will disappear everywhere. When that happens, use of _LIBCPP_HAS_GETS will disappear too, and so it can be removed since no platform will be defining it.

As each platform drops gets(), and thus stops defining _LIBCPP_HAS_GETS, we will discover at that time if any clients on that platform have been testing _LIBCPP_HAS_GETS and actually need it to be defined. Each platform can deal with that as part of their plan on removing gets().

If we reverse the flag, _LIBCPP_DOES_NOT_HAVE_GETS will be used by everyone when gets() disappears everywhere. This will make it harder to remove from libc++ because since every platform uses it, every platform's clients could also be testing against _LIBCPP_DOES_NOT_HAVE_GETS.

gets should not disappear if <stdio.h> is included in C++98 or C++11
mode. If it does, that's a bug; it isn't platforms slowly adopting a
feature.

I completely agree.

glibc had that bug for two months (as far as I can tell, it
never made it into a glibc release), and have already fixed it:

http://sourceware.org/git/?p=glibc.git;a=commitdiff;h=c6e013c15e0091edc49affd6ce26562845000dcd

Punishing all platforms for a glibc bug which is already fixed (and
was never in a glibc release) doesn't seem reasonable, not matter how
bad we all agree "gets" is.

I should've defined what I meant by "ultimately". I'm thinking long term ... decades. In 2033 clang and libc++ might decide they no longer want to support C++11 (for example). If not 2033, maybe 2050. At some point in the future, I hope that clang and libc++ will still be going, but they will care less about the standards we are supporting today, which will surely have been superseded by future standards.

I agree that asking other platforms to define _LIBCPP_HAS_GETS is a bit of a pain. But I wouldn't call it punishment. And the trend, looking decades into the future, is that the requirement for _LIBCPP_HAS_GETS will decrease, not increase. If you do think of this as punishment, then if we reverse the flag, the punishment increases over time, not decreases.

Either way, I don't think it is the end of the world. We have lots of configuration flags and we will never get to a point where we don't need them. I just like to define them in such a way that the need for the flag decreases as time moves on, as opposed to increases. This is the same thinking behind _LIBCPP_HAS_NO_NULLPTR, as opposed to _LIBCPP_HAS_NULLPTR. Eventually no platform will care to define _LIBCPP_HAS_NO_NULLPTR and maybe we can get rid of it. Probably won't happen until after I retire...

Maybe declare gets yourself, #if __GLIBC__ == 2 && __GLIBC_MINOR__ ==
15. This approximately matches how libstdc++ works around the glibc
bug.

Separately, we should push for 'gets' to be removed from C++14
(someone needs to file a national body comment for that), and then
libc++ should provide its using declaration whenever __cplusplus <=
201103L (with a workaround for the broken glibc version as above). If
we don't do this, then we're going to need to work around the glibc
bug in C++14 mode too (where, again, it doesn't declare gets).

Agreed. But I think it is too late, at least for US delegates, unless someone already did it. The deadline for US comments was yesterday.

Howard

Does that include C11 Annex K's Bounds Checking Interfaces (ISO/IEC TR
24731-1 and friends)?

If memory serves, me, one of the libc maintainers did not incorporate
them because he felt they were "horribly inefficient BSD crap." He
also felt developers should "learn to use the existing functions
properly [sic]."

We were recently reminded what happens in that case: tens to hundreds
of millions of embedded devices (mobile devices, home routers and
gateways, et al) with security related defects (some of which will
never be patched). Confer: CVE-2012-5959, CVE-2012-5960,
CVE-2012-5961, CVE-2012-5962, CVE-2012-5963, CVE-2012-5964,
CVE-2012-5965 – collectively known as “libupnp Multiple Buffer
Overflow Vulnerabilities."

Jeff

UK is still accepting ballot comments; I've added this one to the list.