diff options
Diffstat (limited to 'js/src/jsscript.cpp')
-rw-r--r-- | js/src/jsscript.cpp | 93 |
1 files changed, 59 insertions, 34 deletions
diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index 2e02aa63d..9f914943e 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -75,24 +75,19 @@ js::XDRScriptConst(XDRState<mode>* xdr, MutableHandleValue vp) { JSContext* cx = xdr->cx(); - /* - * A script constant can be an arbitrary primitive value as they are used - * to implement JSOP_LOOKUPSWITCH. But they cannot be objects, see - * bug 407186. - */ enum ConstTag { - SCRIPT_INT = 0, - SCRIPT_DOUBLE = 1, - SCRIPT_ATOM = 2, - SCRIPT_TRUE = 3, - SCRIPT_FALSE = 4, - SCRIPT_NULL = 5, - SCRIPT_OBJECT = 6, - SCRIPT_VOID = 7, - SCRIPT_HOLE = 8 + SCRIPT_INT, + SCRIPT_DOUBLE, + SCRIPT_ATOM, + SCRIPT_TRUE, + SCRIPT_FALSE, + SCRIPT_NULL, + SCRIPT_OBJECT, + SCRIPT_VOID, + SCRIPT_HOLE }; - uint32_t tag; + ConstTag tag; if (mode == XDR_ENCODE) { if (vp.isInt32()) { tag = SCRIPT_INT; @@ -116,7 +111,7 @@ js::XDRScriptConst(XDRState<mode>* xdr, MutableHandleValue vp) } } - if (!xdr->codeUint32(&tag)) + if (!xdr->codeEnum32(&tag)) return false; switch (tag) { @@ -182,6 +177,10 @@ js::XDRScriptConst(XDRState<mode>* xdr, MutableHandleValue vp) if (mode == XDR_DECODE) vp.setMagic(JS_ELEMENTS_HOLE); break; + default: + // Fail in debug, but only soft-fail in release + MOZ_ASSERT(false, "Bad XDR value kind"); + return xdr->fail(JS::TranscodeResult_Failure_BadDecode); } return true; } @@ -317,6 +316,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope, HandleScrip IsLegacyGenerator, IsStarGenerator, IsAsync, + HasRest, OwnSource, ExplicitUseStrict, SelfHosted, @@ -432,6 +432,8 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope, HandleScrip scriptBits |= (1 << IsStarGenerator); if (script->asyncKind() == AsyncFunction) scriptBits |= (1 << IsAsync); + if (script->hasRest()) + scriptBits |= (1 << HasRest); if (script->hasSingletons()) scriptBits |= (1 << HasSingleton); if (script->treatAsRunOnce()) @@ -583,6 +585,8 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope, HandleScrip if (scriptBits & (1 << IsAsync)) script->setAsyncKind(AsyncFunction); + if (scriptBits & (1 << HasRest)) + script->setHasRest(); } JS_STATIC_ASSERT(sizeof(jsbytecode) == 1); @@ -742,11 +746,20 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope, HandleScrip case ScopeKind::Module: MOZ_CRASH("NYI"); break; + default: + // Fail in debug, but only soft-fail in release + MOZ_ASSERT(false, "Bad XDR scope kind"); + return xdr->fail(JS::TranscodeResult_Failure_BadDecode); } if (mode == XDR_DECODE) vector[i].init(scope); } + + // Verify marker to detect data corruption after decoding scope data. A + // mismatch here indicates we will almost certainly crash in release. + if (!xdr->codeMarker(0xF81F7F5A)) + return false; } /* @@ -832,12 +845,18 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope, HandleScrip } default: { - MOZ_ASSERT(false, "Unknown class kind."); - return xdr->fail(JS::TranscodeResult_Failure_UnknownClassKind); + // Fail in debug, but only soft-fail in release + MOZ_ASSERT(false, "Bad XDR class kind"); + return xdr->fail(JS::TranscodeResult_Failure_BadDecode); } } } + // Verify marker to detect data corruption after decoding object data. A + // mismatch here indicates we will almost certainly crash in release. + if (!xdr->codeMarker(0x223DB179)) + return false; + if (ntrynotes != 0) { JSTryNote* tnfirst = script->trynotes()->vector; MOZ_ASSERT(script->trynotes()->length == ntrynotes); @@ -1675,6 +1694,16 @@ ScriptSource::substringDontDeflate(JSContext* cx, size_t start, size_t stop) return NewStringCopyNDontDeflate<CanGC>(cx, chars, len); } +JSFlatString* +ScriptSource::functionBodyString(JSContext* cx) +{ + MOZ_ASSERT(isFunctionBody()); + + size_t start = parameterListEnd_ + (sizeof(FunctionConstructorMedialSigils) - 1); + size_t stop = length() - (sizeof(FunctionConstructorFinalBrace) - 1); + return substring(cx, start, stop); +} + MOZ_MUST_USE bool ScriptSource::setSource(ExclusiveContext* cx, mozilla::UniquePtr<char16_t[], JS::FreePolicy>&& source, @@ -1726,10 +1755,9 @@ ScriptSource::setCompressedSource(SharedImmutableString&& raw, size_t uncompress bool ScriptSource::setSourceCopy(ExclusiveContext* cx, SourceBufferHolder& srcBuf, - bool argumentsNotIncluded, SourceCompressionTask* task) + SourceCompressionTask* task) { MOZ_ASSERT(!hasSourceData()); - argumentsNotIncluded_ = argumentsNotIncluded; auto& cache = cx->zone()->runtimeFromAnyThread()->sharedImmutableStrings(); auto deduped = cache.getOrCreate(srcBuf.get(), srcBuf.length(), [&]() { @@ -1926,16 +1954,6 @@ ScriptSource::performXDR(XDRState<mode>* xdr) if (!xdr->codeUint32(&compressedLength)) return false; - { - uint8_t argumentsNotIncluded; - if (mode == XDR_ENCODE) - argumentsNotIncluded = argumentsNotIncluded_; - if (!xdr->codeUint8(&argumentsNotIncluded)) - return false; - if (mode == XDR_DECODE) - argumentsNotIncluded_ = argumentsNotIncluded; - } - size_t byteLen = compressedLength ? compressedLength : (len * sizeof(char16_t)); if (mode == XDR_DECODE) { uint8_t* p = xdr->cx()->template pod_malloc<uint8_t>(Max<size_t>(byteLen, 1)); @@ -2060,7 +2078,8 @@ FormatIntroducedFilename(ExclusiveContext* cx, const char* filename, unsigned li } bool -ScriptSource::initFromOptions(ExclusiveContext* cx, const ReadOnlyCompileOptions& options) +ScriptSource::initFromOptions(ExclusiveContext* cx, const ReadOnlyCompileOptions& options, + Maybe<uint32_t> parameterListEnd) { MOZ_ASSERT(!filename_); MOZ_ASSERT(!introducerFilename_); @@ -2069,6 +2088,7 @@ ScriptSource::initFromOptions(ExclusiveContext* cx, const ReadOnlyCompileOptions introductionType_ = options.introductionType; setIntroductionOffset(options.introductionOffset); + parameterListEnd_ = parameterListEnd.isSome() ? parameterListEnd.value() : 0; if (options.hasIntroductionInfo) { MOZ_ASSERT(options.introductionType != nullptr); @@ -2622,6 +2642,8 @@ JSScript::initFromFunctionBox(ExclusiveContext* cx, HandleScript script, script->isGeneratorExp_ = funbox->isGenexpLambda; script->setGeneratorKind(funbox->generatorKind()); script->setAsyncKind(funbox->asyncKind()); + if (funbox->hasRest()) + script->setHasRest(); PositionalFormalParameterIter fi(script); while (fi && !fi.closedOver()) @@ -2782,9 +2804,10 @@ JSScript::assertValidJumpTargets() const for (; tn < tnlimit; tn++) { jsbytecode* tryStart = mainEntry + tn->start; jsbytecode* tryPc = tryStart - 1; - if (JSOp(*tryPc) != JSOP_TRY) + if (tn->kind != JSTRY_CATCH && tn->kind != JSTRY_FINALLY) continue; + MOZ_ASSERT(JSOp(*tryPc) == JSOP_TRY); jsbytecode* tryTarget = tryStart + tn->length; MOZ_ASSERT(mainEntry <= tryTarget && tryTarget < end); MOZ_ASSERT(BytecodeIsJumpTarget(JSOp(*tryTarget))); @@ -3280,12 +3303,13 @@ js::detail::CopyScript(JSContext* cx, HandleScript src, HandleScript dst, dst->needsHomeObject_ = src->needsHomeObject(); dst->isDefaultClassConstructor_ = src->isDefaultClassConstructor(); dst->isAsync_ = src->asyncKind() == AsyncFunction; + dst->hasRest_ = src->hasRest_; if (nconsts != 0) { GCPtrValue* vector = Rebase<GCPtrValue>(dst, src, src->consts()->vector); dst->consts()->vector = vector; for (unsigned i = 0; i < nconsts; ++i) - MOZ_ASSERT_IF(vector[i].isMarkable(), vector[i].toString()->isAtom()); + MOZ_ASSERT_IF(vector[i].isGCThing(), vector[i].toString()->isAtom()); } if (nobjects != 0) { GCPtrObject* vector = Rebase<GCPtrObject>(dst, src, src->objects()->vector); @@ -4013,6 +4037,7 @@ LazyScript::Create(ExclusiveContext* cx, HandleFunction fun, p.shouldDeclareArguments = false; p.hasThisBinding = false; p.isAsync = false; + p.hasRest = false; p.numClosedOverBindings = closedOverBindings.length(); p.numInnerFunctions = innerFunctions.length(); p.generatorKindBits = GeneratorKindAsBits(NotGenerator); @@ -4154,7 +4179,7 @@ JSScript::hasLoops() bool JSScript::mayReadFrameArgsDirectly() { - return argumentsHasVarBinding() || (function() && function()->hasRest()); + return argumentsHasVarBinding() || hasRest(); } static inline void |