Package: g++-6
Version: 6.3.0-18+deb9u1
Severity: normal

Dear Maintainer,

*** Reporter, please consider answering these questions, where appropriate ***

   * What led up to the situation?
   * What exactly did you do (or not do) that was effective (or
     ineffective)?
   * What was the outcome of this action?
   * What outcome did you expect instead?

*** End of the template - remove these template lines ***
Lead up: I was testing a program to see whether a user could screw it up.  The
answer was YES, for

I tried opening and reading a directory instead of a file using
std::ifstream.open() and operator >>.

Outcome:

The directory was opened sucessfully (rdstate()==0).
On reading a character using operator >> an error of type
std::ios_base::failure >> was thrown, with
what() == "basic_filebuf::underflow error reading the file: iostream error".
Prior to the read the stream had exceptions() == 0.


Expectation:

The prescribed behaviour (www.cplusplus.com) for ifsteam operator >> is:

Basic guarantee: if an exception is thrown, the object is in a valid state.
It throws an exception of member type failure if the resulting error state flag
is not goodbit and member exceptions was set to throw for that state.
Any exception thrown by an internal operation is caught and handled by the
function, setting badbit. If badbit was set on the last call to exceptions, the
function rethrows the caught exception.

I interpret this to mean that operator >> will not throw unless you tell it to
by setting the exception mask to non-zero (the mask being 0 by default.)
Consequently I expected badbit to be set for the stream, and no exception to be
thrown.

I submit a source file and session log demonstrating the fault.



-- System Information:
Debian Release: 9.7
  APT prefers stable-updates
  APT policy: (500, 'stable-updates'), (500, 'stable')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 4.9.0-8-amd64 (SMP w/8 CPU cores)
Locale: LANG=en_NZ.utf8, LC_CTYPE=en_NZ.utf8 (charmap=UTF-8),
LANGUAGE=en_NZ.utf8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)

Versions of packages g++-6 depends on:
ii  gcc-6            6.3.0-18+deb9u1
ii  gcc-6-base       6.3.0-18+deb9u1
ii  libc6            2.24-11+deb9u3
ii  libgmp10         2:6.1.2+dfsg-1
ii  libisl15         0.18-1
ii  libmpc3          1.0.3-1+b2
ii  libmpfr4         3.1.5-1
ii  libstdc++-6-dev  6.3.0-18+deb9u1
ii  zlib1g           1:1.2.8.dfsg-5

g++-6 recommends no packages.

Versions of packages g++-6 suggests:
pn  g++-6-multilib    <none>
ii  gcc-6-doc         6.3.0-1
pn  libstdc++6-6-dbg  <none>
#include <iostream>
#include <fstream>
#include <exception>

int main(int argc, char** argv)
{
        using std::cout; using std::endl;

        if (argc != 2) {
                cout << "Program requires 1 argument (file name)" << endl;
                return 1;
        }

        
        char s;
        std::ifstream ifl;

        cout << std::hex;

        cout << "Opening file\n"
                        << "Exception mask on open: " << ifl.exceptions() << 
endl;
        try {
                ifl.open(argv[1]);
        }

        catch(const std::ios_base::failure& e)
        {
                cout << "std::ios_base::failure exception thrown on open: \n";
                cout << e.what() << '\n';
                cout << "state after exception: " << ifl.rdstate() << endl;     
        
                return 1;
        }

        catch(const std::exception& e)
        {
                cout << "std::exception thrown on open:\n" << e.what() << endl;
                cout << e.what() << '\n';
                cout << "state after exception: " << ifl.rdstate() << endl; 
                return 1;
        }

        catch(...)
        {
                cout << "Other exception thrown" << endl;
                cout << "state after exception: " << ifl.rdstate() << endl; 
                return 1;       
        }

        cout << "No exceptions thrown\n";
        cout << "State after opening: " << ifl.rdstate() << endl;

        if (!ifl.good() ) {
                cout << "Error opening file" << endl;
                return 0;
        }



        cout << "Reading file\n"
                        << "Exception mask on read: " << ifl.exceptions() << 
endl;

        try {
                ifl >> s;
        }

        catch(const std::ios_base::failure& e)
        {
                cout << "std::ios_base::failure exception thrown on read: \n";
                cout << e.what() << '\n';
                cout << "state after exception: " << ifl.rdstate() << endl;     
        
                return 1;
        }

        catch(const std::exception& e)
        {
                cout << "std::exception thrown on read:\n" << e.what() << endl;
                cout << e.what() << '\n';
                cout << "state after exception: " << ifl.rdstate() << endl; 
                return 1;
        }

        catch(...)
        {
                cout << "Other exception thrown on read" << endl;
                cout << "state after exception: " << ifl.rdstate() << endl; 
                return 1;       
        }

        cout << "No exceptions thrown on read\n";
        cout << "State after reading: " <<std::hex << ifl.rdstate() << endl;
        cout << s << endl;

        return 0;
        
}
john@GEORGE:~/projects/istream$ ls
main  main.cpp  main.o  testdir
john@GEORGE:~/projects/istream$ ./main main.cpp
Opening file
Exception mask on open: 0
No exceptions thrown
State after opening: 0
Reading file
Exception mask on read: 0
No exceptions thrown on read
State after reading: 0
#
john@GEORGE:~/projects/istream$ ./testdir
bash: ./testdir: Is a directory
john@GEORGE:~/projects/istream$ 
john@GEORGE:~/projects/istream$ ./main testdir
Opening file
Exception mask on open: 0
No exceptions thrown
State after opening: 0
Reading file
Exception mask on read: 0
std::ios_base::failure exception thrown on read: 
basic_filebuf::underflow error reading the file: iostream error
state after exception: 0
john@GEORGE:~/projects/istream$ 

Reply via email to