Stack overflow checkers are now compatible with ASAN's detect_stack_use_after_return...
authorishell@chromium.org <ishell@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 3 Jul 2014 08:52:28 +0000 (08:52 +0000)
committerishell@chromium.org <ishell@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 3 Jul 2014 08:52:28 +0000 (08:52 +0000)
BUG=chromium:376287
BUG=chromium:376262
BUG=chromium:369962
LOG=N
R=jkummerow@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22183 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/api.cc
src/base/macros.h
src/execution.cc
src/execution.h
src/isolate.cc
src/isolate.h
src/preparser.h
test/cctest/test-parsing.cc

index 4af691515f3a7184288dd4511dde913c12fcf8c7..fd1cb993c2bbf6729ef937d33d8752ddeee2859a 100644 (file)
@@ -1848,19 +1848,10 @@ v8::TryCatch::TryCatch()
       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_)));
+  js_stack_comparable_address_ =
+      reinterpret_cast<void*>(v8::internal::SimulatorStack::RegisterCTryCatch(
+          GetCurrentStackPosition()));
   isolate_->RegisterTryCatchHandler(this);
 }
 
index cb5bf7965cae5bbecbb28041d552a8335252ca5b..543c074e5c877b06e79484c1ae2389c143049b3b 100644 (file)
@@ -246,4 +246,14 @@ inline uint32_t RoundDownToPowerOf2(uint32_t x) {
   return rounded_up;
 }
 
+
+// Returns current value of top of the stack. Works correctly with ASAN.
+DISABLE_ASAN
+inline uintptr_t GetCurrentStackPosition() {
+  // Takes the address of the limit variable in order to find out where
+  // the top of stack is right now.
+  uintptr_t limit = reinterpret_cast<uintptr_t>(&limit);
+  return limit;
+}
+
 #endif   // V8_BASE_MACROS_H_
