[llvm-bugs] [Bug 45393] New: -fwhole-program-vtables miscompile when multiple unique return value checks resolve to the same vtable

via llvm-bugs llvm-bugs at lists.llvm.org
Wed Apr 1 17:02:10 PDT 2020


https://bugs.llvm.org/show_bug.cgi?id=45393

            Bug ID: 45393
           Summary: -fwhole-program-vtables miscompile when multiple
                    unique return value checks resolve to the same vtable
           Product: libraries
           Version: trunk
          Hardware: PC
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: Interprocedural Optimizations
          Assignee: unassignedbugs at nondot.org
          Reporter: llvm at inglorion.net
                CC: llvm-bugs at lists.llvm.org

Created attachment 23305
  --> https://bugs.llvm.org/attachment.cgi?id=23305&action=edit
Run ninja && ./main

class Base {
public:
  virtual bool foo() const { return false; };
  virtual bool bar() const { return false; };
};

class Derived : public Base {
public:
  bool foo() const override { return true; };
  bool bar() const override { return true; };
}

With no other classes in the hierarchy, this allows whole program
devirtualization to replace calls to foo() and bar() with a comparison of the
vptr against Derived's vtable (the methods return true if and only if this is
an instance of Derived).

Because foo() and bar() are in different slots, they are referred to by
different symbols. Code that does something like

  if (foo()) {
    if (bar()) {
      ... }}

translates to something like

  if (vptr == __typeid__ZTSBase_16_unique_member) {
    if (vptr == __typeid__ZTSBase_24_unique_member) {
      ... }}

Because the vtable being checked is the same in both cases, these symbols have
the same value (i.e. they are pointers to the same address).

However, the declarations of these symbols look like

  @__typeid_ZTSBase_16_unique_member = external hidden global i8
  @__typeid_ZTSBase_24_unique_member = external hidden global i8

Because i8 have size, LLVM assumes these globals cannot be at the same address,
concludes the comparison against __typeid__ZTSBase_24_unique_member is always
false, and elides that code.

This was discovered in the analysis of http://crbug.com/1062006

Some C++ code that reproduces the issue is attached. Running ./main returns 2
when built without -fwhole-program-vtables, and returns 1 when built with
-fwhole-program-vtables, even though that value should be impossible.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20200402/80ae2193/attachment.html>


More information about the llvm-bugs mailing list