mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-15 22:35:43 +00:00
Bug 1418894 - Harden XDR data decoding. r=nbp
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
This commit is contained in:
parent
bc340a069c
commit
c9e3f6d398
@ -6018,7 +6018,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,
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
@ -792,6 +791,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)
|
||||
@ -882,8 +885,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1512,9 +1512,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());
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user