public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/115050] New: Segfault when compiled with -O0
@ 2024-05-12 11:40 lobel.krivic at proton dot me
  2024-05-12 11:44 ` [Bug c++/115050] " pinskia at gcc dot gnu.org
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: lobel.krivic at proton dot me @ 2024-05-12 11:40 UTC (permalink / raw)
  To: gcc-bugs

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

            Bug ID: 115050
           Summary: Segfault when compiled with -O0
           Product: gcc
           Version: 13.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: lobel.krivic at proton dot me
  Target Milestone: ---

Created attachment 58183
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=58183&action=edit
the preprocessed file

The following source code:
```
#include <cstddef>
#include <type_traits>
#include <utility>
#include <exception>

///////////////////////////////////////////////////////

class VTable
{
  public:
        virtual void func(int x) = 0; // #1 this line affects behavior
        virtual ~VTable() = default;
};

template <typename T>
class Handler final : public VTable
{
  private:
        static constexpr int S = sizeof(void*);
        std::byte _data[S];

  public:
        template <typename... CArgs>
        Handler(CArgs&&... args) {
                static_assert(sizeof(T) <= S);
                ::new (&_data[0]) T(std::forward<CArgs>(args)...);
        }

        void func(int) { return; }

        ~Handler() { static_cast<T*>(static_cast<void*>(&_data[0]))->~T(); }
};

///////////////////////////////////////////////////////

struct FBase
{
        static constexpr int S = sizeof(void*) + sizeof(VTable);
        std::byte _data[S];

        ~FBase() {
static_cast<VTable*>(static_cast<void*>(&_data[0]))->~VTable(); } // #2 this
line affects behavior
};

struct F : FBase
{
        template <typename T>
        F(T&& t) {
                static_assert(sizeof(Handler<std::decay_t<T>>) <= S);
                ::new (&_data[0]) Handler<std::decay_t<T>>(std::forward<T>(t));
        }

        ~F() = default;
};

///////////////////////////////////////////////////////

struct Testor
{
        Testor() = default;
        ~Testor() = default;

        Testor(const Testor& /*unused*/) { throw std::bad_exception(); }
};

///////////////////////////////////////////////////////

#include <iostream>

int main() {

        try {
                Testor testor;
                F f{testor};
        }
        catch (const std::bad_exception& e) {
                std::cout << " caught! " << e.what() << std::endl;
        }

        return 0;
}
```

segfaults on runtime when compiled with -O0 but works when compiled with
-O1/O2/O3. This happens on all versions of gcc from 11.1 to 14.1 (clang does
not have this problem). -Wall and -Wextra do not report anything.
Here is the link to the source code: https://godbolt.org/z/5dWKEenMM

The complete command line that triggers the bug:
`g++ -O0 ./bug.cpp -o ./bug.out && ./bug.out`

Bug report that may be related:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50239


Output of `gcc -v`:

Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-pc-linux-gnu/13/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with:
/var/tmp/portage/sys-devel/gcc-13.2.1_p20240113-r1/work/gcc-13-20240113/configure
--host=x86_64-pc-linux-gnu --build=x86_64-pc-linux-gn
u --prefix=/usr --bindir=/usr/x86_64-pc-linux-gnu/gcc-bin/13
--includedir=/usr/lib/gcc/x86_64-pc-linux-gnu/13/include
--datadir=/usr/share/gcc-data/x86_
64-pc-linux-gnu/13 --mandir=/usr/share/gcc-data/x86_64-pc-linux-gnu/13/man
--infodir=/usr/share/gcc-data/x86_64-pc-linux-gnu/13/info --with-gxx-include-
dir=/usr/lib/gcc/x86_64-pc-linux-gnu/13/include/g++-v13 --disable-silent-rules
--disable-dependency-tracking --with-python-dir=/share/gcc-data/x86_64-pc
-linux-gnu/13/python --enable-languages=c,c++,fortran --enable-obsolete
--enable-secureplt --disable-werror --with-system-zlib --disable-nls
--disable-l
ibunwind-exceptions --enable-checking=release
--with-bugurl=https://bugs.gentoo.org/ --with-pkgversion='Gentoo
13.2.1_p20240113-r1 p12' --with-gcc-major
-version-only --enable-libstdcxx-time --enable-lto --disable-libstdcxx-pch
--enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale
=gnu --enable-multilib --with-multilib-list=m32,m64 --disable-fixed-point
--enable-targets=all --enable-libgomp --disable-libssp --disable-libada --disa
ble-cet --disable-systemtap --disable-valgrind-annotations
--disable-vtable-verify --disable-libvtv --without-zstd --without-isl
--enable-default-pie --
enable-default-ssp --disable-fixincludes
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 13.2.1 20240113 (Gentoo 13.2.1_p20240113-r1 p12)

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Bug c++/115050] Segfault when compiled with -O0
  2024-05-12 11:40 [Bug c++/115050] New: Segfault when compiled with -O0 lobel.krivic at proton dot me
@ 2024-05-12 11:44 ` pinskia at gcc dot gnu.org
  2024-05-12 15:50 ` sjames at gcc dot gnu.org
  2024-05-28 21:43 ` pinskia at gcc dot gnu.org
  2 siblings, 0 replies; 4+ messages in thread
