On Thu, Aug 06, 2020 at 02:14:48PM +0100, Jonathan Wakely wrote: > 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) > { > size_t __n = __builtin_object_size(__s, 0); > if (__builtin_expect(__n < sizeof(_CharT), false)) > { > // not even space for 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; > } > > This will give a -Wstringop-overflow warning at -O0 and then overflow > the buffer, with undefined behaviour. And it will give no warning but > avoid the overflow when optimising. This isn't my preferred outcome, > I'd prefer to always get a warning, *and* be able to avoid the > overflow when optimising and the size is known.
A way to get warning even at -O2 would be to call some external function in the if (__bos0 < sizeof(_CharT)) block, which wouldn't be optimized away and would have __attribute__((warning ("..."))) on it. See e.g. how glibc uses __warndecl e.g. in /usr/include/bits/string_fortified.h. One can use alias attribute to have different warnings for the same external call (which could do e.g. what part of __glibcxx_assert does, call vprintf + abort. Jakub