Bug 207918 - C++ ostream operator << broken for unsigned long long when using showbase with octal format
Summary: C++ ostream operator << broken for unsigned long long when using showbase wit...
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: standards (show other bugs)
Version: 10.3-BETA2
Hardware: amd64 Any
: --- Affects Many People
Assignee: freebsd-standards (Nobody)
URL:
Keywords: patch
Depends on:
Blocks:
 
Reported: 2016-03-12 08:27 UTC by Daniel McRobb
Modified: 2017-05-09 17:03 UTC (History)
4 users (show)

See Also:


Attachments
patch for contrib/libc++/include/locale (711 bytes, patch)
2016-03-13 06:54 UTC, Daniel McRobb
no flags Details | Diff
new patch that fixes both unsigned long and unsigned long long (1.15 KB, patch)
2016-03-13 07:06 UTC, Daniel McRobb
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Daniel McRobb 2016-03-12 08:27:14 UTC
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.
Comment 1 Mahdi Mokhtari freebsd_committer freebsd_triage 2016-03-12 09:02:44 UTC
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.
Comment 2 Daniel McRobb 2016-03-13 06:54:37 UTC
Created attachment 168073 [details]
patch for contrib/libc++/include/locale

Potenital patch for this bug.
Comment 3 Daniel McRobb 2016-03-13 06:57:13 UTC
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.
Comment 4 Daniel McRobb 2016-03-13 07:06:21 UTC
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.
Comment 5 Daniel McRobb 2017-04-28 03:47:09 UTC
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?
Comment 6 Kyle Evans freebsd_committer freebsd_triage 2017-04-28 14:32:34 UTC
Hi,

CC'ing dim@ on this -- he's committed some libc++ bits, might be able to provide you with some direction.
Comment 7 Daniel McRobb 2017-04-28 18:25:02 UTC
Thanks Kyle, I appreciate it!
Comment 8 Dimitry Andric freebsd_committer freebsd_triage 2017-04-29 10:54:30 UTC
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.
Comment 9 Dimitry Andric freebsd_committer freebsd_triage 2017-04-29 14:18:25 UTC
I have submitted an upstream review here: https://reviews.llvm.org/D32670
Comment 10 commit-hook freebsd_committer freebsd_triage 2017-05-06 21:44:28 UTC
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
Comment 11 Daniel McRobb 2017-05-06 21:55:53 UTC
Thanks!
Comment 12 commit-hook freebsd_committer freebsd_triage 2017-05-09 16:59:09 UTC
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
Comment 13 commit-hook freebsd_committer freebsd_triage 2017-05-09 17:02:13 UTC
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