Ambiguous interpretation of -1 among char_traits::eof, char_traits::to_int_type and streambuf::underflow

Brent Lewis coder0xff@gmail.com
Tue Feb 11 00:26:00 GMT 2014


In certain circumstances, a 0xFF read from a stream buffer may be
erroneously interpreted as the EOF value.

Example from boost iostreams (
iostreams\detail\streambuf\indirect_streambuf.hpp ) :

template<typename T, typename Tr, typename Alloc, typename Mode>
typename indirect_streambuf<T, Tr, Alloc, Mode>::int_type
indirect_streambuf<T, Tr, Alloc, Mode>::underflow()
{
    //... code removed for brevity
    return chars != 0 ?
    traits_type::to_int_type(*gptr()) :
    traits_type::eof();
}

In the event that the parameter to to_int_type is a signed char (which
is the case with istream) with the value -1, sign extension will cause
it to return (int_type) -1. Thusly, when underflow() is called by

std::basic_streambuf<signed char, std::char_traits<signed char> >::uflow()
{
    //...
    int_type __ret = traits_type::eof();
    const bool __testeof = traits_type::eq_int_type(this->underflow(), __ret);
    //...
}

It erroneously interprets this -1 as eof.

Though not optimal, a possible workaround is to ensure EOF is a value
that is not ambiguous. In char_traits.h:

template<typename _CharT>
struct char_traits {
    //...
    static _GLIBCXX_CONSTEXPR int_type
    eof() { //if char_type is signed, to_int_type may return -1, so -1
is NOT a suitable value for EOF
static_assert(sizeof(char_type) < sizeof(int_type), "Please choose a
char_type with a size that is smaller than int_type.");
        return static_cast<int_type>(std::numeric_limits<int_type>::max());
    }
}

and whatever other corresponding changes might need to be made.
Perhaps instead, changing the EOF define would be enough. Another
solution might be to make char_traits::to_int_type circumvent sign
extension, so (char)-1 becomes (int)255, though once again I don't
know what implications this might have elsewhere.

In my case (on Android using boost) 4kb are read for each underflow,
so the 0xFF has to fall exactly on one of these boundaries for the
buggy behavior to be occur.



More information about the Libstdc++ mailing list