aboutsummaryrefslogtreecommitdiff
path: root/libcxxabi
diff options
context:
space:
mode:
authorEric Fiselier <eric@efcs.ca>2014-11-24 18:46:37 +0000
committerEric Fiselier <eric@efcs.ca>2014-11-24 18:46:37 +0000
commit90c138ea6d47c363ee3f7b55f90239c46ba5cc2f (patch)
tree666c3f528217ddfef225932c72606ddc8236839f /libcxxabi
parent909deebfc8b90eee317424646f6bdf358160164e (diff)
downloadllvm-90c138ea6d47c363ee3f7b55f90239c46ba5cc2f.zip
llvm-90c138ea6d47c363ee3f7b55f90239c46ba5cc2f.tar.gz
llvm-90c138ea6d47c363ee3f7b55f90239c46ba5cc2f.tar.bz2
[libcxxabi] Delay adjustment of pointer to prevent referencing invalid memory.
Summary: This patch delays the dereference adjustment until 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 Reviewers: danalbert, jroelofs, mclow.lists Reviewed By: mclow.lists Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D6353 llvm-svn: 222674
Diffstat (limited to 'libcxxabi')
-rw-r--r--libcxxabi/src/private_typeinfo.cpp18
1 files changed, 11 insertions, 7 deletions
diff --git a/libcxxabi/src/private_typeinfo.cpp b/libcxxabi/src/private_typeinfo.cpp
index a4699ff..38e70ab 100644
--- a/libcxxabi/src/private_typeinfo.cpp
+++ b/libcxxabi/src/private_typeinfo.cpp
@@ -347,30 +347,34 @@ bool
__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;