From: pinskia at gcc dot gnu.org @ 2024-05-12 11:44 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #1 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
Note there is an alignment missing on the data field.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Bug c++/115050] Segfault when compiled with -O0
  2024-05-12 11:40 [Bug c++/115050] New: Segfault when compiled with -O0 lobel.krivic at proton dot me
  2024-05-12 11:44 ` [Bug c++/115050] " pinskia at gcc dot gnu.org
@ 2024-05-12 15:50 ` sjames at gcc dot gnu.org
  2024-05-28 21:43 ` pinskia at gcc dot gnu.org
  2 siblings, 0 replies; 4+ messages in thread
From: sjames at gcc dot gnu.org @ 2024-05-12 15:50 UTC (permalink / raw)
  To: gcc-bugs

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

Sam James <sjames at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |sjames at gcc dot gnu.org

--- Comment #2 from Sam James <sjames at gcc dot gnu.org> ---
Clang trunk UBSAN says:
```
/app/example.cpp:22:5: runtime error: constructor call on misaligned address
0x7ffe75477cbb for type 'Handler<Testor> *', which requires 8 byte alignment
0x7ffe75477cbb: note: pointer points here
 00  62 52 4a fe c8 7b 00 00  01 00 00 00 00 00 00 00  67 6c 69 62 00 00 00 00 
01 00 00 00 00 00 00
              ^ 
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /app/example.cpp:22:5 
/app/example.cpp:22:5: runtime error: constructor call on misaligned address
0x7ffe75477cbb for type 'VTable', which requires 8 byte alignment
0x7ffe75477cbb: note: pointer points here
 00  62 52 4a fe c8 7b 00 00  01 00 00 00 00 00 00 00  67 6c 69 62 00 00 00 00 
01 00 00 00 00 00 00
              ^ 
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /app/example.cpp:22:5 
/app/example.cpp:8:7: runtime error: constructor call on misaligned address
0x7ffe75477cbb for type 'VTable *', which requires 8 byte alignment
0x7ffe75477cbb: note: pointer points here
 00  62 52 4a fe c8 7b 00 00  01 00 00 00 00 00 00 00  67 6c 69 62 00 00 00 00 
01 00 00 00 00 00 00
              ^ 
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /app/example.cpp:8:7 
/app/example.cpp:24:27: runtime error: constructor call on misaligned address
0x7ffe75477cc3 for type 'Testor', which requires 8 byte alignment
0x7ffe75477cc3: note: pointer points here
 68  5a 00 00 00 00 00 00 00  67 6c 69 62 00 00 00 00  01 00 00 00 00 00 00 00 
