Title: [223024] trunk/Source/_javascript_Core
Revision
223024
Author
[email protected]
Date
2017-10-07 18:10:19 -0700 (Sat, 07 Oct 2017)

Log Message

Octane/splay can leak memory due to stray pointers on the stack when run from the command line
https://bugs.webkit.org/show_bug.cgi?id=178054

Reviewed by Saam Barati.
        
This throws in a bunch of sanitize calls. It fixes the problem. It's also performance-neutral. In
most cases, calling the sanitize function is O(1), because it doesn't have anything to do if the stack
height stays relatively constant.

* dfg/DFGOperations.cpp:
* dfg/DFGTierUpCheckInjectionPhase.cpp:
(JSC::DFG::TierUpCheckInjectionPhase::run):
* ftl/FTLOSREntry.cpp:
* heap/Heap.cpp:
(JSC::Heap::runCurrentPhase):
* heap/MarkedAllocatorInlines.h:
(JSC::MarkedAllocator::tryAllocate):
(JSC::MarkedAllocator::allocate):
* heap/Subspace.cpp:
(JSC::Subspace::tryAllocateSlow):
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::sanitizeStackInline):
* jit/ThunkGenerators.cpp:
(JSC::slowPathFor):
* runtime/VM.h:
(JSC::VM::addressOfLastStackTop):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (223023 => 223024)


--- trunk/Source/_javascript_Core/ChangeLog	2017-10-07 23:44:45 UTC (rev 223023)
+++ trunk/Source/_javascript_Core/ChangeLog	2017-10-08 01:10:19 UTC (rev 223024)
@@ -1,3 +1,32 @@
+2017-10-07  Filip Pizlo  <[email protected]>
+
+        Octane/splay can leak memory due to stray pointers on the stack when run from the command line
+        https://bugs.webkit.org/show_bug.cgi?id=178054
+
+        Reviewed by Saam Barati.
+        
+        This throws in a bunch of sanitize calls. It fixes the problem. It's also performance-neutral. In
+        most cases, calling the sanitize function is O(1), because it doesn't have anything to do if the stack
+        height stays relatively constant.
+
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGTierUpCheckInjectionPhase.cpp:
+        (JSC::DFG::TierUpCheckInjectionPhase::run):
+        * ftl/FTLOSREntry.cpp:
+        * heap/Heap.cpp:
+        (JSC::Heap::runCurrentPhase):
+        * heap/MarkedAllocatorInlines.h:
+        (JSC::MarkedAllocator::tryAllocate):
+        (JSC::MarkedAllocator::allocate):
+        * heap/Subspace.cpp:
+        (JSC::Subspace::tryAllocateSlow):
+        * jit/AssemblyHelpers.h:
+        (JSC::AssemblyHelpers::sanitizeStackInline):
+        * jit/ThunkGenerators.cpp:
+        (JSC::slowPathFor):
+        * runtime/VM.h:
+        (JSC::VM::addressOfLastStackTop):
+
 2017-10-07  Yusuke Suzuki  <[email protected]>
 
         `async` should be able to be used as an imported binding name

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (223023 => 223024)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2017-10-07 23:44:45 UTC (rev 223023)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2017-10-08 01:10:19 UTC (rev 223024)
@@ -2540,6 +2540,8 @@
     // really be profitable.
     DeferGCForAWhile deferGC(codeBlock->vm()->heap);
     
+    sanitizeStackForVM(codeBlock->vm());
+
     if (Options::verboseOSR())
         dataLog(*codeBlock, ": Entered reoptimize\n");
     // We must be called with the baseline code block.
@@ -2665,6 +2667,8 @@
     DeferGCForAWhile deferGC(vm->heap);
     CodeBlock* codeBlock = exec->codeBlock();
     
