From 6251ea15f55ec57d6325c2e37e88b22315aba658 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 6 Aug 2020 16:16:33 +0100 Subject: libstdc++: Adjust overflow prevention to operator>> This adjusts the overflow prevention added to operator>> so that we can distinguish "unknown size" from "zero size", and avoid writing anything at all in to zero sized buffers. This also removes the incorrect comment saying extraction stops at a null byte. libstdc++-v3/ChangeLog: * include/std/istream (operator>>(istream&, char*)): Add attributes to get warnings for pointers that are null or known to point to the end of a buffer. Request upper bound from __builtin_object_size check and handle zero-sized buffer case. (operator>>(istream&, signed char)) (operator>>(istream&, unsigned char*)): Add attributes. * testsuite/27_io/basic_istream/extractors_character/char/overflow.cc: Check extracting into the middle of a buffer. * testsuite/27_io/basic_istream/extractors_character/wchar_t/overflow.cc: New test. --- libstdc++-v3/include/std/istream | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'libstdc++-v3/include/std/istream') diff --git a/libstdc++-v3/include/std/istream b/libstdc++-v3/include/std/istream index cb8e9f8..20a455a 100644 --- a/libstdc++-v3/include/std/istream +++ b/libstdc++-v3/include/std/istream @@ -790,7 +790,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * - `n - 1` characters are stored * - EOF is reached * - the next character is whitespace according to the current locale - * - the next character is a null byte (i.e., `charT()`) * * `width(0)` is then called for the input stream. * @@ -799,25 +798,38 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus <= 201703L template + __attribute__((__nonnull__(2), __access__(__write_only__, 2))) inline basic_istream<_CharT, _Traits>& operator>>(basic_istream<_CharT, _Traits>& __in, _CharT* __s) { - streamsize __n = __builtin_object_size(__s, 2) / sizeof(_CharT); - if (__n == 0) - __n = __gnu_cxx::__numeric_traits::__max / sizeof(_CharT); - std::__istream_extract(__in, __s, __n); + size_t __n = __builtin_object_size(__s, 0); + if (__builtin_expect(__n < sizeof(_CharT), false)) + { + // There is not even space for the required null terminator. + __glibcxx_assert(__n >= sizeof(_CharT)); + __in.width(0); + __in.setstate(ios_base::failbit); + } + else + { + if (__n == (size_t)-1) + __n = __gnu_cxx::__numeric_traits::__max; + std::__istream_extract(__in, __s, __n / sizeof(_CharT)); + } return __in; } template + __attribute__((__nonnull__(2), __access__(__write_only__, 2))) inline basic_istream& operator>>(basic_istream& __in, unsigned char* __s) - { return (__in >> reinterpret_cast(__s)); } + { return __in >> reinterpret_cast(__s); } template + __attribute__((__nonnull__(2), __access__(__write_only__, 2))) inline basic_istream& operator>>(basic_istream& __in, signed char* __s) - { return (__in >> reinterpret_cast(__s)); } + { return __in >> reinterpret_cast(__s); } #else // _GLIBCXX_RESOLVE_LIB_DEFECTS // 2499. operator>>(istream&, char*) makes it hard to avoid buffer overflows -- cgit v1.1