Hi mclow.lists, danalbert, jroelofs,

This patch delays the dereference adjustment until we are sure we are sure the 
thrown type is a pointer type. It is possible the thrown type is not a pointer 
and is smaller than `sizeof(void*)`. If the thrown type is is smaller than 
`sizeof(void*)` the deference adjustment will result in a heap buffer overflow.

I audited all the call sites of `can_catch(...)` and there are no places where 
`adjustedPtr` is used if `can_catch(...)` returns false. For this reason the 
patch should not introduce any functionality change.

This patch fixes the following tests when using ASAN:
* unwind_01.cpp
* unwind_02.cpp
* unwind_04.cpp

http://reviews.llvm.org/D6353

Files:
  src/private_typeinfo.cpp
Index: src/private_typeinfo.cpp
===================================================================
--- src/private_typeinfo.cpp
+++ src/private_typeinfo.cpp
@@ -347,30 +347,34 @@
 __pbase_type_info::can_catch(const __shim_type_info* thrown_type,
                              void*&) const
 {
-    if (is_equal(this, thrown_type, false))
-        return true;
-    return is_equal(thrown_type, &typeid(std::nullptr_t), false);
+    return is_equal(this, thrown_type, false) ||
+           is_equal(thrown_type, &typeid(std::nullptr_t), false);
 }
 
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wmissing-field-initializers"
 
 // Handles bullets 1, 3 and 4
+// NOTE: It might not be safe to adjust the pointer if it is not not a pointer
+// type. Only adjust the pointer after we know it is safe to do so.
 bool
 __pointer_type_info::can_catch(const __shim_type_info* thrown_type,
                                void*& adjustedPtr) const
 {
-    // Do the dereference adjustment
-    if (adjustedPtr != NULL)
-        adjustedPtr = *static_cast<void**>(adjustedPtr);
     // bullets 1 and 4
-    if (__pbase_type_info::can_catch(thrown_type, adjustedPtr))
+    if (__pbase_type_info::can_catch(thrown_type, adjustedPtr)) {
+        if (adjustedPtr != NULL)
+            adjustedPtr = *static_cast<void**>(adjustedPtr);
         return true;
+    }
     // bullet 3
     const __pointer_type_info* thrown_pointer_type =
         dynamic_cast<const __pointer_type_info*>(thrown_type);
     if (thrown_pointer_type == 0)
         return false;
+    // Do the dereference adjustment
+    if (adjustedPtr != NULL)
+        adjustedPtr = *static_cast<void**>(adjustedPtr);
     // bullet 3B
     if (thrown_pointer_type->__flags & ~__flags)
         return false;
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to