[PATCH] D25448: [ubsan] Disable -fsanitize=vptr checks for devirtualized calls

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 17 12:29:17 PDT 2016


On 17 Oct 2016 12:06 pm, "Vedant Kumar via cfe-commits" <
cfe-commits at lists.llvm.org> wrote:

vsk added a comment.

Thanks for your feedback so far, and sorry for the delayed response.

In https://reviews.llvm.org/D25448#570014, @rjmccall wrote:

> Wait, can you talk me through the bug here?


Derived inherits from Base1 and Base2. We upcast an instance of Derived to
Base2, then call a method (f1). Clang figures out that the method has to be
Derived::f1. Next, clang passes in a pointer to the vtable pointer for
**Base1**, along with the typeinfo for **Base2**, into the sanitizer
runtime. This confuses the runtime, which reports that the dynamic type of
the object is "Base1", and that this does not match the expected type
("Base2").

With the 'final' keyword:

  %6 = ptrtoint <2 x i32 (...)**>* %1 to i64
  call void @__ubsan_handle_dynamic_type_cache_miss(@1 (TypeInfo for
Base2), i64 %6, ...)

Without the 'final' keyword:

  %6 = bitcast <2 x i32 (...)**>* %1 to %class.Derived*
  %7 = getelementptr inbounds %class.Derived, %class.Derived* %6, i64 0,
i32 1
  %8 = ptrtoint %class.Base2* %7 to i64, !nosanitize !5
  call void @__ubsan_handle_dynamic_type_cache_miss(@1 (TypeInfo for
Base2), i64 %8, ...)



>   Why is final-based devirtualization here different from, say,
user-directed devirtualization via a qualified method name?

I'm not sure. I tested this by removing the 'final' specifier from
'Derived' and calling:

  obj.Derived::f1()

In this case, clang passes the correct typeinfo (for Derived) in to the
runtime.

> It sounds to me from your description that you're not sure why this is
happening.  If this indeed only triggers in the presence of multiple
inheritance, it might just be the case that you're doing your
object-extents analysis starting from the wrong offset.

It looks like I just haven't done a good job of explaining the issue. The
bug really does seem to be that clang isn't passing the right information
to the ubsan runtime. However, I'm not sure what the right fix is. Do we
disable sanitization in cases where we expect FP's, do we try harder to
pass in the right vptr (in this case, the vptr for Base2) into the runtime,
or do we try harder to pass in the right typeinfo (in this case, the
typeinfo for Derived)?


The baseline correct behaviour is that we should be passing a pointer to
the Base2 subobject, since we're calling a function declared in Base2.
However, since we know we can devirtualize, we can do better by passing a
pointer to the Derived object and the Derived typeinfo.

But we should not be working around our broken instrumentation by just
turning it off.

https://reviews.llvm.org/D25448



_______________________________________________
cfe-commits mailing list
cfe-commits at lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20161017/f1d07a6a/attachment.html>


More information about the cfe-commits mailing list