Hide
The C++11 standard says that the "iterator is always left pointing one position beyond the last character successfully matched." In this case, that's after zero characters, so the iterator should point to the first character, just as the test expects. However, libcxx doesn't do this; it returns the pointer to the end of the string, which is indeed composed of characters that might match a (hex) float, but that's not the final word.
The libc++ code has advanced the iterator to "end," which it should not have done because the input sequence did not match. The test case expects the match to fail, leaving an iterator pointing to something other than "end," and it dereferences the iterator; because the iterator is actually "end", we get a NULL pointer dereference and hilarity ensues.
I claim this is a flaw in the the libc++ implementation.
cutdown test case:
#include <locale>
#include <sstream>
typedef std::char_traits<char> test1;
typedef std::istreambuf_iterator<char, test1> istr_it;
struct mynum : public std::num_get<char, istr_it>
{
iter_type my_do_get(iter_type first, iter_type last, std::ios_base& str,
std::ios_base::iostate& st, bool& val) const
{ return (do_get(first, last, str, st, val)); }
};
int main()
{
mynum my_num_get;
std::ios_base::iostate st = std::ios_base::goodbit;
std::istringstream istr("abcdef");
istr_it first(istr.rdbuf()), last;
st = std::ios_base::goodbit;
double dv = 0;
if(*(first = my_num_get.get(first, last, istr, st, dv)) == 'a')
return 1;
}
Show
The C++11 standard says that the "iterator is always left pointing one position beyond the last character successfully matched." In this case, that's after zero characters, so the iterator should point to the first character, just as the test expects. However, libcxx doesn't do this; it returns the pointer to the end of the string, which is indeed composed of characters that might match a (hex) float, but that's not the final word.
The libc++ code has advanced the iterator to "end," which it should not have done because the input sequence did not match. The test case expects the match to fail, leaving an iterator pointing to something other than "end," and it dereferences the iterator; because the iterator is actually "end", we get a NULL pointer dereference and hilarity ensues.
I claim this is a flaw in the the libc++ implementation.
cutdown test case:
#include <locale>
#include <sstream>
typedef std::char_traits<char> test1;
typedef std::istreambuf_iterator<char, test1> istr_it;
struct mynum : public std::num_get<char, istr_it>
{
iter_type my_do_get(iter_type first, iter_type last, std::ios_base& str,
std::ios_base::iostate& st, bool& val) const
{ return (do_get(first, last, str, st, val)); }
};
int main()
{
mynum my_num_get;
std::ios_base::iostate st = std::ios_base::goodbit;
std::istringstream istr("abcdef");
istr_it first(istr.rdbuf()), last;
st = std::ios_base::goodbit;
double dv = 0;
if(*(first = my_num_get.get(first, last, istr, st, dv)) == 'a')
return 1;
}