<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - Infinite recursion in type_info::operator== under UBSan"
   href="https://bugs.llvm.org/show_bug.cgi?id=48929">48929</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Infinite recursion in type_info::operator== under UBSan
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>compiler-rt
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>unspecified
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>enhancement
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>ubsan
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>tlively@google.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Apologies if this is the wrong component to file a bug on. It is definitely a
UBSan bug, but the relevant code is spread across compiler-rt, libc++, and
libc++abi.

I just investigated an issue in which using std::type_info::operator== produced
an infinite recursion with the following cycle of function calls:

RangeError: Maximum call stack size exceeded
    ...
    at std::type_info::operator==(std::type_info const&) const
    at is_equal(std::type_info const*, std::type_info const*, bool) 
    at __dynamic_cast (<anonymous>:wasm-function[40]:0x8fb)
    at __ubsan::checkDynamicType(void*, void*, unsigned long)
    at HandleDynamicTypeCacheMiss(__ubsan::DynamicTypeCacheMissData*, unsigned
long, unsigned long, __ubsan::ReportOptions)
    at __ubsan_handle_dynamic_type_cache_miss
    at std::type_info::operator==(std::type_info const&) const
    ...

Here is the reproducing program:

    // main.cpp
    #include <typeinfo>
    int main() {
      return typeid(int) == typeid(int)
    }


This infinite recursion happens when libc++abi is compiled with -Oz, but not
when it compiled with -O3. In the latter configuration, enough inlining and
follow-on optimizations happen to remove the call to std::type_info::operator==
under __dynamic_cast, preventing the infinite recursion. I found that adding
__attribute__((always_inline)) to std::type_info::operator== in libc++ was
sufficient to prevent the infinite recursion in the -Oz configuration as well.

This is certainly a niche configuration required to reproduce the bug, but it
seems that UBSan depending on optimizations to prevent infinite recursions is
not great, so possibly worth fixing.

The upstream workaround in Emscripten is here:
<a href="https://github.com/emscripten-core/emscripten/pull/13367">https://github.com/emscripten-core/emscripten/pull/13367</a>.</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>