Copied from: https://hg.mozilla.org/releases/mozilla-esr38/rev/0f7224441f20 Security advisory: https://www.mozilla.org/en-US/security/advisories/mfsa2016-01/ Mozilla Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1234280 # HG changeset patch # User Benjamin Bouvier # Date 1450947090 -3600 # Node ID 0f7224441f2089001f7934b46ac10cb72d267606 # Parent debff255c08e898be370e307e1e014f5601c20c6 Bug 1234280: Handle oom in CodeGeneratorShared::allocateData; r=jandem, a=sledru diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -7902,17 +7902,19 @@ const VMFunction GetPropertyIC::UpdateIn void CodeGenerator::visitGetPropertyIC(OutOfLineUpdateCache* ool, DataPtr& ic) { LInstruction* lir = ool->lir(); if (ic->idempotent()) { size_t numLocs; CacheLocationList& cacheLocs = lir->mirRaw()->toGetPropertyCache()->location(); - size_t locationBase = addCacheLocations(cacheLocs, &numLocs); + size_t locationBase; + if (!addCacheLocations(cacheLocs, &numLocs, &locationBase)) + return; ic->setLocationInfo(locationBase, numLocs); } saveLive(lir); pushArg(ic->object()); pushArg(Imm32(ool->getCacheIndex())); pushArg(ImmGCPtr(gen->info().script())); diff --git a/js/src/jit/shared/CodeGenerator-shared.cpp b/js/src/jit/shared/CodeGenerator-shared.cpp --- a/js/src/jit/shared/CodeGenerator-shared.cpp +++ b/js/src/jit/shared/CodeGenerator-shared.cpp @@ -1527,31 +1527,34 @@ CodeGeneratorShared::jumpToBlock(MBasicB masm.propagateOOM(patchableBackedges_.append(PatchableBackedgeInfo(backedge, mir->lir()->label(), oolEntry))); } else { masm.j(cond, mir->lir()->label()); } } #endif -size_t -CodeGeneratorShared::addCacheLocations(const CacheLocationList& locs, size_t* numLocs) +MOZ_WARN_UNUSED_RESULT bool +CodeGeneratorShared::addCacheLocations(const CacheLocationList& locs, size_t* numLocs, + size_t* curIndex) { size_t firstIndex = runtimeData_.length(); size_t numLocations = 0; for (CacheLocationList::iterator iter = locs.begin(); iter != locs.end(); iter++) { // allocateData() ensures that sizeof(CacheLocation) is word-aligned. // If this changes, we will need to pad to ensure alignment. - size_t curIndex = allocateData(sizeof(CacheLocation)); - new (&runtimeData_[curIndex]) CacheLocation(iter->pc, iter->script); + if (!allocateData(sizeof(CacheLocation), curIndex)) + return false; + new (&runtimeData_[*curIndex]) CacheLocation(iter->pc, iter->script); numLocations++; } MOZ_ASSERT(numLocations != 0); *numLocs = numLocations; - return firstIndex; + *curIndex = firstIndex; + return true; } ReciprocalMulConstants CodeGeneratorShared::computeDivisionConstants(int d) { // In what follows, d is positive and is not a power of 2. MOZ_ASSERT(d > 0 && (d & (d - 1)) != 0); // Speeding up division by non power-of-2 constants is possible by diff --git a/js/src/jit/shared/CodeGenerator-shared.h b/js/src/jit/shared/CodeGenerator-shared.h --- a/js/src/jit/shared/CodeGenerator-shared.h +++ b/js/src/jit/shared/CodeGenerator-shared.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 jit_shared_CodeGenerator_shared_h #define jit_shared_CodeGenerator_shared_h #include "mozilla/Alignment.h" +#include "mozilla/TypeTraits.h" #include "jit/JitFrames.h" #include "jit/LIR.h" #include "jit/MacroAssembler.h" #include "jit/MIRGenerator.h" #include "jit/MIRGraph.h" #include "jit/OptimizationTracking.h" #include "jit/Safepoints.h" @@ -242,24 +243,16 @@ class CodeGeneratorShared : public LElem return SlotToStackOffset(a->toStackSlot()->slot()); } uint32_t frameSize() const { return frameClass_ == FrameSizeClass::None() ? frameDepth_ : frameClass_.frameSize(); } protected: - // Ensure the cache is an IonCache while expecting the size of the derived - // class. We only need the cache list at GC time. Everyone else can just take - // runtimeData offsets. - size_t allocateCache(const IonCache&, size_t size) { - size_t dataOffset = allocateData(size); - masm.propagateOOM(cacheList_.append(dataOffset)); - return dataOffset; - } #ifdef CHECK_OSIPOINT_REGISTERS void resetOsiPointRegs(LSafepoint* safepoint); bool shouldVerifyOsiPointRegs(LSafepoint* safepoint); void verifyOsiPointRegs(LSafepoint* safepoint); #endif bool addNativeToBytecodeEntry(const BytecodeSite* site); @@ -295,27 +288,33 @@ class CodeGeneratorShared : public LElem return lookup(); } T * operator*() { return lookup(); } }; protected: - - size_t allocateData(size_t size) { + MOZ_WARN_UNUSED_RESULT + bool allocateData(size_t size, size_t* offset) { MOZ_ASSERT(size % sizeof(void*) == 0); - size_t dataOffset = runtimeData_.length(); + *offset = runtimeData_.length(); masm.propagateOOM(runtimeData_.appendN(0, size)); - return dataOffset; + return !masm.oom(); } + // Ensure the cache is an IonCache while expecting the size of the derived + // class. We only need the cache list at GC time. Everyone else can just take + // runtimeData offsets. template inline size_t allocateCache(const T& cache) { - size_t index = allocateCache(cache, sizeof(mozilla::AlignedStorage2)); + static_assert(mozilla::IsBaseOf::value, "T must inherit from IonCache"); + size_t index; + masm.propagateOOM(allocateData(sizeof(mozilla::AlignedStorage2), &index)); + masm.propagateOOM(cacheList_.append(index)); if (masm.oom()) return SIZE_MAX; // Use the copy constructor on the allocated space. MOZ_ASSERT(index == cacheList_.back()); new (&runtimeData_[index]) T(cache); return index; } @@ -475,17 +474,17 @@ class CodeGeneratorShared : public LElem void callVM(const VMFunction& f, LInstruction* ins, const Register* dynStack = nullptr); template inline OutOfLineCode* oolCallVM(const VMFunction& fun, LInstruction* ins, const ArgSeq& args, const StoreOutputTo& out); void addCache(LInstruction* lir, size_t cacheIndex); - size_t addCacheLocations(const CacheLocationList& locs, size_t* numLocs); + bool addCacheLocations(const CacheLocationList& locs, size_t* numLocs, size_t* offset); ReciprocalMulConstants computeDivisionConstants(int d); protected: void addOutOfLineCode(OutOfLineCode* code, const MInstruction* mir); void addOutOfLineCode(OutOfLineCode* code, const BytecodeSite* site); bool hasOutOfLineCode() { return !outOfLineCode_.empty(); } bool generateOutOfLineCode();