Bug 50722

Summary: istrstream extraction not working properly
Product: [Retired] Red Hat Linux Reporter: Jon Gjerde <jo-gjerd>
Component: gccAssignee: Jakub Jelinek <jakub>
Status: CLOSED UPSTREAM QA Contact: David Lawrence <dkl>
Severity: medium Docs Contact:
Priority: medium    
Version: 7.1   
Target Milestone: ---   
Target Release: ---   
Hardware: i386   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2004-10-01 15:36:55 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Jon Gjerde 2001-08-02 16:04:20 UTC
From Bugzilla Helper:
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0b; Windows 98)

Description of problem:
Extraction of a double variable from a istrstream consisting of a single 
char should set fail() and ios::failbit. The string "i" and "s" give 
different results!

How reproducible:
Always

Steps to Reproduce:
1.See program below in additional information
2.
3.
	

Actual Results:  if string = "i", result = 2 0;
if string = "s", result = 2 2;

Additional info:

istrstream a("i");
double b;
a>>b;
cout<<ios::failbit<<" "<<a.fail()<<endl;

(Run, look at the result, then change to a("s")).

Comment 1 Jakub Jelinek 2001-08-08 12:36:42 UTC
It is not that surprising, 'i' is prefix of inf, so in that case it failed
on the EOF condition (eofbit is set), while with "s" it failed already on 's'
character.
Anyway, istream::operator>> should check whether it did not actually scan the
number and set failbit too.
Following patch should do the job:
2001-08-07  Jakub Jelinek  <jakub>

        * iostream.cc (do_scan): New.
        (istream::operator>>(long double &)): Use it.
        (istream::operator>>(double &)): Likewise.
        (istream::operator>>(float &)): Likewise.

        * g++.old-deja/g++.other/failbit1.C: New test.

--- gcc/testsuite/g++.old-deja/g++.other/failbit1.C.jj  Wed Aug  8 14:52:09 2001
+++ gcc/testsuite/g++.old-deja/g++.other/failbit1.C     Wed Aug  8 14:51:12 2001
@@ -0,0 +1,21 @@
+#include <strstream>
+#include <iostream>
+
+extern "C" void abort (void);
+
+using namespace std;
+
+int main(void)
+{
+  istrstream a ("i");
+  istrstream b ("s");
+  double c;
+
+  a >> c;
+  b >> c;
+  if (! a.fail ())
+    abort ();
+  if (! b.fail ())
+    abort ();
+  return 0;
+}
--- libio/iostream.cc.jj        Tue Jul 24 20:40:52 2001
+++ libio/iostream.cc   Wed Aug  8 14:37:14 2001
@@ -361,6 +361,19 @@ READ_INT(unsigned long long)
 READ_INT(bool)
 #endif

+static void do_scan(istream *istr, const char *format, ...)
+{
+  streambuf *_strbuf = istr->_strbuf;
+  va_list ap;
+  va_start(ap, format);
+  int errcode = 0;
+  int count = _IO_vfscanf(_strbuf, format, ap, &errcode);
+  if ((errcode & (_IOS_EOF|_IOS_FAIL)) == _IOS_EOF && count != 1)
+    errcode |= _IOS_FAIL;
+  istr->setstate((ios::iostate)errcode);
+  va_end(ap);
+}
+
 istream& istream::operator>>(long double& x)
 {
     if (ipfx0())
@@ -368,10 +381,10 @@ istream& istream::operator>>(long double
        _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
                                  _strbuf);
 #if _G_HAVE_LONG_DOUBLE_IO
-       scan("%Lg", &x);
+       do_scan(this, "%Lg", &x);
 #else
        double y;
-       scan("%lg", &y);
+       do_scan(this, "%lg", &y);
        x = y;
 #endif
        isfx();
@@ -386,7 +399,7 @@ istream& istream::operator>>(double& x)
       {
        _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
                                  _strbuf);
-       scan("%lg", &x);
+       do_scan(this, "%lg", &x);
        isfx();
        _IO_cleanup_region_end (0);
       }
@@ -399,7 +412,7 @@ istream& istream::operator>>(float& x)
       {
        _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
                                  _strbuf);
-       scan("%g", &x);
+       do_scan(this, "%g", &x);
        isfx();
        _IO_cleanup_region_end (0);
       }

Comment 2 Jakub Jelinek 2001-08-17 16:50:16 UTC
I've added that patch into libstdc++-2.96-96.

Comment 3 Benjamin Kosnik 2004-10-01 15:36:55 UTC
Fixed.