https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113994
Bug ID: 113994 Summary: Probable C++ code generation bug with -O2 on s390x platform Product: gcc Version: 13.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: thierry at lelegard dot fr Target Milestone: --- - GCC version: 13.2.0 - Operating system: Ubuntu 23.10 - Platform: IBM s390x (emulated on Qemu 8.2.1) On s390x platform, with "g++ -O2", the following C++ sample test code aborts with std::out_of_range exception in the instantiation of template std::string::substr(). The parameters are valid (see below) and no exception should be thrown. The problem does not occur either: 1. when the std::cout trace line is uncommented (probably break some incorrect optimization) 2. with -O1 or -O0 3. with clang 4. on other CPU architectures For information, the original project (https://tsduck.io/) was tested on 16 different operating systems, 8 CPU architectures and 3 compilers (details here: https://tsduck.io/doxy/building.html). The problem occurs on s390x only. Demonstration: ------------------------------------------------------------ $ g++ -O2 test.cpp -o test $ ./test terminate called after throwing an instance of 'std::out_of_range' what(): basic_string::substr: __pos (which is 3) > this->size() (which is 3) Aborted (core dumped) $ $ g++ -O1 test.cpp -o test $ ./test ok $ $ clang++ -O2 test.cpp -o test $ ./test ok $ ------------------------------------------------------------ Source code: ------------------------------------------------------------ #include <string> #include <iostream> void f(const std::string& path, size_t& index, std::string& next) { size_t end = path.find(']'); if (end >= path.size()) { return; } else if (end == 1) { index = std::string::npos; } while (++end < path.size() && path[end] == u'.') { } // If uncommented, display "end = 3" and there is no exception. // std::cout << "end = " << end << std::endl; next = path.substr(end); } int main(int argc, char* argv[]) { size_t index = 0; std::string next; f("[0]", index, next); std::cout << "ok" << std::endl; } ------------------------------------------------------------ At the point of exception, end == path.size() == 3. This is case is permitted by the C++ standard and should return the empty string. By the way, the exception message "__pos (which is 3) > this->size() (which is 3)" is inconsistent because "3 > 3" is false. The problem is not in the source code if the C++ library but most probably in the generated code for the instantiation of the template class std::basic_string. If the code was in the C++ library, the problem should be also present with the trace line, with other forms of optimization in the compilation of the application or with clang. Using gdb on the core file demonstrates that: - the exception is thrown in the generated code for the instantiation of std::__cxx11::basic_string::substr - the __pos parameter of substr() is 3 (get the substring starting at index 3) - the string is "[0]" (length is 3) ------------------------------------------------------------ $ gdb ./test core GNU gdb (Ubuntu 14.0.50.20230907-0ubuntu1) 14.0.50.20230907-git .... Core was generated by `./test'. Program terminated with signal SIGABRT, Aborted. #0 __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44 44 pthread_kill.c: No such file or directory. (gdb) bt #0 __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44 #1 0x000003ff89d9e106 in __pthread_kill_internal (signo=6, threadid=<optimized out>) at pthread_kill.c:78 #2 0x000003ff89d4aa90 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26 #3 0x000003ff89d2a4ec in __GI_abort () at abort.c:79 #4 0x000003ff8a0d28f2 in __gnu_cxx::__verbose_terminate_handler() () from /lib/s390x-linux-gnu/libstdc++.so.6 #5 0x000003ff8a0cfc4e in ?? () from /lib/s390x-linux-gnu/libstdc++.so.6 #6 0x000003ff8a0cfcd8 in std::terminate() () from /lib/s390x-linux-gnu/libstdc++.so.6 #7 0x000003ff8a0cffe6 in __cxa_throw () from /lib/s390x-linux-gnu/libstdc++.so.6 #8 0x000003ff8a1053de in std::__throw_out_of_range_fmt(char const*, ...) () from /lib/s390x-linux-gnu/libstdc++.so.6 #9 0x000002aa3f8013ac in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_check ( __s=0x2aa3f8013f0 "basic_string::substr", __pos=3, this=0x3ffe9979cf8) at /usr/include/c++/13/bits/basic_string.h:379 #10 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::substr (__n=18446744073709551615, __pos=3, this=0x3ffe9979cf8) at /usr/include/c++/13/bits/basic_string.h:3153 #11 f (path="[0]", index=@0x3ffe9979cd0: 0, next="") at test.cpp:17 #12 0x000002aa3f800e48 in main (argc=<optimized out>, argv=<optimized out>) at test.cpp:24 (gdb) f 9 #9 0x000002aa3f8013ac in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_check ( __s=0x2aa3f8013f0 "basic_string::substr", __pos=3, this=0x3ffe9979cf8) at /usr/include/c++/13/bits/basic_string.h:379 379 __throw_out_of_range_fmt(__N("%s: __pos (which is %zu) > " (gdb) p *this $2 = "[0]" (gdb) ------------------------------------------------------------ Compilers and OS versions: ------------------------------------------------------------ $ gcc --version gcc (Ubuntu 13.2.0-4ubuntu3) 13.2.0 Copyright (C) 2023 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ $ gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/libexec/gcc/s390x-linux-gnu/13/lto-wrapper Target: s390x-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu 13.2.0-4ubuntu3' --with-bugurl=file:///usr/share/doc/gcc-13/README.Bugs --enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-13 --program-prefix=s390x-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/libexec --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-libquadmath --disable-libquadmath-support --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch=z13 --with-tune=z16 --enable-s390-excess-float-precision --with-long-double-128 --enable-multilib --enable-checking=release --build=s390x-linux-gnu --host=s390x-linux-gnu --target=s390x-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2 Thread model: posix Supported LTO compression algorithms: zlib zstd gcc version 13.2.0 (Ubuntu 13.2.0-4ubuntu3) $ $ clang --version Ubuntu clang version 16.0.6 (15) Target: s390x-unknown-linux-gnu Thread model: posix InstalledDir: /usr/bin $ $ uname -a Linux vms390x 6.5.0-17-generic #17-Ubuntu SMP Thu Jan 11 13:28:22 UTC 2024 s390x s390x s390x GNU/Linux $ $ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 23.10 Release: 23.10 Codename: mantic ------------------------------------------------------------