Bug 69191 - Wrong equality comparison between error_code and error_condition + segfault
Summary: Wrong equality comparison between error_code and error_condition + segfault
Status: UNCONFIRMED
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 4.9.3
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-01-08 07:27 UTC by eyenseo
Modified: 2018-05-14 13:15 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
Precompiled minimal testcase (79.42 KB, text/plain)
2016-01-08 07:27 UTC, eyenseo
Details
Fixed precompiled testcase (79.16 KB, text/plain)
2016-01-08 08:16 UTC, eyenseo
Details

Note You need to log in before you can comment on or make changes to this bug.
Description eyenseo 2016-01-08 07:27:03 UTC
Created attachment 37264 [details]
Precompiled minimal testcase

Greetings!

This is a bug (maybe two) regarding the comparison of std::error_condition and std::error_code. An error_code and an error_condition with same value, message and category name are not identified as same - but they should.

While pinpointing this bug I happened to produce a segmentation fault in libstdc++ that is most probably part of the comparison bug. Using Clang with libstdc++ produces the same result (including segfault). Using Clang with libc++ produces the expected results and there is no segfault.


command line:
g++ --std=c++11 main.cpp && ./a.out

output:
code == con1: 0
code == con2: 1
con1 == con2: 0
con1 == con3: 0
con2 == con3: 0

code: value: 13
  message: Permission denied
  category name: generic
con1: value: 13
  message: Permission denied
  category name: generic
con2: value: 13
  message: Permission denied
  category name: generic
con3: value: 0
  message: Success
  category name: generic

expected:
code == con1: 1
code == con2: 1
con1 == con2: 1
con1 == con3: 1
con2 == con3: 1

code:	value: 13
	message: Permission denied
	category name: generic
con1:	value: 13
	message: Permission denied
	category name: generic
con2:	value: 13
	message: Permission denied
	category name: generic
con3:	value: 13
	message: Permission denied
	category name: generic


Source: main.cpp
#include <system_error>
#include <iostream>

#define equals(a, b) std::cout << #a " == " #b ": " << (a == b) << '\n';
#define print(a)                                                              \
  std::cout << #a ":\tvalue: " << a.value() << "\n\tmessage: " << a.message() \
            << "\n\tcategory name: " << a.category().name() << '\n';

int main(int, char const* []) {
  auto code = std::make_error_code(std::errc::permission_denied);
  auto con1 = std::make_error_condition(std::errc::permission_denied);
  auto con2 = code.category().default_error_condition(code.value());
  auto con3 = code.default_error_condition();

  equals(code, con1);  // This should be true
  equals(code, con2);  // This is true
  // equals(code, con3);  // Segmentation fault
  //                      // std::_V2::error_category::equivalent(int,
  //                      // std::error_condition const&) const () from
  //                      // /usr/lib/x86_64-linux-gnu/libstdc++.so.6
  equals(con1, con2);  // This should be true
  equals(con1, con3);  // This should be true
  equals(con2, con3);  // This should be true

  std::cout << '\n';

  print(code);  // Same as con1 and con2
  print(con1);  // Same as code and con2
  print(con2);  // Same as code and con1
  print(con3);  // This should be the same as code and con1 and con2

  return 0;
}


My system is:
x86_64-linux-gnu

GCC build:
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.9.3-8ubuntu2~14.04' --with-bugurl=file:///usr/share/doc/gcc-4.9/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.9 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.9 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.9-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.9-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.9-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Comment 1 eyenseo 2016-01-08 08:16:37 UTC
Created attachment 37265 [details]
Fixed precompiled testcase

The other precompiled testcase had text in it.
Comment 2 Jonathan Wakely 2016-01-08 18:11:25 UTC
I can't reproduce this, it might be specific to Ubuntu, maybe caused by mixing gcc 4.9 with the lisbtdc++ from gcc 5 (which would mean this is PR 66438).
Comment 3 eyenseo 2016-01-08 18:19:38 UTC
This bug does not appear in 5.3.0 - using Arch Linux.

