diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2020-08-06 16:16:33 +0100 |
---|---|---|
committer | Jonathan Wakely <jwakely@redhat.com> | 2020-08-06 18:26:45 +0100 |
commit | 6251ea15f55ec57d6325c2e37e88b22315aba658 (patch) | |
tree | 0f44c42a6daea85c951e58e781fb2a6c7f4bf37b /libstdc++-v3/include/std/istream | |
parent | 9c376d1c166e7c8b10bba6f1675d2471ffe8447f (diff) | |
download | gcc-6251ea15f55ec57d6325c2e37e88b22315aba658.zip gcc-6251ea15f55ec57d6325c2e37e88b22315aba658.tar.gz gcc-6251ea15f55ec57d6325c2e37e88b22315aba658.tar.bz2 |
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.
Diffstat (limited to 'libstdc++-v3/include/std/istream')
-rw-r--r-- | libstdc++-v3/include/std/istream | 26 |
1 files changed, 19 insertions, 7 deletions
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<typename _CharT, typename _Traits> + __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<streamsize>::__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<streamsize>::__max; + std::__istream_extract(__in, __s, __n / sizeof(_CharT)); + } return __in; } template<class _Traits> + __attribute__((__nonnull__(2), __access__(__write_only__, 2))) inline basic_istream<char, _Traits>& operator>>(basic_istream<char, _Traits>& __in, unsigned char* __s) - { return (__in >> reinterpret_cast<char*>(__s)); } + { return __in >> reinterpret_cast<char*>(__s); } template<class _Traits> + __attribute__((__nonnull__(2), __access__(__write_only__, 2))) inline basic_istream<char, _Traits>& operator>>(basic_istream<char, _Traits>& __in, signed char* __s) - { return (__in >> reinterpret_cast<char*>(__s)); } + { return __in >> reinterpret_cast<char*>(__s); } #else // _GLIBCXX_RESOLVE_LIB_DEFECTS // 2499. operator>>(istream&, char*) makes it hard to avoid buffer overflows |