90 9d 42 fe c8 7b 00
              ^ 
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /app/example.cpp:24:27 
/app/example.cpp:11:13: runtime error: member call on misaligned address
0x7ffe75477cbb for type 'VTable *', which requires 8 byte alignment
0x7ffe75477cbb: note: pointer points here
 00  62 52 4a 60 4c 47 5d 68  5a 00 00 00 00 00 00 00  67 6c 69 62 00 00 00 00 
01 00 00 00 00 00 00
              ^ 
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /app/example.cpp:11:13 
/app/example.cpp:39:62: runtime error: member call on misaligned address
0x7ffe75477cbb for type 'VTable', which requires 8 byte alignment
0x7ffe75477cbb: note: pointer points here
 00  62 52 4a 60 4c 47 5d 68  5a 00 00 00 00 00 00 00  67 6c 69 62 00 00 00 00 
01 00 00 00 00 00 00
              ^ 
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /app/example.cpp:39:62 
/app/example.cpp:29:5: runtime error: member call on misaligned address
0x7ffe75477cbb for type 'Handler<Testor> *', which requires 8 byte alignment
0x7ffe75477cbb: note: pointer points here
 00  62 52 4a 60 4c 47 5d 68  5a 00 00 00 00 00 00 00  67 6c 69 62 00 00 00 00 
01 00 00 00 00 00 00
              ^ 
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /app/example.cpp:29:5 
 caught! std::bad_exception
```

GCC's reports nothing though.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Bug c++/115050] Segfault when compiled with -O0
  2024-05-12 11:40 [Bug c++/115050] New: Segfault when compiled with -O0 lobel.krivic at proton dot me
  2024-05-12 11:44 ` [Bug c++/115050] " pinskia at gcc dot gnu.org
  2024-05-12 15:50 ` sjames at gcc dot gnu.org
@ 2024-05-28 21:43 ` pinskia at gcc dot gnu.org
  2 siblings, 0 replies; 4+ messages in thread
From: pinskia at gcc dot gnu.org @ 2024-05-28 21:43 UTC (permalink / raw)
  To: gcc-bugs

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

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Resolution|---                         |INVALID
             Status|UNCONFIRMED                 |RESOLVED

--- Comment #3 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
There is a copy of Tester involved before F's constructor fully happens so we
call ~FBase (on the unwind) which then calls the bad (vtable) deconstructor.
Why it happens at -O0 only is just by accident. At -O1 we do some
de-virtualization which allows the (right) deconstructor to be called. Note
GCC's VTable::~VTable sets the vtable to be VTable's vtable which exposes the
bug. This only happens at -O0 because at -O1 and above it is considered a dead
store.

This is definitely undefined code without the following change because you
might get ~VTable being called twice.



Note if you change VTable to:
```
class VTable
{
  public:
        virtual void func(int x) = 0; // #1 this line affects behavior
        virtual ~VTable() {__builtin_printf("~vtable\n");}
};
```

You will see there is 2 calls to ~VTable which is incorrect.



Changing FBase/F to this:
```

struct FBase
{
        static constexpr int S = sizeof(void*) + sizeof(VTable);
        bool constructed = false;
        std::byte _data[S];

        ~FBase() { if (!constructed) return;
static_cast<VTable*>(static_cast<void*>(&_data[0]))->~VTable(); } // #2 this
line affects behavior
};

struct F : FBase
{
        template <typename T>
        F(T&& t) {
                static_assert(sizeof(Handler<std::decay_t<T>>) <= S);
                ::new (&_data[0]) Handler<std::decay_t<T>>(std::forward<T>(t));
                constructed = true;
        }

        ~F() = default;
};
```

Fixes the issue and only one call to ~VTable happens.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2024-05-28 21:43 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-05-12 11:40 [Bug c++/115050] New: Segfault when compiled with -O0 lobel.krivic at proton dot me
2024-05-12 11:44 ` [Bug c++/115050] " pinskia at gcc dot gnu.org
2024-05-12 15:50 ` sjames at gcc dot gnu.org
2024-05-28 21:43 ` pinskia at gcc dot gnu.org

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