public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
From: "thierry at lelegard dot fr" <gcc-bugzilla@gcc.gnu.org>
To: gcc-bugs@gcc.gnu.org
Subject: [Bug c++/113994] New: Probable C++ code generation bug with -O2 on s390x platform
Date: Mon, 19 Feb 2024 15:01:41 +0000	[thread overview]
Message-ID: <bug-113994-4@http.gcc.gnu.org/bugzilla/> (raw)

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
------------------------------------------------------------

             reply	other threads:[~2024-02-19 15:01 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-02-19 15:01 thierry at lelegard dot fr [this message]
2024-02-19 23:46 ` [Bug target/113994] " xry111 at gcc dot gnu.org
2024-02-19 23:57 ` jakub at gcc dot gnu.org
2024-02-20  8:08 ` rguenth at gcc dot gnu.org
2024-02-21 10:37 ` jakub at gcc dot gnu.org
2024-02-21 11:00 ` [Bug target/113994] [13/14 Regression] " jakub at gcc dot gnu.org
2024-02-21 12:25 ` jakub at gcc dot gnu.org
2024-02-29 10:17 ` stefansf at linux dot ibm.com
2024-02-29 10:23 ` jakub at gcc dot gnu.org
2024-02-29 12:00 ` rguenth at gcc dot gnu.org
2024-02-29 12:02 ` rguenth at gcc dot gnu.org
2024-02-29 12:04 ` jakub at gcc dot gnu.org
2024-02-29 12:59 ` rguenth at gcc dot gnu.org
2024-05-21  9:19 ` [Bug target/113994] [13/14/15 " jakub at gcc dot gnu.org

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bug-113994-4@http.gcc.gnu.org/bugzilla/ \
    --to=gcc-bugzilla@gcc.gnu.org \
    --cc=gcc-bugs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).