+    sanitizeStackForVM(vm);
+
     if (codeBlock->jitType() != JITCode::DFGJIT) {
         dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
         RELEASE_ASSERT_NOT_REACHED();
@@ -2719,7 +2723,7 @@
     // The following is only true for triggerTierUpNowInLoop, which can never
     // be an OSR entry.
     bool canOSRFromHere = originBytecodeIndex == osrEntryBytecodeIndex;
-
+    
     bool triggeredSlowPathToStartCompilation = false;
     auto tierUpEntryTriggers = jitCode->tierUpEntryTriggers.find(originBytecodeIndex);
     if (tierUpEntryTriggers != jitCode->tierUpEntryTriggers.end()) {
@@ -2899,6 +2903,8 @@
     DeferGCForAWhile deferGC(vm->heap);
     CodeBlock* codeBlock = exec->codeBlock();
 
+    sanitizeStackForVM(vm);
+
     if (codeBlock->jitType() != JITCode::DFGJIT) {
         dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
         RELEASE_ASSERT_NOT_REACHED();
@@ -2933,6 +2939,8 @@
     DeferGCForAWhile deferGC(vm->heap);
     CodeBlock* codeBlock = exec->codeBlock();
 
+    sanitizeStackForVM(vm);
+
     if (codeBlock->jitType() != JITCode::DFGJIT) {
         dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
         RELEASE_ASSERT_NOT_REACHED();

Modified: trunk/Source/_javascript_Core/dfg/DFGTierUpCheckInjectionPhase.cpp (223023 => 223024)


--- trunk/Source/_javascript_Core/dfg/DFGTierUpCheckInjectionPhase.cpp	2017-10-07 23:44:45 UTC (rev 223023)
+++ trunk/Source/_javascript_Core/dfg/DFGTierUpCheckInjectionPhase.cpp	2017-10-08 01:10:19 UTC (rev 223024)
@@ -74,7 +74,7 @@
 
         if (!ensureGlobalFTLWhitelist().contains(m_graph.m_profiledBlock))
             return false;
-
+        
 #if ENABLE(FTL_JIT)
         FTL::CapabilityLevel level = FTL::canCompile(m_graph);
         if (level == FTL::CannotCompile)

Modified: trunk/Source/_javascript_Core/ftl/FTLOSREntry.cpp (223023 => 223024)


--- trunk/Source/_javascript_Core/ftl/FTLOSREntry.cpp	2017-10-07 23:44:45 UTC (rev 223023)
+++ trunk/Source/_javascript_Core/ftl/FTLOSREntry.cpp	2017-10-08 01:10:19 UTC (rev 223024)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2014, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions

Modified: trunk/Source/_javascript_Core/heap/Heap.cpp (223023 => 223024)


--- trunk/Source/_javascript_Core/heap/Heap.cpp	2017-10-07 23:44:45 UTC (rev 223023)
+++ trunk/Source/_javascript_Core/heap/Heap.cpp	2017-10-08 01:10:19 UTC (rev 223024)
@@ -1092,6 +1092,9 @@
     checkConn(conn);
     m_currentThreadState = currentThreadState;
     
+    if (conn == GCConductor::Mutator)
+        sanitizeStackForVM(vm());
+    
     // If the collector transfers the conn to the mutator, it leaves us in between phases.
     if (!finishChangingPhase(conn)) {
         // A mischevious mutator could repeatedly relinquish the conn back to us. We try to avoid doing

Modified: trunk/Source/_javascript_Core/heap/MarkedAllocatorInlines.h (223023 => 223024)


--- trunk/Source/_javascript_Core/heap/MarkedAllocatorInlines.h	2017-10-07 23:44:45 UTC (rev 223023)
+++ trunk/Source/_javascript_Core/heap/MarkedAllocatorInlines.h	2017-10-08 01:10:19 UTC (rev 223024)
@@ -39,6 +39,7 @@
 {
     return m_freeList.allocate(
         [&] () -> HeapCell* {
+            sanitizeStackForVM(heap()->vm());
             return static_cast<HeapCell*>(tryAllocateSlowCase(deferralContext));
         });
 }
@@ -47,6 +48,7 @@
 {
     return m_freeList.allocate(
         [&] () -> HeapCell* {
+            sanitizeStackForVM(heap()->vm());
             return static_cast<HeapCell*>(allocateSlowCase(deferralContext));
         });
 }

Modified: trunk/Source/_javascript_Core/heap/Subspace.cpp (223023 => 223024)


--- trunk/Source/_javascript_Core/heap/Subspace.cpp	2017-10-07 23:44:45 UTC (rev 223023)
+++ trunk/Source/_javascript_Core/heap/Subspace.cpp	2017-10-08 01:10:19 UTC (rev 223024)
@@ -207,6 +207,8 @@
 
 void* Subspace::tryAllocateSlow(GCDeferralContext* deferralContext, size_t size)
 {
+    sanitizeStackForVM(m_space.heap()->vm());
+    
     if (MarkedAllocator* allocator = allocatorFor(size))
         return allocator->tryAllocate(deferralContext);
     

Modified: trunk/Source/_javascript_Core/jit/AssemblyHelpers.cpp (223023 => 223024)


--- trunk/Source/_javascript_Core/jit/AssemblyHelpers.cpp	2017-10-07 23:44:45 UTC (rev 223023)
+++ trunk/Source/_javascript_Core/jit/AssemblyHelpers.cpp	2017-10-08 01:10:19 UTC (rev 223024)
@@ -898,6 +898,19 @@
 #endif
 }
 
+void AssemblyHelpers::sanitizeStackInline(VM& vm, GPRReg scratch)
+{
+    loadPtr(vm.addressOfLastStackTop(), scratch);
+    Jump done = branchPtr(BelowOrEqual, stackPointerRegister, scratch);
+    Label loop = label();
+    storePtr(TrustedImmPtr(0), scratch);
+    addPtr(TrustedImmPtr(sizeof(void*)), scratch);
+    branchPtr(Above, stackPointerRegister, scratch).linkTo(loop, this);
+    done.link(this);
+    move(stackPointerRegister, scratch);
+    storePtr(scratch, vm.addressOfLastStackTop());
+}
+
 } // namespace JSC
 
 #endif // ENABLE(JIT)

Modified: trunk/Source/_javascript_Core/jit/AssemblyHelpers.h (223023 => 223024)


--- trunk/Source/_javascript_Core/jit/AssemblyHelpers.h	2017-10-07 23:44:45 UTC (rev 223023)
+++ trunk/Source/_javascript_Core/jit/AssemblyHelpers.h	2017-10-08 01:10:19 UTC (rev 223024)
@@ -1387,6 +1387,8 @@
         return branchTest8(Zero, AbsoluteAddress(vm.heap.addressOfMutatorShouldBeFenced()));
     }
     
+    void sanitizeStackInline(VM&, GPRReg scratch);
+    
     // Emits the branch structure for typeof. The code emitted by this doesn't fall through. The
     // functor is called at those points where we have pinpointed a type. One way to use this is to
     // have the functor emit the code to put the type string into an appropriate register and then

Modified: trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp (223023 => 223024)


--- trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp	2017-10-07 23:44:45 UTC (rev 223023)
+++ trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp	2017-10-08 01:10:19 UTC (rev 223024)
@@ -81,6 +81,7 @@
 static void slowPathFor(
     CCallHelpers& jit, VM* vm, Sprt_JITOperation_ECli slowPathFunction)
 {
+    jit.sanitizeStackInline(*vm, GPRInfo::nonArgGPR0);
     jit.emitFunctionPrologue();
     jit.storePtr(GPRInfo::callFrameRegister, &vm->topCallFrame);
 #if OS(WINDOWS) && CPU(X86_64)

Modified: trunk/Source/_javascript_Core/runtime/VM.h (223023 => 223024)


--- trunk/Source/_javascript_Core/runtime/VM.h	2017-10-07 23:44:45 UTC (rev 223023)
+++ trunk/Source/_javascript_Core/runtime/VM.h	2017-10-08 01:10:19 UTC (rev 223024)
@@ -553,6 +553,7 @@
         return isSafeToRecurse(m_stackLimit);
     }
 
+    void** addressOfLastStackTop() { return &m_lastStackTop; }
     void* lastStackTop() { return m_lastStackTop; }
     void setLastStackTop(void*);
     
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to