Bug 1402167 - Check JSScript::data integrity in XDR r=nbp
authorTed Campbell <tcampbell@mozilla.com>
Thu, 21 Sep 2017 19:39:42 -0400
changeset 382579 ddff620ec86abbb80d2e3e46d105e30938729481
parent 382578 db561b3fd2655dffd04aaa0995f3cb06c3f36d09
child 382580 bec1b493c91e58f9e26e370905e9c2d8fd1ba992
push id32562
push userarchaeopteryx@coole-files.de
push dateSat, 23 Sep 2017 09:38:29 +0000
treeherdermozilla-central@8db0c4ecd94c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs1402167
milestone58.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 1402167 - Check JSScript::data integrity in XDR r=nbp MozReview-Commit-ID: ADBCAUKpakY
js/src/jsscript.cpp
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -66,16 +66,32 @@ using namespace js;
 using namespace js::gc;
 using namespace js::frontend;
 
 using mozilla::AsVariant;
 using mozilla::PodCopy;
 using mozilla::PodZero;
 using mozilla::RotateLeft;
 
+
+// Check that JSScript::data hasn't experienced obvious memory corruption.
+// This is a diagnositic for Bug 1367896.
+static void
+CheckScriptDataIntegrity(JSScript* script)
+{
+    ScopeArray* sa = script->scopes();
+    uint8_t* ptr = reinterpret_cast<uint8_t*>(sa->vector);
+
+    // Check that scope data - who's pointer is stored in data region - also
+    // points within the data region.
+    MOZ_RELEASE_ASSERT(ptr >= script->data &&
+                       ptr + sa->length <= script->data + script->dataSize(),
+                       "Corrupt JSScript::data");
+}
+
 template<XDRMode mode>
 bool
 js::XDRScriptConst(XDRState<mode>* xdr, MutableHandleValue vp)
 {
     JSContext* cx = xdr->cx();
 
     /*
      * A script constant can be an arbitrary primitive value as they are used
@@ -357,16 +373,18 @@ js::XDRScript(XDRState<mode>* xdr, Handl
     RootedScript script(cx);
     natoms = nsrcnotes = 0;
     nconsts = nobjects = nscopes = nregexps = ntrynotes = nscopenotes = nyieldoffsets = 0;
 
     if (mode == XDR_ENCODE) {
         script = scriptp.get();
         MOZ_ASSERT(script->functionNonDelazifying() == fun);
 
+        CheckScriptDataIntegrity(script);
+
         if (!fun && script->treatAsRunOnce() && script->hasRunOnce()) {
             // This is a toplevel or eval script that's runOnce.  We want to
             // make sure that we're not XDR-saving an object we emitted for
             // JSOP_OBJECT that then got modified.  So throw if we're not
             // cloning in JSOP_OBJECT or if we ever didn't clone in it in the
             // past.
             JSCompartment* comp = cx->compartment();
             if (!comp->creationOptions().cloneSingletons() ||
@@ -932,16 +950,18 @@ js::XDRScript(XDRState<mode>* xdr, Handl
         if (!XDRRelazificationInfo(xdr, fun, script, scriptEnclosingScope, &lazy))
             return false;
 
         if (mode == XDR_DECODE)
             script->setLazyScript(lazy);
     }
 
     if (mode == XDR_DECODE) {
+        CheckScriptDataIntegrity(script);
+
         scriptp.set(script);
 
         /* see BytecodeEmitter::tellDebuggerAboutCompiledScript */
         if (!fun && !cx->helperThread())
             Debugger::onNewScript(cx, script);
     }
 
     return true;
@@ -3488,16 +3508,18 @@ js::detail::CopyScript(JSContext* cx, Ha
 {
     if (src->treatAsRunOnce() && !src->functionNonDelazifying()) {
         JS_ReportErrorASCII(cx, "No cloning toplevel run-once scripts");
         return false;
     }
 
     /* NB: Keep this in sync with XDRScript. */
 
+    CheckScriptDataIntegrity(src);
+
     /* Some embeddings are not careful to use ExposeObjectToActiveJS as needed. */
     MOZ_ASSERT(!src->sourceObject()->isMarkedGray());
 
     uint32_t nconsts   = src->hasConsts()   ? src->consts()->length   : 0;
     uint32_t nobjects  = src->hasObjects()  ? src->objects()->length  : 0;
     uint32_t nscopes   = src->scopes()->length;
     uint32_t ntrynotes = src->hasTrynotes() ? src->trynotes()->length : 0;
     uint32_t nscopenotes = src->hasScopeNotes() ? src->scopeNotes()->length : 0;