[libcxxabi] r200904 - Fix PR17221 - can't catch virtual base classes when throwing derived NULL pointers. Specifically, libc++abi would crash when you tried it.

Marshall Clow mclow.lists at gmail.com
Wed Feb 5 20:47:03 PST 2014


Author: marshall
Date: Wed Feb  5 22:47:02 2014
New Revision: 200904

URL: http://llvm.org/viewvc/llvm-project?rev=200904&view=rev
Log:
Fix PR17221 - can't catch virtual base classes when throwing derived NULL pointers. Specifically, libc++abi would crash when you tried it.

Modified:
    libcxxabi/trunk/src/private_typeinfo.cpp
    libcxxabi/trunk/test/catch_ptr_02.cpp

Modified: libcxxabi/trunk/src/private_typeinfo.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/private_typeinfo.cpp?rev=200904&r1=200903&r2=200904&view=diff
==============================================================================
--- libcxxabi/trunk/src/private_typeinfo.cpp (original)
+++ libcxxabi/trunk/src/private_typeinfo.cpp Wed Feb  5 22:47:02 2014
@@ -301,17 +301,20 @@ __base_class_type_info::has_unambiguous_
                                                     void* adjustedPtr,
                                                     int path_below) const
 {
-    ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
-    if (__offset_flags & __virtual_mask)
+    ptrdiff_t offset_to_base = 0;
+    if (adjustedPtr != nullptr)
     {
-        const char* vtable = *static_cast<const char*const*>(adjustedPtr);
-        offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
+        offset_to_base = __offset_flags >> __offset_shift;
+        if (__offset_flags & __virtual_mask)
+        {
+            const char* vtable = *static_cast<const char*const*>(adjustedPtr);
+            offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
+        }
     }
-    __base_type->has_unambiguous_public_base(info,
-                                             static_cast<char*>(adjustedPtr) + offset_to_base,
-                                             (__offset_flags & __public_mask) ?
-                                                 path_below :
-                                                 not_public_path);
+    __base_type->has_unambiguous_public_base(
+            info,
+            static_cast<char*>(adjustedPtr) + offset_to_base,
+            (__offset_flags & __public_mask) ? path_below : not_public_path);
 }
 
 void
@@ -358,7 +361,8 @@ __pointer_type_info::can_catch(const __s
                                void*& adjustedPtr) const
 {
     // Do the dereference adjustment
-    adjustedPtr = *static_cast<void**>(adjustedPtr);
+    if (adjustedPtr != NULL)
+        adjustedPtr = *static_cast<void**>(adjustedPtr);
     // bullets 1 and 4
     if (__pbase_type_info::can_catch(thrown_type, adjustedPtr))
         return true;

Modified: libcxxabi/trunk/test/catch_ptr_02.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/test/catch_ptr_02.cpp?rev=200904&r1=200903&r2=200904&view=diff
==============================================================================
--- libcxxabi/trunk/test/catch_ptr_02.cpp (original)
+++ libcxxabi/trunk/test/catch_ptr_02.cpp Wed Feb  5 22:47:02 2014
@@ -130,17 +130,49 @@ void test7 ()
 }
 
 
-struct vA {};
-struct vC : virtual public vA {};
+struct vBase {};
+struct vDerived : virtual public vBase {};
 
 void test8 ()
 {
     try
     {
-        throw (vC*)0;
+        throw new vDerived;
         assert(false);
     }
-    catch (vA *p) {
+    catch (vBase *p) {
+        assert(p != 0);
+    }
+    catch (...)
+    {
+        assert (false);
+    }
+}
+
+void test9 ()
+{
+    try
+    {
+        throw nullptr;
+        assert(false);
+    }
+    catch (vBase *p) {
+        assert(p == 0);
+    }
+    catch (...)
+    {
+        assert (false);
+    }
+}
+
+void test10 ()
+{
+    try
+    {
+        throw (vDerived*)0;
+        assert(false);
+    }
+    catch (vBase *p) {
         assert(p == 0);
     }
     catch (...)
@@ -158,4 +190,7 @@ int main()
     test5();
     test6();
     test7();
+    test8();
+    test9();
+    test10();
 }





More information about the cfe-commits mailing list