index 3a31c7fe86a18be3a9926afaffde8f045277c143..e3eee224771c9202266a2983b03feea2c4c8e55e 100644 (file)
@@ -443,11 +443,9 @@ void StackGuard::ThreadLocal::Clear() {
 bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) {
   bool should_set_stack_limits = false;
   if (real_climit_ == kIllegalLimit) {
-    // Takes the address of the limit variable in order to find out where
-    // the top of stack is right now.
     const uintptr_t kLimitSize = FLAG_stack_size * KB;
-    uintptr_t limit = reinterpret_cast<uintptr_t>(&limit) - kLimitSize;
-    ASSERT(reinterpret_cast<uintptr_t>(&limit) > kLimitSize);
+    ASSERT(GetCurrentStackPosition() > kLimitSize);
+    uintptr_t limit = GetCurrentStackPosition() - kLimitSize;
     real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
     jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
     real_climit_ = limit;
index 8d7b69362d9ec8dc1fdb7becae6999d16a5a4140..2a41bb8ba0d68a1fba217f5f3f301d9fa072294a 100644 (file)
@@ -261,11 +261,6 @@ class StackGuard V8_FINAL {
     int interrupt_flags_;
   };
 
-  class StackPointer {
-   public:
-    inline uintptr_t address() { return reinterpret_cast<uintptr_t>(this); }
-  };
-
   // TODO(isolates): Technically this could be calculated directly from a
   //                 pointer to StackGuard.
   Isolate* isolate_;
index 8f2fa4aa098ff373b19e013d29c8c9147d98afb9..5eb1021e7f98af3e9d76c6698819f43bcbfd1e7e 100644 (file)
@@ -2354,7 +2354,7 @@ bool StackLimitCheck::JsHasOverflowed() const {
   uintptr_t jssp = reinterpret_cast<uintptr_t>(jssp_address);
   if (jssp < stack_guard->real_jslimit()) return true;
 #endif  // USE_SIMULATOR
-  return reinterpret_cast<uintptr_t>(this) < stack_guard->real_climit();
+  return GetCurrentStackPosition() < stack_guard->real_climit();
 }
 
 
index aa9796edc3870517f462d8c6edd963f87e78d578..5c4725b7d077fe2111cc2ddc424f1142dc280a74 100644 (file)
@@ -1417,7 +1417,7 @@ class StackLimitCheck BASE_EMBEDDED {
   // Use this to check for stack-overflows in C++ code.
   inline bool HasOverflowed() const {
     StackGuard* stack_guard = isolate_->stack_guard();
-    return reinterpret_cast<uintptr_t>(this) < stack_guard->real_climit();
+    return GetCurrentStackPosition() < stack_guard->real_climit();
   }
 
   // Use this to check for stack-overflow when entering runtime from JS code.
index d6be902713dc578af4e0f1e854736508db7b70b3..d14393811d7e6767e68597a7edba74c94faabfc2 100644 (file)
@@ -246,8 +246,7 @@ class ParserBase : public Traits {
   INLINE(Token::Value Next()) {
     if (stack_overflow_) return Token::ILLEGAL;
     {
-      int marker;
-      if (reinterpret_cast<uintptr_t>(&marker) < stack_limit_) {
+      if (GetCurrentStackPosition() < stack_limit_) {
         // Any further calls to Next or peek will return the illegal token.
         // The current call must return the next token, which might already
         // have been peek'ed.
index 47f5e6abecef02c5ae37e43f3249c61e781570be..b12098a85a19e5352471686389ca8387a1789031 100644 (file)
@@ -143,9 +143,8 @@ TEST(ScanHTMLEndComments) {
   };
 
   // Parser/Scanner needs a stack limit.
-  int marker;
-  CcTest::i_isolate()->stack_guard()->SetStackLimit(
-      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
+  CcTest::i_isolate()->stack_guard()->SetStackLimit(GetCurrentStackPosition() -
+                                                    128 * 1024);
   uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
   for (int i = 0; tests[i]; i++) {
     const i::byte* source =
@@ -199,9 +198,8 @@ TEST(UsingCachedData) {
   v8::HandleScope handles(isolate);
   v8::Local<v8::Context> context = v8::Context::New(isolate);
   v8::Context::Scope context_scope(context);
-  int marker;
-  CcTest::i_isolate()->stack_guard()->SetStackLimit(
-      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
+  CcTest::i_isolate()->stack_guard()->SetStackLimit(GetCurrentStackPosition() -
+                                                    128 * 1024);
 
   // Source containing functions that might be lazily compiled  and all types
   // of symbols (string, propertyName, regexp).
@@ -247,9 +245,8 @@ TEST(PreparseFunctionDataIsUsed) {
   v8::HandleScope handles(isolate);
   v8::Local<v8::Context> context = v8::Context::New(isolate);
   v8::Context::Scope context_scope(context);
-  int marker;
-  CcTest::i_isolate()->stack_guard()->SetStackLimit(
-      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
+  CcTest::i_isolate()->stack_guard()->SetStackLimit(GetCurrentStackPosition() -
+                                                    128 * 1024);
 
   const char* good_code =
       "function this_is_lazy() { var a; } function foo() { return 25; } foo();";
@@ -282,9 +279,8 @@ TEST(PreparseFunctionDataIsUsed) {
 TEST(StandAlonePreParser) {
   v8::V8::Initialize();
 
-  int marker;
-  CcTest::i_isolate()->stack_guard()->SetStackLimit(
-      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
+  CcTest::i_isolate()->stack_guard()->SetStackLimit(GetCurrentStackPosition() -
+                                                    128 * 1024);
 
   const char* programs[] = {
       "{label: 42}",
@@ -319,9 +315,8 @@ TEST(StandAlonePreParser) {
 TEST(StandAlonePreParserNoNatives) {
   v8::V8::Initialize();
 
-  int marker;
-  CcTest::i_isolate()->stack_guard()->SetStackLimit(
-      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
+  CcTest::i_isolate()->stack_guard()->SetStackLimit(GetCurrentStackPosition() -
+                                                    128 * 1024);
 
   const char* programs[] = {
       "%ArgleBargle(glop);",
@@ -358,9 +353,8 @@ TEST(PreparsingObjectLiterals) {
   v8::HandleScope handles(isolate);
   v8::Local<v8::Context> context = v8::Context::New(isolate);
   v8::Context::Scope context_scope(context);
-  int marker;
-  CcTest::i_isolate()->stack_guard()->SetStackLimit(
-      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
+  CcTest::i_isolate()->stack_guard()->SetStackLimit(GetCurrentStackPosition() -
+                                                    128 * 1024);
 
   {
     const char* source = "var myo = {if: \"foo\"}; myo.if;";
@@ -392,9 +386,7 @@ TEST(RegressChromium62639) {
   v8::V8::Initialize();
   i::Isolate* isolate = CcTest::i_isolate();
 
-  int marker;
-  isolate->stack_guard()->SetStackLimit(
-      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
+  isolate->stack_guard()->SetStackLimit(GetCurrentStackPosition() - 128 * 1024);
 
   const char* program = "var x = 'something';\n"
                         "escape: function() {}";
@@ -429,9 +421,7 @@ TEST(Regress928) {
   // as with-content, which made it assume that a function inside
   // the block could be lazily compiled, and an extra, unexpected,
   // entry was added to the data.
-  int marker;
-  isolate->stack_guard()->SetStackLimit(
-      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
+  isolate->stack_guard()->SetStackLimit(GetCurrentStackPosition() - 128 * 1024);
 
   const char* program =
       "try { } catch (e) { var foo = function () { /* first */ } }"
@@ -473,9 +463,8 @@ TEST(Regress928) {
 TEST(PreParseOverflow) {
   v8::V8::Initialize();
 
-  int marker;
-  CcTest::i_isolate()->stack_guard()->SetStackLimit(
-      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
+  CcTest::i_isolate()->stack_guard()->SetStackLimit(GetCurrentStackPosition() -
+                                                    128 * 1024);
 
   size_t kProgramSize = 1024 * 1024;
   i::SmartArrayPointer<char> program(i::NewArray<char>(kProgramSize + 1));
@@ -1097,9 +1086,7 @@ TEST(ScopePositions) {
   v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
   v8::Context::Scope context_scope(context);
 
-  int marker;
-  isolate->stack_guard()->SetStackLimit(
-      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
+  isolate->stack_guard()->SetStackLimit(GetCurrentStackPosition() - 128 * 1024);
 
   for (int i = 0; source_data[i].outer_prefix; i++) {
     int kPrefixLen = Utf8LengthHelper(source_data[i].outer_prefix);
@@ -1400,9 +1387,8 @@ TEST(ParserSync) {
   v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
   v8::Context::Scope context_scope(context);
 
-  int marker;
-  CcTest::i_isolate()->stack_guard()->SetStackLimit(
-      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
+  CcTest::i_isolate()->stack_guard()->SetStackLimit(GetCurrentStackPosition() -
+                                                    128 * 1024);
 
   static const ParserFlag flags1[] = {
     kAllowLazy, kAllowHarmonyScoping, kAllowModules, kAllowGenerators,
@@ -1478,9 +1464,8 @@ void RunParserSyncTest(const char* context_data[][2],
   v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
   v8::Context::Scope context_scope(context);
 
-  int marker;
-  CcTest::i_isolate()->stack_guard()->SetStackLimit(
-      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
+  CcTest::i_isolate()->stack_guard()->SetStackLimit(GetCurrentStackPosition() -
+                                                    128 * 1024);
 
   static const ParserFlag default_flags[] = {
     kAllowLazy, kAllowHarmonyScoping, kAllowModules, kAllowGenerators,
@@ -2153,9 +2138,8 @@ TEST(DontRegressPreParserDataSizes) {
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope handles(isolate);
 
-  int marker;
-  CcTest::i_isolate()->stack_guard()->SetStackLimit(
-      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
+  CcTest::i_isolate()->stack_guard()->SetStackLimit(GetCurrentStackPosition() -
+                                                    128 * 1024);
 
   struct TestCase {
     const char* program;