Bug 1418894 - Use marker values in XDR data to detect corruption. r=nbp a=gchang
authorTed Campbell <tcampbell@mozilla.com>
Tue, 28 Nov 2017 22:52:34 -0500
changeset 442686 73bde255ce55e61a3d01873d846d22b50e1a3428
parent 442685 84ca5dce1d6a63bc64612876eccee30fc45080f9
child 442687 73a12159e3d7e829bab40a251d44f9a0e39b4286
push id8300
push userccoroiu@mozilla.com
push dateMon, 04 Dec 2017 12:38:17 +0000
treeherdermozilla-beta@810f9fabc684 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp, gchang
bugs1418894
milestone58.0
Bug 1418894 - Use marker values in XDR data to detect corruption. r=nbp a=gchang MozReview-Commit-ID: D6PxPBdgtPP
js/src/jsfun.cpp
js/src/jsscript.cpp
js/src/vm/Xdr.h
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -677,16 +677,20 @@ js::XDRInterpretedFunction(XDRState<mode
         }
 
         bool singleton = firstword & HasSingletonType;
         if (!JSFunction::setTypeForScriptedFunction(cx, fun, singleton))
             return false;
         objp.set(fun);
     }
 
+    // Verify marker at end of function to detect buffer trunction.
+    if (!xdr->codeMarker(0x9E35CA1F))
+        return false;
+
     return true;
 }
 
 template bool
 js::XDRInterpretedFunction(XDRState<XDR_ENCODE>*, HandleScope, HandleScriptSource,
                            MutableHandleFunction);
 
 template bool
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -803,16 +803,21 @@ js::XDRScript(XDRState<mode>* xdr, Handl
                 // 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(0x48922BAB))
+            return false;
     }
 
     /*
      * Here looping from 0-to-length to xdr objects is essential to ensure that
      * all references to enclosing blocks (via FindScopeIndex below) happen
      * after the enclosing block has been XDR'd.
      */
     for (i = 0; i != nobjects; ++i) {
@@ -895,16 +900,21 @@ js::XDRScript(XDRState<mode>* xdr, Handl
           default: {
             // 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(0xF83B989A))
+        return false;
+
     if (ntrynotes != 0) {
         JSTryNote* tnfirst = script->trynotes()->vector;
         MOZ_ASSERT(script->trynotes()->length == ntrynotes);
         JSTryNote* tn = tnfirst + ntrynotes;
         do {
             --tn;
             if (!xdr->codeUint8(&tn->kind) ||
                 !xdr->codeUint32(&tn->stackDepth) ||
--- a/js/src/vm/Xdr.h
+++ b/js/src/vm/Xdr.h
@@ -302,16 +302,28 @@ class XDRState : public XDRCoderBase
             pun.d = *dp;
         if (!codeUint64(&pun.u))
             return false;
         if (mode == XDR_DECODE)
             *dp = pun.d;
         return true;
     }
 
+    bool codeMarker(uint32_t magic) {
+        uint32_t actual = magic;
+        if (!codeUint32(&actual))
+            return false;
+        if (actual != magic) {
+            // Fail in debug, but only soft-fail in release
+            MOZ_ASSERT(false, "Bad XDR marker");
+            return fail(JS::TranscodeResult_Failure_BadDecode);
+        }
+        return true;
+    }
+
     bool codeBytes(void* bytes, size_t len) {
         if (len == 0)
             return true;
         if (mode == XDR_ENCODE) {
             uint8_t* ptr = buf.write(len);
             if (!ptr)
                 return fail(JS::TranscodeResult_Throw);
             memcpy(ptr, bytes, len);