C++ library issue. Using showbase with ostreams causes truncation of unsigned long long when output format is octal. #include <iostream> #include <iomanip> int main(int argc, char *argv[]) { std::cout << std::oct; std::cout << std::numeric_limits<unsigned long long>::max() << '\n'; std::cout << std::showbase << std::numeric_limits<unsigned long long>::max() << '\n'; return 0; } Outputs: 1777777777777777777777 0177777777777777777777 Problem exists for 10.3-PRERELEASE r296556 for amd64 as well as 11.0-CURRENT r292991 for arm.
I've checked this. I figured out it happens for all ::max() ones, seems because of "this->fill()". This could be changed easily, though i think we should see which is the better (standard) behavior (use fill in all cases or exclude showbase case) ? this is the code i talking based on(contrib/libc++/include/ostream): <code> template <class _CharT, class _Traits> basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(unsigned long long __n) { #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS sentry __s(*this); if (__s) { typedef num_put<char_type, ostreambuf_iterator<char_type, traits_type> > _Fp; const _Fp& __f = use_facet<_Fp>(this->getloc()); if (__f.put(*this, *this, this->fill(), __n).failed()) this->setstate(ios_base::badbit | ios_base::failbit); } #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { this->__set_badbit_and_consider_rethrow(); } #endif // _LIBCPP_NO_EXCEPTIONS return *this; } </code> regards, Mokhi.
Created attachment 168073 [details] patch for contrib/libc++/include/locale Potenital patch for this bug.
Comment on attachment 168073 [details] patch for contrib/libc++/include/locale The issue I see is that __nbuf was too small by 1, causing snprintf_l() to truncate the output. My fix isn't pretty but appears to address the issue.
Created attachment 168074 [details] new patch that fixes both unsigned long and unsigned long long New patch that includes same fix for unsigned long as original patch for unsigned long long.
It's been a year and some of my library unit tests continue to fail due to this bug. Can we get the patch committed so I don't have to keep applying it on our machines? Do I need to change the Component in the bug?
Hi, CC'ing dim@ on this -- he's committed some libc++ bits, might be able to provide you with some direction.
Thanks Kyle, I appreciate it!
I'm looking at the problem now. I still don't fully understand how this code operates, as my attempts at debugging it have failed until now. In any case, it is definitely a bug, but before applying any patches, I would rather like to discuss it with upstream.
I have submitted an upstream review here: https://reviews.llvm.org/D32670
A commit references this bug: Author: dim Date: Sat May 6 21:43:55 UTC 2017 New revision: 317888 URL: https://svnweb.freebsd.org/changeset/base/317888 Log: Pull in r302362 from upstream libc++ trunk (by me): Ensure showbase does not overflow do_put buffers Summary: In https://bugs.freebsd.org/207918, Daniel McRobb describes how using std::showbase with ostreams can cause truncation of unsigned long long when output format is octal. In fact, this can even happen with unsigned int and unsigned long. To ensure this does not happen, add one additional character to the do_put buffers if std::showbase is on. Also add a test case. Reviewers: EricWF, mclow.lists Reviewed By: EricWF Subscribers: cfe-commits, emaste Differential Revision: https://reviews.llvm.org/D32670 PR: 207918 MFC after: 3 days Changes: head/contrib/libc++/include/locale
Thanks!
A commit references this bug: Author: dim Date: Tue May 9 16:58:09 UTC 2017 New revision: 318031 URL: https://svnweb.freebsd.org/changeset/base/318031 Log: MFC r317888 and two upstream prerequisites: Pull in r227097 from upstream libc++ trunk (by Marshall Clow): Fix PR21428. Buffer was one byte too small in octal formatting case. Add test Pull in r268009 from upstream libc++ trunk (by Eric Fiselier): Fix PR21428 for long. Buffer was one byte too small in octal formatting case. Rename previously added test Pull in r302362 from upstream libc++ trunk (by me): Ensure showbase does not overflow do_put buffers Summary: In https://bugs.freebsd.org/207918, Daniel McRobb describes how using std::showbase with ostreams can cause truncation of unsigned long long when output format is octal. In fact, this can even happen with unsigned int and unsigned long. To ensure this does not happen, add one additional character to the do_put buffers if std::showbase is on. Also add a test case. Reviewers: EricWF, mclow.lists Reviewed By: EricWF Subscribers: cfe-commits, emaste Differential Revision: https://reviews.llvm.org/D32670 PR: 207918 Changes: _U stable/10/ stable/10/contrib/libc++/include/locale
A commit references this bug: Author: dim Date: Tue May 9 17:01:25 UTC 2017 New revision: 318032 URL: https://svnweb.freebsd.org/changeset/base/318032 Log: MFC r317888: Pull in r302362 from upstream libc++ trunk (by me): Ensure showbase does not overflow do_put buffers Summary: In https://bugs.freebsd.org/207918, Daniel McRobb describes how using std::showbase with ostreams can cause truncation of unsigned long long when output format is octal. In fact, this can even happen with unsigned int and unsigned long. To ensure this does not happen, add one additional character to the do_put buffers if std::showbase is on. Also add a test case. Reviewers: EricWF, mclow.lists Reviewed By: EricWF Subscribers: cfe-commits, emaste Differential Revision: https://reviews.llvm.org/D32670 PR: 207918 Changes: _U stable/11/ stable/11/contrib/libc++/include/locale