Reland "v8::TryCatch now works correctly with ASAN's UseAfterReturn mode enabled."

BUG=chromium:369962
LOG=N
R=jkummerow@chromium.org

Review URL: https://codereview.chromium.org/282783004

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21382 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
ishell@chromium.org 2014-05-20 10:13:46 +00:00
parent 2c6438bbfa
commit 2a62cce170
11 changed files with 61 additions and 66 deletions

View File

@ -5076,6 +5076,22 @@ class V8_EXPORT TryCatch {
*/
void SetCaptureMessage(bool value);
/**
* There are cases when the raw address of C++ TryCatch object cannot be
* used for comparisons with addresses into the JS stack. The cases are:
* 1) ARM, ARM64 and MIPS simulators which have separate JS stack.
* 2) Address sanitizer allocates local C++ object in the heap when
* UseAfterReturn mode is enabled.
* This method returns address that can be used for comparisons with
* addresses into the JS stack. When neither simulator nor ASAN's
* UseAfterReturn is enabled, then the address returned will be the address
* of the C++ try catch handler itself.
*/
static void* JSStackComparableAddress(v8::TryCatch* handler) {
if (handler == NULL) return NULL;
return handler->js_stack_comparable_address_;
}
private:
// Make it hard to create heap-allocated TryCatch blocks.
TryCatch(const TryCatch&);
@ -5084,10 +5100,11 @@ class V8_EXPORT TryCatch {
void operator delete(void*, size_t);
v8::internal::Isolate* isolate_;
void* next_;
v8::TryCatch* next_;
void* exception_;
void* message_obj_;
void* message_script_;
void* js_stack_comparable_address_;
int message_start_pos_;
int message_end_pos_;
bool is_verbose_ : 1;

View File

@ -6,6 +6,9 @@
#include <string.h> // For memcpy, strlen.
#include <cmath> // For isnan.
#ifdef V8_USE_ADDRESS_SANITIZER
#include <sanitizer/asan_interface.h>
#endif // V8_USE_ADDRESS_SANITIZER
#include "../include/v8-debug.h"
#include "../include/v8-profiler.h"
#include "../include/v8-testing.h"
@ -37,6 +40,7 @@
#include "runtime.h"
#include "runtime-profiler.h"
#include "scanner-character-streams.h"
#include "simulator.h"
#include "snapshot.h"
#include "unicode-inl.h"
#include "utils/random-number-generator.h"
@ -1785,13 +1789,26 @@ Local<Script> Script::Compile(v8::Handle<String> source,
v8::TryCatch::TryCatch()
: isolate_(i::Isolate::Current()),
next_(isolate_->try_catch_handler_address()),
next_(isolate_->try_catch_handler()),
is_verbose_(false),
can_continue_(true),
capture_message_(true),
rethrow_(false),
has_terminated_(false) {
Reset();
js_stack_comparable_address_ = this;
#ifdef V8_USE_ADDRESS_SANITIZER
void* asan_fake_stack_handle = __asan_get_current_fake_stack();
if (asan_fake_stack_handle != NULL) {
js_stack_comparable_address_ = __asan_addr_is_in_fake_stack(
asan_fake_stack_handle, js_stack_comparable_address_, NULL, NULL);
CHECK(js_stack_comparable_address_ != NULL);
}
#endif
// Special handling for simulators which have a separate JS stack.
js_stack_comparable_address_ = reinterpret_cast<void*>(
v8::internal::SimulatorStack::RegisterCTryCatch(
reinterpret_cast<uintptr_t>(js_stack_comparable_address_)));
isolate_->RegisterTryCatchHandler(this);
}
@ -1811,10 +1828,12 @@ v8::TryCatch::~TryCatch() {
isolate_->RestorePendingMessageFromTryCatch(this);
}
isolate_->UnregisterTryCatchHandler(this);
v8::internal::SimulatorStack::UnregisterCTryCatch();
reinterpret_cast<Isolate*>(isolate_)->ThrowException(exc);
ASSERT(!isolate_->thread_local_top()->rethrowing_message_);
} else {
isolate_->UnregisterTryCatchHandler(this);
v8::internal::SimulatorStack::UnregisterCTryCatch();
}
}

View File

@ -37,9 +37,6 @@ typedef int (*arm_regexp_matcher)(String*, int, const byte*, const byte*,
(FUNCTION_CAST<arm_regexp_matcher>(entry)( \
p0, p1, p2, p3, NULL, p4, p5, p6, p7, p8))
#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
reinterpret_cast<TryCatch*>(try_catch_address)
// The stack limit beyond which we will throw stack overflow errors in
// generated code. Because generated code on arm uses the C stack, we
// just use the C stack limit.
@ -436,10 +433,6 @@ class Simulator {
Simulator::current(Isolate::Current())->Call( \
entry, 10, p0, p1, p2, p3, NULL, p4, p5, p6, p7, p8)
#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
try_catch_address == NULL ? \
NULL : *(reinterpret_cast<TryCatch**>(try_catch_address))
// The simulator has its own stack. Thus it has a different stack limit from
// the C-based native code. Setting the c_limit to indicate a very small

View File

@ -54,9 +54,6 @@ typedef int (*arm64_regexp_matcher)(String* input,
(FUNCTION_CAST<arm64_regexp_matcher>(entry)( \
p0, p1, p2, p3, p4, p5, p6, p7, NULL, p8))
#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
reinterpret_cast<TryCatch*>(try_catch_address)
// Running without a simulator there is nothing to do.
class SimulatorStack : public v8::internal::AllStatic {
public:
@ -857,10 +854,6 @@ class Simulator : public DecoderVisitor {
entry, \
p0, p1, p2, p3, p4, p5, p6, p7, NULL, p8)
#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
try_catch_address == NULL ? \
NULL : *(reinterpret_cast<TryCatch**>(try_catch_address))
// The simulator has its own stack. Thus it has a different stack limit from
// the C-based native code.

View File

@ -54,15 +54,17 @@
#define MUST_USE_RESULT V8_WARN_UNUSED_RESULT
// Define DISABLE_ASAN macros.
// Define V8_USE_ADDRESS_SANITIZER macros.
#if defined(__has_feature)
#if __has_feature(address_sanitizer)
#define V8_USE_ADDRESS_SANITIZER 1
#endif
#endif
// Define DISABLE_ASAN macros.
#ifdef V8_USE_ADDRESS_SANITIZER
#define DISABLE_ASAN __attribute__((no_sanitize_address))
#endif
#endif
#ifndef DISABLE_ASAN
#else
#define DISABLE_ASAN
#endif

View File

@ -25,9 +25,6 @@ typedef int (*regexp_matcher)(String*, int, const byte*,
(FUNCTION_CAST<regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6, p7, p8))
#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
(reinterpret_cast<TryCatch*>(try_catch_address))
// The stack limit beyond which we will throw stack overflow errors in
// generated code. Because generated code on ia32 uses the C stack, we
// just use the C stack limit.

View File

@ -69,7 +69,7 @@ void ThreadLocalTop::InitializeInternal() {
js_entry_sp_ = NULL;
external_callback_scope_ = NULL;
current_vm_state_ = EXTERNAL;
try_catch_handler_address_ = NULL;
try_catch_handler_ = NULL;
context_ = NULL;
thread_id_ = ThreadId::Invalid();
external_caught_exception_ = false;
@ -98,11 +98,6 @@ void ThreadLocalTop::Initialize() {
}
v8::TryCatch* ThreadLocalTop::TryCatchHandler() {
return TRY_CATCH_FROM_ADDRESS(try_catch_handler_address());
}
Thread::LocalStorageKey Isolate::isolate_key_;
Thread::LocalStorageKey Isolate::thread_id_key_;
Thread::LocalStorageKey Isolate::per_isolate_thread_data_key_;
@ -209,9 +204,9 @@ void Isolate::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) {
v->VisitPointer(BitCast<Object**>(&(thread->context_)));
v->VisitPointer(&thread->scheduled_exception_);
for (v8::TryCatch* block = thread->TryCatchHandler();
for (v8::TryCatch* block = thread->try_catch_handler();
block != NULL;
block = TRY_CATCH_FROM_ADDRESS(block->next_)) {
block = block->next_) {
v->VisitPointer(BitCast<Object**>(&(block->exception_)));
v->VisitPointer(BitCast<Object**>(&(block->message_obj_)));
v->VisitPointer(BitCast<Object**>(&(block->message_script_)));
@ -266,23 +261,14 @@ bool Isolate::IsDeferredHandle(Object** handle) {
void Isolate::RegisterTryCatchHandler(v8::TryCatch* that) {
// The ARM simulator has a separate JS stack. We therefore register
// the C++ try catch handler with the simulator and get back an
// address that can be used for comparisons with addresses into the
// JS stack. When running without the simulator, the address
// returned will be the address of the C++ try catch handler itself.
Address address = reinterpret_cast<Address>(
SimulatorStack::RegisterCTryCatch(reinterpret_cast<uintptr_t>(that)));
thread_local_top()->set_try_catch_handler_address(address);
thread_local_top()->set_try_catch_handler(that);
}
void Isolate::UnregisterTryCatchHandler(v8::TryCatch* that) {
ASSERT(thread_local_top()->TryCatchHandler() == that);
thread_local_top()->set_try_catch_handler_address(
reinterpret_cast<Address>(that->next_));
ASSERT(thread_local_top()->try_catch_handler() == that);
thread_local_top()->set_try_catch_handler(that->next_);
thread_local_top()->catcher_ = NULL;
SimulatorStack::UnregisterCTryCatch();
}

View File

@ -213,10 +213,10 @@ class ThreadLocalTop BASE_EMBEDDED {
// Get the top C++ try catch handler or NULL if none are registered.
//
// This method is not guarenteed to return an address that can be
// This method is not guaranteed to return an address that can be
// used for comparison with addresses into the JS stack. If such an
// address is needed, use try_catch_handler_address.
v8::TryCatch* TryCatchHandler();
FIELD_ACCESSOR(v8::TryCatch*, try_catch_handler)
// Get the address of the top C++ try catch handler or NULL if
// none are registered.
@ -228,12 +228,15 @@ class ThreadLocalTop BASE_EMBEDDED {
// stack, try_catch_handler_address returns a JS stack address that
// corresponds to the place on the JS stack where the C++ handler
// would have been if the stack were not separate.
FIELD_ACCESSOR(Address, try_catch_handler_address)
Address try_catch_handler_address() {
return reinterpret_cast<Address>(
v8::TryCatch::JSStackComparableAddress(try_catch_handler()));
}
void Free() {
ASSERT(!has_pending_message_);
ASSERT(!external_caught_exception_);
ASSERT(try_catch_handler_address_ == NULL);
ASSERT(try_catch_handler_ == NULL);
}
Isolate* isolate_;
@ -281,7 +284,7 @@ class ThreadLocalTop BASE_EMBEDDED {
private:
void InitializeInternal();
Address try_catch_handler_address_;
v8::TryCatch* try_catch_handler_;
};
@ -559,7 +562,7 @@ class Isolate {
thread_local_top_.pending_message_script_ = heap_.the_hole_value();
}
v8::TryCatch* try_catch_handler() {
return thread_local_top_.TryCatchHandler();
return thread_local_top_.try_catch_handler();
}
Address try_catch_handler_address() {
return thread_local_top_.try_catch_handler_address();

View File

@ -38,9 +38,6 @@ typedef int (*mips_regexp_matcher)(String*, int, const byte*, const byte*,
(FUNCTION_CAST<mips_regexp_matcher>(entry)( \
p0, p1, p2, p3, NULL, p4, p5, p6, p7, p8))
#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
reinterpret_cast<TryCatch*>(try_catch_address)
// The stack limit beyond which we will throw stack overflow errors in
// generated code. Because generated code on mips uses the C stack, we
// just use the C stack limit.
@ -390,10 +387,6 @@ class Simulator {
Simulator::current(Isolate::Current())->Call( \
entry, 10, p0, p1, p2, p3, NULL, p4, p5, p6, p7, p8)
#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
try_catch_address == NULL ? \
NULL : *(reinterpret_cast<TryCatch**>(try_catch_address))
// The simulator has its own stack. Thus it has a different stack limit from
// the C-based native code. Setting the c_limit to indicate a very small

View File

@ -24,9 +24,6 @@ typedef int (*regexp_matcher)(String*, int, const byte*,
#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \
(FUNCTION_CAST<regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6, p7, p8))
#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
(reinterpret_cast<TryCatch*>(try_catch_address))
// The stack limit beyond which we will throw stack overflow errors in
// generated code. Because generated code on x64 uses the C stack, we
// just use the C stack limit.

View File

@ -15,11 +15,6 @@
namespace v8 {
namespace internal {
#if defined(__has_feature)
#if __has_feature(address_sanitizer)
#define V8_USE_ADDRESS_SANITIZER
#endif
#endif
class Segment;
class Isolate;