aboutsummaryrefslogblamecommitdiff
path: root/www/waterfox/files/patch-bug1418894
blob: b092b623b5b19e9f78fd123f09c2ba2a13400cb5 (plain) (tree)



















































































































































































































































                                                                                                     
commit 408a8eddca66
Author: Ted Campbell <tcampbell@mozilla.com>
Date:   Tue Nov 28 22:52:34 2017 -0500

    Bug 1418894 - Use marker values in XDR data to detect corruption. r=nbp a=gchang
    
    MozReview-Commit-ID: D6PxPBdgtPP
    
    --HG--
    extra : source : 3c5cc7786d922c70b937d1dbe57f0ce700c39551
---
 js/src/jsfun.cpp    |  4 ++++
 js/src/jsscript.cpp | 10 ++++++++++
 js/src/vm/Xdr.h     | 12 ++++++++++++
 3 files changed, 26 insertions(+)

diff --git js/src/jsfun.cpp js/src/jsfun.cpp
index 234d0cc3438c..5a461c9230eb 100644
--- js/src/jsfun.cpp
+++ js/src/jsfun.cpp
@@ -682,6 +682,10 @@ js::XDRInterpretedFunction(XDRState<mode>* xdr, HandleScope enclosingScope,
         objp.set(fun);
     }
 
+    // Verify marker at end of function to detect buffer trunction.
+    if (!xdr->codeMarker(0x9E35CA1F))
+        return false;
+
     return true;
 }
 
diff --git js/src/jsscript.cpp js/src/jsscript.cpp
index 1b31a0639644..88d6c7bc75b6 100644
--- js/src/jsscript.cpp
+++ js/src/jsscript.cpp
@@ -808,6 +808,11 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
             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;
     }
 
     /*
@@ -900,6 +905,11 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
         }
     }
 
+    // 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);
diff --git js/src/vm/Xdr.h js/src/vm/Xdr.h
index 18fa1af8ab5b..0a6cbf01b50f 100644
--- js/src/vm/Xdr.h
+++ js/src/vm/Xdr.h
@@ -307,6 +307,18 @@ class XDRState : public XDRCoderBase
         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;

commit 885c19e8e675
Author: Ted Campbell <tcampbell@mozilla.com>
Date:   Tue Nov 28 23:01:49 2017 -0500

    Bug 1418894 - Harden XDR data decoding. r=nbp a=gchang
    
    This patch adds better error detection to XDR decoding to reduce memory
    corruption in the event that XDR data is corrupt (which is not
    *supposed* to happen).
    
    Add missing default cases. Make out-of-range values fail the decode by
    asserting in debug, and returning a TranscodeError in release. Mix a
    magic value into enum value before transcoding to buffer (to reduce
    chance of garbage data being decoded).
    
    MozReview-Commit-ID: 1wPkho9dm8c
    
    --HG--
    extra : source : 484499ffcbbad636a904832cc90c56c016ad4582
---
 js/src/jsapi.h      |  2 +-
 js/src/jsscript.cpp | 40 ++++++++++++++++++++++------------------
 js/src/shell/js.cpp |  4 ++--
 js/src/vm/Xdr.h     |  8 ++++++--
 4 files changed, 31 insertions(+), 23 deletions(-)

diff --git js/src/jsapi.h js/src/jsapi.h
index 323396025b7a..c43a4c693778 100644
--- js/src/jsapi.h
+++ js/src/jsapi.h
@@ -6420,7 +6420,7 @@ enum TranscodeResult
     TranscodeResult_Failure_BadBuildId =          TranscodeResult_Failure | 0x1,
     TranscodeResult_Failure_RunOnceNotSupported = TranscodeResult_Failure | 0x2,
     TranscodeResult_Failure_AsmJSNotSupported =   TranscodeResult_Failure | 0x3,
-    TranscodeResult_Failure_UnknownClassKind =    TranscodeResult_Failure | 0x4,
+    TranscodeResult_Failure_BadDecode =           TranscodeResult_Failure | 0x4,
     TranscodeResult_Failure_WrongCompileOption =  TranscodeResult_Failure | 0x5,
     TranscodeResult_Failure_NotInterpretedFun =   TranscodeResult_Failure | 0x6,
 
diff --git js/src/jsscript.cpp js/src/jsscript.cpp
index eff03d909353..1b31a0639644 100644
--- js/src/jsscript.cpp
+++ js/src/jsscript.cpp
@@ -92,24 +92,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;
@@ -133,7 +128,7 @@ js::XDRScriptConst(XDRState<mode>* xdr, MutableHandleValue vp)
         }
     }
 
-    if (!xdr->codeUint32(&tag))
+    if (!xdr->codeEnum32(&tag))
         return false;
 
     switch (tag) {
@@ -199,6 +194,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;
 }
@@ -800,6 +799,10 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
               case ScopeKind::WasmFunction:
                 MOZ_CRASH("wasm functions cannot be nested in JSScripts");
                 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)
@@ -890,8 +893,9 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
           }
 
           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);
           }
         }
     }
diff --git js/src/shell/js.cpp js/src/shell/js.cpp
index 16ee93bc66a8..1f5afb04e1f8 100644
--- js/src/shell/js.cpp
+++ js/src/shell/js.cpp
@@ -1519,9 +1519,9 @@ ConvertTranscodeResultToJSException(JSContext* cx, JS::TranscodeResult rv)
         MOZ_ASSERT(!cx->isExceptionPending());
         JS_ReportErrorASCII(cx, "Asm.js is not supported by XDR");
         return false;
-      case JS::TranscodeResult_Failure_UnknownClassKind:
+      case JS::TranscodeResult_Failure_BadDecode:
         MOZ_ASSERT(!cx->isExceptionPending());
-        JS_ReportErrorASCII(cx, "Unknown class kind, go fix it.");
+        JS_ReportErrorASCII(cx, "XDR data corruption");
         return false;
       case JS::TranscodeResult_Failure_WrongCompileOption:
         MOZ_ASSERT(!cx->isExceptionPending());
diff --git js/src/vm/Xdr.h js/src/vm/Xdr.h
index e88968b9a4c0..18fa1af8ab5b 100644
--- js/src/vm/Xdr.h
+++ js/src/vm/Xdr.h
@@ -279,13 +279,17 @@ class XDRState : public XDRCoderBase
     template <typename T>
     bool codeEnum32(T* val, typename mozilla::EnableIf<mozilla::IsEnum<T>::value, T>::Type * = NULL)
     {
+        // Mix the enumeration value with a random magic number, such that a
+        // corruption with a low-ranged value (like 0) is less likely to cause a
+        // miss-interpretation of the XDR content and instead cause a failure.
+        const uint32_t MAGIC = 0x21AB218C;
         uint32_t tmp;
         if (mode == XDR_ENCODE)
-            tmp = uint32_t(*val);
+            tmp = uint32_t(*val) ^ MAGIC;
         if (!codeUint32(&tmp))
             return false;
         if (mode == XDR_DECODE)
-            *val = T(tmp);
+            *val = T(tmp ^ MAGIC);
         return true;
     }