public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
From: "jakob2811 at hotmail dot de" <gcc-bugzilla@gcc.gnu.org>
To: gcc-bugs@gcc.gnu.org
Subject: [Bug c++/105387] New: libstdc++: with -fno-rtti, pointer type info class incorrectly matches non-pointer type info classes
Date: Tue, 26 Apr 2022 08:58:57 +0000	[thread overview]
Message-ID: <bug-105387-4@http.gcc.gnu.org/bugzilla/> (raw)

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105387

            Bug ID: 105387
           Summary: libstdc++: with -fno-rtti, pointer type info class
                    incorrectly matches non-pointer type info classes
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Keywords: EH
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jakob2811 at hotmail dot de
  Target Milestone: ---
              Host: x86_64-linux-gnu (Ubuntu 20, Ubuntu 22)
            Target: x86_64-linux-gnu, xtensa
             Build: x86_64-linux-gnu

Created attachment 52879
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=52879&action=edit
Patch which adds a check if the type info object is a pointer type

We observed a potential misbehavior in libstdc++'s libsupc++: When compiled
with exceptions but without RTTI, we see undefined behavior because a "normal"
type info object is incorrectly casted to a pointer type info object.

The problem occurs if there's a catch statement for a pointer type and an
exception with a non-pointer type is thrown like in the following code sample
code:

#include <cstdio>
#include <stdexcept>

int main(int argc, char** argv) {
    try {
        throw std::runtime_error("test runtime error");
    } catch (const char *e) {
        printf("~~~~~ cought outer exception char * %s ~~~~\n", e);
    } catch (const std::exception &e) {
        printf("~~~~~ cought outer exception %s ~~~~\n", e.what());
    }
}

On Linux, we built it with: /path/to/g++ test_linux.cpp -o test_linux, then ran
it.

Execution will eventually reach __pbase_type_info::__do_catch() in
libstdc++-v3/libsupc++/pbase_type_info.cc. Inside that function, the type info 
object of the exception (const type_info *), will be wrongly casted into a
pointer type info object (const __pbase_type_info *). The latter has additional
members of which __pbase_type_info::__flags will also be evaluated in
__pbase_type_info::__do_catch(). This may lead to a direct access fault or a
plain return false from the function (in which case nothing happens and the
program continues without issue) or a call of
__pbase_type_info::__pointer_catch() which most likely fails due to evaluation
of undefined members.

It looks as if __pbase_type_info::__do_catch() is made to handle both pointer
and non-pointer type info objects, since the calling function
get_adjusted_ptr() in libstdc++-v3/libsupc++/eh_personality.cc also checks if
the type info object is a pointer type and later calls type_info::__do_catch()
with that very object as parameter.

We observed this in gcc 8.4.0 for Xtensa as well as in gcc 11.2.0 for x86_64
Linux, please refer to the last section for detailed compiler configurations.

I debugged the sample code above on Xtensa, that's how I gained all the
knowledge described above. On Linux, I wasn't able to setup a gdb with the
modified libstdc++, so I couldn't debug it properly. But I did run the sample
code with the -fno-rtti version of the libstdc++ and the program produced a
segfault. When I later applied the attached fix to the compiler, the program
ran normally with the locally built libstdc++ with -fno-rtti.

If confirmed, I would like to create a proper patch but I don't know how I can
create a test case that reliably fails on an undefined variable. On Xtensa with
our configuration, __pbase_type_info->__flags of the wrongly casted pointer is
in fact a vtable pointer and the issue will not appear in many cases. On Linux,
the sample code always produced a segfault, though.
I furthermore don't know if the added check in the patch should be switched off
if RTTI is active. I haven't analyzed the additional RTTI-related code.

GCC configurations of the tested compilers:

$ xtensa-esp32-elf-gcc -v
Using built-in specs.
COLLECT_GCC=xtensa-esp32-elf-gcc
COLLECT_LTO_WRAPPER=/home/jakob/.espressif/tools/xtensa-esp32-elf/esp-2021r2-patch3-8.4.0/xtensa-esp32-elf/bin/../libexec/gcc/xtensa-esp32-elf/8.4.0/lto-wrapper
Target: xtensa-esp32-elf
Configured with:
/builds/idf/crosstool-NG/.build/xtensa-esp32-elf/src/gcc/configure
--build=x86_64-build_pc-linux-gnu --host=x86_64-build_pc-linux-gnu
--target=xtensa-esp32-elf
--prefix=/builds/idf/crosstool-NG/builds/xtensa-esp32-elf
--with-local-prefix=/builds/idf/crosstool-NG/builds/xtensa-esp32-elf/xtensa-esp32-elf
--with-headers=/builds/idf/crosstool-NG/builds/xtensa-esp32-elf/xtensa-esp32-elf/include
--with-newlib --enable-threads=no --disable-shared
--with-pkgversion='crosstool-NG esp-2021r2-patch3' --disable-__cxa_atexit
--enable-cxx-flags=-ffunction-sections --disable-libgomp --disable-libmudflap
--disable-libmpx --disable-libssp --disable-libquadmath
--disable-libquadmath-support
--with-gmp=/builds/idf/crosstool-NG/.build/xtensa-esp32-elf/buildtools
--with-mpfr=/builds/idf/crosstool-NG/.build/xtensa-esp32-elf/buildtools
--with-mpc=/builds/idf/crosstool-NG/.build/xtensa-esp32-elf/buildtools
--with-isl=/builds/idf/crosstool-NG/.build/xtensa-esp32-elf/buildtools
--enable-lto --enable-target-optspace --without-long-double-128 --disable-nls
--enable-multiarch --enable-languages=c,c++ --disable-libstdcxx-verbose
--enable-threads=posix --enable-gcov-custom-rtio --enable-libstdcxx-time=yes
Thread model: posix
gcc version 8.4.0 (crosstool-NG esp-2021r2-patch3) 

$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-linux-gnu/11.2.0/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../configure -prefix=/usr --enable-languages=c,c++
--enable-multiarch --host=x86_64-linux-gnu --build=x86_64-linux-gnu
--target=x86_64-linux-gnu --enable-cxx-flags=-fno-rtti
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 11.2.0 (GCC)

             reply	other threads:[~2022-04-26  8:58 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-26  8:58 jakob2811 at hotmail dot de [this message]
2022-04-26  9:03 ` [Bug c++/105387] " rguenth at gcc dot gnu.org
2022-04-26  9:07 ` jakub at gcc dot gnu.org
2022-04-28  1:57 ` [Bug libstdc++/105387] " jakob2811 at hotmail dot de
2022-05-04 22:18 ` redi at gcc dot gnu.org
2022-11-05 14:03 ` cvs-commit at gcc dot gnu.org
2022-11-05 14:05 ` redi 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-105387-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).