Make Isolate::GetIncumbentContext() work fine with ASAN

When ASAN is enabled, the previous implementation of
Isolate::GetIncumbentContext didn't work well due to mixture of fake
and real stack frames.

This patch converts an address in the fake stack frame to an address
in the real stack frame so that we can compare two addresses.

Bug: chromium:888867, chromium:866610
Change-Id: Iccf570b8555f2fbdc737b12894a2784ffdb31602
Reviewed-on: https://chromium-review.googlesource.com/c/1343709
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
Commit-Queue: Yuki Shiino <yukishiino@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57662}
This commit is contained in:
Yuki Shiino 2018-11-20 23:32:42 +09:00 committed by Commit Bot
parent 8708d46cc3
commit f379bb117f
2 changed files with 22 additions and 11 deletions

View File

@ -74,6 +74,10 @@
#include "unicode/uobject.h"
#endif // V8_INTL_SUPPORT
#if defined(V8_USE_ADDRESS_SANITIZER)
#include <sanitizer/asan_interface.h>
#endif
extern "C" const uint8_t* v8_Default_embedded_blob_;
extern "C" uint32_t v8_Default_embedded_blob_size_;
@ -2497,14 +2501,23 @@ Handle<Context> Isolate::GetIncumbentContext() {
// if it's newer than the last Context::BackupIncumbentScope entry.
//
// NOTE: This code assumes that the stack grows downward.
// This code doesn't work with ASAN because ASAN seems allocating stack
// separated for native C++ code and compiled JS code, and the following
// comparison doesn't make sense in ASAN.
// TODO(yukishiino): Make the implementation of BackupIncumbentScope more
// robust.
if (!it.done() && (!top_backup_incumbent_scope() ||
it.frame()->sp() < reinterpret_cast<Address>(
top_backup_incumbent_scope()))) {
#if defined(V8_USE_ADDRESS_SANITIZER)
// |it.frame()->sp()| points to an address in the real stack frame, but
// |top_backup_incumbent_scope()| points to an address in a fake stack frame.
// In order to compare them, convert the latter into the address in the real
// stack frame.
void* maybe_fake_top = const_cast<void*>(
reinterpret_cast<const void*>(top_backup_incumbent_scope()));
void* maybe_real_top = __asan_addr_is_in_fake_stack(
__asan_get_current_fake_stack(), maybe_fake_top, nullptr, nullptr);
Address top_backup_incumbent = reinterpret_cast<Address>(
maybe_real_top ? maybe_real_top : maybe_fake_top);
#else
Address top_backup_incumbent =
reinterpret_cast<Address>(top_backup_incumbent_scope());
#endif
if (!it.done() &&
(!top_backup_incumbent || it.frame()->sp() < top_backup_incumbent)) {
Context* context = Context::cast(it.frame()->context());
return Handle<Context>(context->native_context(), this);
}

View File

@ -74,8 +74,7 @@ using IncumbentContextTest = TestWithIsolate;
// Check that Isolate::GetIncumbentContext() returns the correct one in basic
// scenarios.
#if !defined(V8_USE_ADDRESS_SANITIZER)
TEST_F(IncumbentContextTest, MAYBE_Basic) {
TEST_F(IncumbentContextTest, Basic) {
auto Str = [&](const char* s) {
return String::NewFromUtf8(isolate(), s, NewStringType::kNormal)
.ToLocalChecked();
@ -137,6 +136,5 @@ TEST_F(IncumbentContextTest, MAYBE_Basic) {
EXPECT_EQ(global_c, Run(context_a, "funcA()"));
}
}
#endif // !defined(V8_USE_ADDRESS_SANITIZER)
} // namespace v8