[compiler-rt] r221445 - UBSan: Teach isDerivedFromAtOffset and findBaseAtOffset about vbases

Alexey Samsonov vonosmas at gmail.com
Mon Dec 29 16:36:35 PST 2014


I've reverted this change in r224972. It seems to cause false positives:

$ cat tmp/ubsan/ex.cc
class Base {
  int a;
public:
  virtual void set(int val) { a = val; }
};

class Derived : virtual public Base {
  int b;
};

void foo(Base *b) {
  b->set(2);
}

int main() {
  Derived d;
  foo(&d);
  return 0;
}

$ ./bin/clang++ -fsanitize=vptr tmp/ubsan/ex.cc && ./a.out
tmp/ubsan/ex.cc:4:31: runtime error: member access within address
0x7fff49db8238 which does not point to an object of type 'Base'
0x7fff49db8228: note: object is base class subobject at offset 16 within
object of type 'Derived'
 ff 7f 00 00  a0 fa 41 00 00 00 00 00  40 ab 41 00 00 00 00 00  b8 fa 41 00
00 00 00 00  30 83 db 49
              ^
~~~~~~~~~~~~~~~~~~~~~~~
                                                                vptr for
'<unknown>' base class of 'Derived'
    #0 0x41ab25 in Base::set(int) (a.out+0x41ab25)
    #1 0x41a906 in foo(Base*) (a.out+0x41a906)
    #2 0x41a9e9 in main (a.out+0x41a9e9)
    #3 0x7fb8d2062ec4 in __libc_start_main
/build/buildd/eglibc-2.19/csu/libc-start.c:287
    #4 0x401e88 in _start (a.out+0x401e88)

On Thu, Nov 6, 2014 at 12:55 AM, David Majnemer <david.majnemer at gmail.com>
wrote:

> Author: majnemer
> Date: Thu Nov  6 02:55:23 2014
> New Revision: 221445
>
> URL: http://llvm.org/viewvc/llvm-project?rev=221445&view=rev
> Log:
> UBSan: Teach isDerivedFromAtOffset and findBaseAtOffset about vbases
>
> When the __virtual_mask is set, __offset_flags >> __offset_shift yields
> an offset into the vtable.  Dereferencing this vtable slot gets us the
> vbase offset.
>
> Adjust a test case to verify that this, in fact, works.
>
> Differential Revision: http://reviews.llvm.org/D6074
>
> Modified:
>     compiler-rt/trunk/lib/ubsan/ubsan_type_hash.cc
>     compiler-rt/trunk/test/ubsan/TestCases/TypeCheck/vptr.cpp
>
> Modified: compiler-rt/trunk/lib/ubsan/ubsan_type_hash.cc
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_type_hash.cc?rev=221445&r1=221444&r2=221445&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/ubsan/ubsan_type_hash.cc (original)
> +++ compiler-rt/trunk/lib/ubsan/ubsan_type_hash.cc Thu Nov  6 02:55:23 2014
> @@ -115,7 +115,8 @@ __ubsan::__ubsan_vptr_type_cache[__ubsan
>
>  /// \brief Determine whether \p Derived has a \p Base base class
> subobject at
>  /// offset \p Offset.
> -static bool isDerivedFromAtOffset(const abi::__class_type_info *Derived,
> +static bool isDerivedFromAtOffset(sptr Object,
> +                                  const abi::__class_type_info *Derived,
>                                    const abi::__class_type_info *Base,
>                                    sptr Offset) {
>    if (Derived->__type_name == Base->__type_name)
> @@ -123,7 +124,7 @@ static bool isDerivedFromAtOffset(const
>
>    if (const abi::__si_class_type_info *SI =
>          dynamic_cast<const abi::__si_class_type_info*>(Derived))
> -    return isDerivedFromAtOffset(SI->__base_type, Base, Offset);
> +    return isDerivedFromAtOffset(Object, SI->__base_type, Base, Offset);
>
>    const abi::__vmi_class_type_info *VTI =
>      dynamic_cast<const abi::__vmi_class_type_info*>(Derived);
> @@ -138,13 +139,13 @@ static bool isDerivedFromAtOffset(const
>      sptr OffsetHere = VTI->base_info[base].__offset_flags >>
>                        abi::__base_class_type_info::__offset_shift;
>      if (VTI->base_info[base].__offset_flags &
> -          abi::__base_class_type_info::__virtual_mask)
> -      // For now, just punt on virtual bases and say 'yes'.
> -      // FIXME: OffsetHere is the offset in the vtable of the virtual base
> -      //        offset. Read the vbase offset out of the vtable and use
> it.
> -      return true;
> -    if (isDerivedFromAtOffset(VTI->base_info[base].__base_type,
> -                              Base, Offset - OffsetHere))
> +          abi::__base_class_type_info::__virtual_mask) {
> +      sptr VTable = *reinterpret_cast<const sptr *>(Object);
> +      OffsetHere = *reinterpret_cast<const sptr *>(VTable + OffsetHere);
> +    }
> +    if (isDerivedFromAtOffset(Object + OffsetHere,
> +                              VTI->base_info[base].__base_type, Base,
> +                              Offset - OffsetHere))
>        return true;
>    }
>
> @@ -153,14 +154,15 @@ static bool isDerivedFromAtOffset(const
>
>  /// \brief Find the derived-most dynamic base class of \p Derived at
> offset
>  /// \p Offset.
> -static const abi::__class_type_info *findBaseAtOffset(
> -    const abi::__class_type_info *Derived, sptr Offset) {
> +static const abi::__class_type_info *
> +findBaseAtOffset(sptr Object, const abi::__class_type_info *Derived,
> +                 sptr Offset) {
>    if (!Offset)
>      return Derived;
>
>    if (const abi::__si_class_type_info *SI =
>          dynamic_cast<const abi::__si_class_type_info*>(Derived))
> -    return findBaseAtOffset(SI->__base_type, Offset);
> +    return findBaseAtOffset(Object, SI->__base_type, Offset);
>
>    const abi::__vmi_class_type_info *VTI =
>      dynamic_cast<const abi::__vmi_class_type_info*>(Derived);
> @@ -172,12 +174,13 @@ static const abi::__class_type_info *fin
>      sptr OffsetHere = VTI->base_info[base].__offset_flags >>
>                        abi::__base_class_type_info::__offset_shift;
>      if (VTI->base_info[base].__offset_flags &
> -          abi::__base_class_type_info::__virtual_mask)
> -      // FIXME: Can't handle virtual bases yet.
> -      continue;
> -    if (const abi::__class_type_info *Base =
> -          findBaseAtOffset(VTI->base_info[base].__base_type,
> -                           Offset - OffsetHere))
> +          abi::__base_class_type_info::__virtual_mask) {
> +      sptr VTable = *reinterpret_cast<const sptr *>(Object);
> +      OffsetHere = *reinterpret_cast<const sptr *>(VTable + OffsetHere);
> +    }
> +    if (const abi::__class_type_info *Base = findBaseAtOffset(
> +            Object + OffsetHere, VTI->base_info[base].__base_type,
> +            Offset - OffsetHere))
>        return Base;
>    }
>
> @@ -229,7 +232,8 @@ bool __ubsan::checkDynamicType(void *Obj
>      return false;
>
>    abi::__class_type_info *Base = (abi::__class_type_info*)Type;
> -  if (!isDerivedFromAtOffset(Derived, Base, -Vtable->Offset))
> +  if (!isDerivedFromAtOffset(reinterpret_cast<sptr>(Object), Derived,
> Base,
> +                             -Vtable->Offset))
>      return false;
>
>    // Success. Cache this result.
> @@ -243,8 +247,9 @@ __ubsan::DynamicTypeInfo __ubsan::getDyn
>    if (!Vtable)
>      return DynamicTypeInfo(0, 0, 0);
>    const abi::__class_type_info *ObjectType = findBaseAtOffset(
> -    static_cast<const abi::__class_type_info*>(Vtable->TypeInfo),
> -    -Vtable->Offset);
> +      reinterpret_cast<sptr>(Object),
> +      static_cast<const abi::__class_type_info *>(Vtable->TypeInfo),
> +      -Vtable->Offset);
>    return DynamicTypeInfo(Vtable->TypeInfo->__type_name, -Vtable->Offset,
>                           ObjectType ? ObjectType->__type_name :
> "<unknown>");
>  }
>
> Modified: compiler-rt/trunk/test/ubsan/TestCases/TypeCheck/vptr.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/ubsan/TestCases/TypeCheck/vptr.cpp?rev=221445&r1=221444&r2=221445&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/test/ubsan/TestCases/TypeCheck/vptr.cpp (original)
> +++ compiler-rt/trunk/test/ubsan/TestCases/TypeCheck/vptr.cpp Thu Nov  6
> 02:55:23 2014
> @@ -48,7 +48,8 @@ struct T : S {
>    virtual int v() { return 1; }
>  };
>
> -struct U : S, T { virtual int v() { return 2; } };
> +struct X {};
> +struct U : S, T, virtual X { virtual int v() { return 2; } };
>
>  struct V : S {};
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>



-- 
Alexey Samsonov
vonosmas at gmail.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20141229/ffb6c527/attachment.html>


More information about the llvm-commits mailing list