diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index df0d8a7b0..a816402c1 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -195,15 +195,21 @@ BytecodeEmitter::updateLocalsToFrameSlots() bool BytecodeEmitter::emitCheck(ptrdiff_t delta, ptrdiff_t* offset) { - *offset = code().length(); - // Start it off moderately large to avoid repeated resizings early on. // ~98% of cases fit within 1024 bytes. if (code().capacity() == 0 && !code().reserve(1024)) return false; + size_t oldLength = code().length(); + *offset = ptrdiff_t(oldLength); + + size_t newLength = oldLength + size_t(delta); + if (MOZ_UNLIKELY(newLength > MaxBytecodeLength)) { + ReportAllocationOverflow(cx); + return false; + } + if (!code().growBy(delta)) { - ReportOutOfMemory(cx); return false; } return true; @@ -8791,12 +8797,18 @@ AllocSrcNote(ExclusiveContext* cx, SrcNotesVector& notes, unsigned* index) if (notes.capacity() == 0 && !notes.reserve(256)) return false; - if (!notes.growBy(1)) { - ReportOutOfMemory(cx); + size_t oldLength = notes.length(); + + if (MOZ_UNLIKELY(oldLength + 1 > MaxSrcNotesLength)) { + ReportAllocationOverflow(cx); return false; } - *index = notes.length() - 1; + if (!notes.growBy(1)) { + return false; + } + + *index = oldLength; return true; } @@ -8922,12 +8934,15 @@ BytecodeEmitter::setSrcNoteOffset(unsigned index, unsigned which, ptrdiff_t offs /* Maybe this offset was already set to a four-byte value. */ if (!(*sn & SN_4BYTE_OFFSET_FLAG)) { /* Insert three dummy bytes that will be overwritten shortly. */ + if (MOZ_UNLIKELY(notes.length() + 3 > MaxSrcNotesLength)) { + ReportAllocationOverflow(cx); + return false; + } jssrcnote dummy = 0; if (!(sn = notes.insert(sn, dummy)) || !(sn = notes.insert(sn, dummy)) || !(sn = notes.insert(sn, dummy))) { - ReportOutOfMemory(cx); return false; } } diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h index 7d4b31d1c..6fb611eaa 100644 --- a/js/src/frontend/BytecodeEmitter.h +++ b/js/src/frontend/BytecodeEmitter.h @@ -659,6 +659,9 @@ struct BytecodeEmitter bool emitSuperElemOp(ParseNode* pn, JSOp op, bool isCall = false); }; +static constexpr size_t MaxBytecodeLength = INT32_MAX; +static constexpr size_t MaxSrcNotesLength = INT32_MAX; + } /* namespace frontend */ } /* namespace js */ diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index a769bf1db..94c07e1fa 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -844,21 +844,8 @@ CodeGenerator::visitFunctionDispatch(LFunctionDispatch* lir) { MFunctionDispatch* mir = lir->mir(); Register input = ToRegister(lir->input()); - Label* lastLabel; - size_t casesWithFallback; - - // Determine if the last case is fallback or an ordinary case. - if (!mir->hasFallback()) { - MOZ_ASSERT(mir->numCases() > 0); - casesWithFallback = mir->numCases(); - lastLabel = skipTrivialBlocks(mir->getCaseBlock(mir->numCases() - 1))->lir()->label(); - } else { - casesWithFallback = mir->numCases() + 1; - lastLabel = skipTrivialBlocks(mir->getFallback())->lir()->label(); - } - - // Compare function pointers, except for the last case. - for (size_t i = 0; i < casesWithFallback - 1; i++) { + // Compare function pointers + for (size_t i = 0; i < mir->numCases(); i++) { MOZ_ASSERT(i < mir->numCases()); LBlock* target = skipTrivialBlocks(mir->getCaseBlock(i))->lir(); if (ObjectGroup* funcGroup = mir->getCaseObjectGroup(i)) { @@ -870,8 +857,14 @@ CodeGenerator::visitFunctionDispatch(LFunctionDispatch* lir) } } - // Jump to the last case. - masm.jump(lastLabel); + // If at the end, and we have a fallback, we can jump to the fallback block. + if (mir->hasFallback()) { + masm.jump(skipTrivialBlocks(mir->getFallback())->lir()->label()); + return; + } + + // Otherwise, crash. + masm.assumeUnreachable("Did not match input function!"); } void @@ -914,13 +907,12 @@ CodeGenerator::visitObjectGroupDispatch(LObjectGroupDispatch* lir) if (!mir->hasFallback()) { MOZ_ASSERT(lastBranch.isInitialized()); -#ifdef DEBUG + Label ok; lastBranch.relink(&ok); lastBranch.emit(masm); masm.assumeUnreachable("Unexpected ObjectGroup"); masm.bind(&ok); -#endif if (!isNextBlock(lastBlock)) masm.jump(lastBlock->label()); return;