Bug 1332594 - Part 2: Check AssemblerBuffer for corruption during realloc. r=jandem
authorEmanuel Hoogeveen <emanuel.hoogeveen@gmail.com>
Mon, 30 Jan 2017 14:57:53 +0100
changeset 331770 51901165b259a99aafe7d96edfb297fa7f333edd
parent 331769 1064fae59e5d7ca5bf208e3253b2f411181b608f
child 331771 e1bf3889601e94e852799a9a539fd1ff81a7178e
push id31286
push usercbook@mozilla.com
push dateTue, 31 Jan 2017 14:54:46 +0000
treeherdermozilla-central@b47946b2076f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1332594
milestone54.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1332594 - Part 2: Check AssemblerBuffer for corruption during realloc. r=jandem
js/src/ds/PageProtectingVector.h
--- a/js/src/ds/PageProtectingVector.h
+++ b/js/src/ds/PageProtectingVector.h
@@ -3,16 +3,17 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef ds_PageProtectingVector_h
 #define ds_PageProtectingVector_h
 
 #include "mozilla/Atomics.h"
+#include "mozilla/PodOperations.h"
 #include "mozilla/Vector.h"
 
 #include "ds/MemoryProtectionExceptionHandler.h"
 #include "gc/Memory.h"
 #include "js/Utility.h"
 
 namespace js {
 
@@ -449,59 +450,53 @@ PageProtectingVector<T, A, B, C, D, E, F
 {
     if (MOZ_LIKELY(length() + size <= capacity()))
         return appendNewPage(values, size);
     return appendNewBuffer(values, size);
 }
 
 class ProtectedReallocPolicy
 {
-    /* We hardcode the page size here to minimize administrative overhead. */
-    static const size_t pageShift = 12;
-    static const size_t pageSize = 1 << pageShift;
-    static const size_t pageMask = pageSize - 1;
-
   public:
     template <typename T> T* maybe_pod_malloc(size_t numElems) {
         return js_pod_malloc<T>(numElems);
     }
     template <typename T> T* maybe_pod_calloc(size_t numElems) {
         return js_pod_calloc<T>(numElems);
     }
     template <typename T> T* maybe_pod_realloc(T* oldAddr, size_t oldSize, size_t newSize) {
         MOZ_ASSERT_IF(oldAddr, oldSize);
-        MOZ_ASSERT(gc::SystemPageSize() == pageSize);
         if (MOZ_UNLIKELY(!newSize))
             return nullptr;
         if (MOZ_UNLIKELY(!oldAddr))
             return js_pod_malloc<T>(newSize);
 
-        T* newAddr = nullptr;
-        size_t initPage = (uintptr_t(oldAddr - 1) >> pageShift) + 1;
-        size_t lastPage = (uintptr_t(oldAddr + oldSize) >> pageShift) - 1;
-        size_t toCopy = (newSize >= oldSize ? oldSize : newSize) * sizeof(T);
-        if (MOZ_UNLIKELY(oldSize >= 32 * 1024 && lastPage >= initPage)) {
-            T* protectAddr = reinterpret_cast<T*>(initPage << pageShift);
-            size_t protectSize = (lastPage - initPage + 1) << pageShift;
-            MemoryProtectionExceptionHandler::addRegion(protectAddr, protectSize);
-            gc::MakePagesReadOnly(protectAddr, protectSize);
-            newAddr = js_pod_malloc<T>(newSize);
-            if (MOZ_LIKELY(newAddr))
-                memcpy(newAddr, oldAddr, toCopy);
-            gc::UnprotectPages(protectAddr, protectSize);
-            MemoryProtectionExceptionHandler::removeRegion(protectAddr);
-            if (MOZ_LIKELY(newAddr))
-                js_free(oldAddr);
-        } else {
-            newAddr = js_pod_malloc<T>(newSize);
-            if (MOZ_LIKELY(newAddr)) {
-                memcpy(newAddr, oldAddr, toCopy);
-                js_free(oldAddr);
-            }
+        T* tmpAddr = js_pod_malloc<T>(newSize);
+        if (MOZ_UNLIKELY(!tmpAddr))
+            return js_pod_realloc<T>(oldAddr, oldSize, newSize);
+
+        size_t bytes = (newSize >= oldSize ? oldSize : newSize) * sizeof(T);
+        memcpy(tmpAddr, oldAddr, bytes);
+
+        T* newAddr = js_pod_realloc<T>(oldAddr, oldSize, newSize);
+        if (MOZ_UNLIKELY(!newAddr)) {
+            js_free(tmpAddr);
+            return js_pod_realloc<T>(oldAddr, oldSize, newSize);
         }
+
+        const uint8_t* newAddrBytes = reinterpret_cast<const uint8_t*>(newAddr);
+        const uint8_t* tmpAddrBytes = reinterpret_cast<const uint8_t*>(tmpAddr);
+        if (!mozilla::PodEqual(tmpAddrBytes, newAddrBytes, bytes)) {
+            if (oldAddr == newAddr)
+                MOZ_CRASH("New buffer doesn't match the old buffer (newAddr == oldAddr)!");
+            else
+                MOZ_CRASH("New buffer doesn't match the old buffer (newAddr != oldAddr)!");
+        }
+
+        js_free(tmpAddr);
         return newAddr;
     }
 
     template <typename T> T* pod_malloc(size_t numElems) { return maybe_pod_malloc<T>(numElems); }
     template <typename T> T* pod_calloc(size_t numElems) { return maybe_pod_calloc<T>(numElems); }
     template <typename T> T* pod_realloc(T* p, size_t oldSize, size_t newSize) {
         return maybe_pod_realloc<T>(p, oldSize, newSize);
     }