I would like to know what a critical or major bug would be if a segfault is not? I think that a segfault is quite devastating, especially when working with error codes that should help get out of mess.
Comment 4 eyenseo 2016-01-08 18:20:43 UTC
The ubuntu system I used is "normal" no testing / unstable.
Comment 5 eyenseo 2016-01-08 18:38:48 UTC
(In reply to Jonathan Wakely from comment #2)
> I can't reproduce this, it might be specific to Ubuntu, maybe caused by
> mixing gcc 4.9 with the lisbtdc++ from gcc 5 (which would mean this is PR
> 66438).

The bug seems to have something to do with ubuntu indeed:

This is gcc 4.9.3 with XCode (I suspect on OSX) [line: 2824]
https://travis-ci.org/mnmlstc/core/jobs/98418930

This is gcc 4.9.3 on Ubuntu 12.04.5 LTS [line: 430]
https://travis-ci.org/mnmlstc/core/jobs/98418950
Comment 6 Jonathan Wakely 2016-01-08 18:49:19 UTC
(In reply to eyenseo from comment #3)
> I would like to know what a critical or major bug would be if a segfault is
> not? I think that a segfault is quite devastating, especially when working
> with error codes that should help get out of mess.

The severity field is almost useless, we don't use it in practice because too many users think their bug is the most critical one ever and set it to critical or blocker, but it's up to the GCC devs to determine the severity.

A segfault bug is not necessarily critical anyway, it's just a bug. Especially a C++11 bug in GCC 4.9 given that C++11 support in 4.9 was still labelled as experimental, and what you're doing is not supported (see below).

(In reply to eyenseo from comment #4)
> The ubuntu system I used is "normal" no testing / unstable.

I have no idea what that means in terms of which version of libstdc++ you have, but when I compile your preprocessed source and link to GCC 5's libstdc++ I see the wrong result (but not a segfault). That strongly suggests the behaviour you observe on Ubuntu is due to using the experimental C++11 support in GCC 4.9 with the non-experimental and incompatible C++11 parts of the library from GCC 5, i.e. PR 66438.

I do hope to get a workaround for the problem, but it's low priority  (definitely not critical) because mixing C++11 code from different GCC versions was not supported before GCC 5.
Comment 7 eyenseo 2016-01-08 19:01:44 UTC
(In reply to Jonathan Wakely from comment #6)

Thanks for letting me know of the "importance-ignoring" one two less clicks next time ;) 

I didn't include the segfault in the precompiled file as I would not be able to get the full output that describes the bug better than the segfault.

So in the end we have to assume that the travis setup and my system get the error because the Ubuntu guys build gcc wrong - but not recognisable in the build settings I included in comment #1 ?
Comment 8 Jonathan Wakely 2016-01-08 19:18:03 UTC
(In reply to eyenseo from comment #7)
> (In reply to Jonathan Wakely from comment #6)
> 
> Thanks for letting me know of the "importance-ignoring" one two less clicks
> next time ;) 

Yes, you don't need to bother with that :-)

> I didn't include the segfault in the precompiled file as I would not be able
> to get the full output that describes the bug better than the segfault.

Ah yes, so that will be why I didn't see a segfault when mixing GCC 4.9 and GCC 5.

> So in the end we have to assume that the travis setup and my system get the
> error because the Ubuntu guys build gcc wrong - but not recognisable in the
> build settings I included in comment #1 ?

That only shows how your gcc compiler was built. If I understand correctly the Ubuntu packages that provide libstdc++.so.6 come from a different build (of a different version) from the gcc compiler executables.
Comment 9 eyenseo 2016-01-08 19:23:32 UTC
(In reply to Jonathan Wakely from comment #8)
> That only shows how your gcc compiler was built. If I understand correctly
> the Ubuntu packages that provide libstdc++.so.6 come from a different build
> (of a different version) from the gcc compiler executables.

Well that sucks ... and now what?
Close this bug and report one to ubuntu? 
Is there a way I can check at runtime which library I'm using?
Comment 10 Jonathan Wakely 2016-01-09 00:40:18 UTC
Use ldd to see which library is used at runtime. See what file that symlink points to. Compare with the version numbers of the releases.

GCC 4.9.0: libstdc++.so.6.0.20

GCC 5.1.0: libstdc++.so.6.0.21
Comment 11 eyenseo 2016-01-09 09:57:54 UTC
(In reply to Jonathan Wakely from comment #10)
> Use ldd to see which library is used at runtime. See what file that symlink
> points to. Compare with the version numbers of the releases.
> 
> GCC 4.9.0: libstdc++.so.6.0.20
> 
> GCC 5.1.0: libstdc++.so.6.0.21

Ok will do on Monday
Comment 12 eyenseo 2016-01-11 07:36:35 UTC
(In reply to Jonathan Wakely from comment #10)
> Use ldd to see which library is used at runtime. See what file that symlink
> points to. Compare with the version numbers of the releases.
> 
> GCC 4.9.0: libstdc++.so.6.0.20
> 
> GCC 5.1.0: libstdc++.so.6.0.21

It does use /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21 ... why would they do that?
Comment 13 Kristian Spangsege 2016-08-05 02:05:46 UTC
I've now run into this problem too, and it seems to be general, not just limited to Ubuntu.

There is the code that I compile:

    #include <cerrno>
    #include <system_error>
    #include <iostream>

    int main()
    {
        std::error_code ec(EDOM, std::system_category());
        bool b = (ec == std::errc::argument_out_of_domain);
        std::cout << b << "\n";
    }

I expect it to write `1`, not `0`.

I get the expected result with Clang on OS X. I get the wrong result with

 - GCC 6.1.1 on Fedora 24, which links against libstdc++.so.6.0.22
 - GCC 5.4.0 on Linux Mint 18 (Ubuntu 14.04), which links against libstdc++.so.6.0.21
 - GCC 4.9.3 on Linux Mint 17.1 (Ubuntu 16.04), which links against libstdc++.so.6.0.22

It therefore seems to me that this is really a bug in libstdc++.
Comment 14 Jonathan Wakely 2016-08-05 08:43:41 UTC
(In reply to Kristian Spangsege from comment #13)
> I expect it to write `1`, not `0`.

Which is not a segfault, so is a completely different problem.
Comment 15 Jonathan Wakely 2016-08-05 08:46:14 UTC
(In reply to Jonathan Wakely from comment #14)
> (In reply to Kristian Spangsege from comment #13)
> > I expect it to write `1`, not `0`.
> 
> Which is not a segfault, so is a completely different problem.

PR 60555 probably.
Comment 16 Chip Salzenberg 2018-01-02 03:01:41 UTC
Still happening in 7.2
Comment 17 Jonathan Wakely 2018-05-14 13:15:42 UTC
(In reply to Chip Salzenberg from comment #16)
> Still happening in 7.2

What is?