mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 15:23:51 +00:00
Bug 1848369 - Add checksum to Stencil XDR content. r=nbp
Differential Revision: https://phabricator.services.mozilla.com/D186025
This commit is contained in:
parent
c2089aeeb8
commit
0d04f4494b
@ -198,6 +198,7 @@ MSG_DEF(JSMSG_ALLOC_OVERFLOW, 0, JSEXN_INTERNALERR, "allocation size ov
|
||||
MSG_DEF(JSMSG_BAD_BYTECODE, 1, JSEXN_INTERNALERR, "unimplemented JavaScript bytecode {0}")
|
||||
MSG_DEF(JSMSG_BUFFER_TOO_SMALL, 0, JSEXN_INTERNALERR, "buffer too small")
|
||||
MSG_DEF(JSMSG_BYTECODE_TOO_BIG, 2, JSEXN_INTERNALERR, "bytecode {0} too large (limit {1})")
|
||||
MSG_DEF(JSMSG_DECODE_FAILURE, 0, JSEXN_INTERNALERR, "failed to decode cache")
|
||||
MSG_DEF(JSMSG_NEED_DIET, 1, JSEXN_INTERNALERR, "{0} too large")
|
||||
MSG_DEF(JSMSG_OUT_OF_MEMORY, 0, JSEXN_INTERNALERR, "out of memory")
|
||||
MSG_DEF(JSMSG_OVER_RECURSED, 0, JSEXN_INTERNALERR, "too much recursion")
|
||||
|
@ -1404,19 +1404,6 @@ static XDRResult VersionCheck(XDRState<mode>* xdr) {
|
||||
return Ok();
|
||||
}
|
||||
|
||||
template <XDRMode mode>
|
||||
static XDRResult XDRStencilHeader(XDRState<mode>* xdr,
|
||||
const JS::ReadOnlyDecodeOptions* maybeOptions,
|
||||
RefPtr<ScriptSource>& source) {
|
||||
// The XDR-Stencil header is inserted at beginning of buffer, but it is
|
||||
// computed at the end the incremental-encoding process.
|
||||
|
||||
MOZ_TRY(VersionCheck(xdr));
|
||||
MOZ_TRY(frontend::StencilXDR::codeSource(xdr, maybeOptions, source));
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
XDRResult XDRStencilEncoder::codeStencil(
|
||||
const RefPtr<ScriptSource>& source,
|
||||
const frontend::CompilationStencil& stencil) {
|
||||
@ -1427,10 +1414,32 @@ XDRResult XDRStencilEncoder::codeStencil(
|
||||
|
||||
MOZ_TRY(frontend::StencilXDR::checkCompilationStencil(this, stencil));
|
||||
|
||||
MOZ_TRY(XDRStencilHeader(this, nullptr,
|
||||
const_cast<RefPtr<ScriptSource>&>(source)));
|
||||
MOZ_TRY(VersionCheck(this));
|
||||
|
||||
uint32_t dummy = 0;
|
||||
size_t lengthOffset = buf->cursor();
|
||||
MOZ_TRY(codeUint32(&dummy));
|
||||
size_t hashOffset = buf->cursor();
|
||||
MOZ_TRY(codeUint32(&dummy));
|
||||
|
||||
size_t contentOffset = buf->cursor();
|
||||
MOZ_TRY(frontend::StencilXDR::codeSource(
|
||||
this, nullptr, const_cast<RefPtr<ScriptSource>&>(source)));
|
||||
MOZ_TRY(frontend::StencilXDR::codeCompilationStencil(
|
||||
this, const_cast<frontend::CompilationStencil&>(stencil)));
|
||||
size_t endOffset = buf->cursor();
|
||||
|
||||
if (endOffset > UINT32_MAX) {
|
||||
ReportOutOfMemory(fc());
|
||||
return fail(JS::TranscodeResult::Throw);
|
||||
}
|
||||
|
||||
uint32_t length = endOffset - contentOffset;
|
||||
codeUint32At(&length, lengthOffset);
|
||||
|
||||
const uint8_t* contentBegin = buf->bufferAt(contentOffset);
|
||||
uint32_t hash = mozilla::HashBytes(contentBegin, length);
|
||||
codeUint32At(&hash, hashOffset);
|
||||
|
||||
return Ok();
|
||||
}
|
||||
@ -1478,7 +1487,23 @@ XDRResult XDRStencilDecoder::codeStencil(
|
||||
auto resetOptions = mozilla::MakeScopeExit([&] { options_ = nullptr; });
|
||||
options_ = &options;
|
||||
|
||||
MOZ_TRY(XDRStencilHeader(this, &options, stencil.source));
|
||||
MOZ_TRY(VersionCheck(this));
|
||||
|
||||
uint32_t length;
|
||||
MOZ_TRY(codeUint32(&length));
|
||||
|
||||
uint32_t hash;
|
||||
MOZ_TRY(codeUint32(&hash));
|
||||
|
||||
const uint8_t* contentBegin;
|
||||
MOZ_TRY(peekArray(length, &contentBegin));
|
||||
uint32_t actualHash = mozilla::HashBytes(contentBegin, length);
|
||||
|
||||
if (MOZ_UNLIKELY(actualHash != hash)) {
|
||||
return fail(JS::TranscodeResult::Failure_BadDecode);
|
||||
}
|
||||
|
||||
MOZ_TRY(frontend::StencilXDR::codeSource(this, &options, stencil.source));
|
||||
MOZ_TRY(frontend::StencilXDR::codeCompilationStencil(this, stencil));
|
||||
|
||||
return Ok();
|
||||
|
@ -156,12 +156,12 @@ class StencilXDR {
|
||||
/*
|
||||
* The structure of the Stencil XDR buffer is:
|
||||
*
|
||||
* 1. Header
|
||||
* a. Version
|
||||
* b. ScriptSource
|
||||
* d. Alignment padding
|
||||
* 2. Stencil
|
||||
* a. CompilationStencil
|
||||
* 1. Version
|
||||
* 2. length of content
|
||||
* 3. checksum of content
|
||||
* 4. content
|
||||
* a. ScriptSource
|
||||
* b. CompilationStencil
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -632,12 +632,28 @@ DecodeStencilTask::DecodeStencilTask(JSContext* cx,
|
||||
MOZ_ASSERT(JS::IsTranscodingBytecodeAligned(range.begin().get()));
|
||||
}
|
||||
|
||||
static void ReportDecodeFailure(JS::FrontendContext* fc) {
|
||||
js::ErrorMetadata metadata;
|
||||
metadata.filename = JS::ConstUTF8CharsZ("<unknown>");
|
||||
metadata.lineNumber = 0;
|
||||
metadata.columnNumber = 0;
|
||||
metadata.lineLength = 0;
|
||||
metadata.tokenOffset = 0;
|
||||
metadata.isMuted = false;
|
||||
|
||||
js::ReportCompileErrorLatin1(fc, std::move(metadata), nullptr,
|
||||
JSMSG_DECODE_FAILURE);
|
||||
}
|
||||
|
||||
void DecodeStencilTask::parse(FrontendContext* fc) {
|
||||
JS::DecodeOptions decodeOptions(options);
|
||||
|
||||
JS::TranscodeResult tr =
|
||||
JS::DecodeStencil(fc, decodeOptions, range, getter_AddRefs(stencil_));
|
||||
if (tr != JS::TranscodeResult::Ok) {
|
||||
if (tr != JS::TranscodeResult::Throw) {
|
||||
ReportDecodeFailure(fc);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -92,6 +92,11 @@ class XDRBuffer<XDR_ENCODE> : public XDRBufferBase {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint8_t* bufferAt(size_t cursor) {
|
||||
MOZ_ASSERT(cursor < buffer_.length());
|
||||
return &buffer_[cursor];
|
||||
}
|
||||
|
||||
private:
|
||||
JS::TranscodeBuffer& buffer_;
|
||||
};
|
||||
@ -310,6 +315,38 @@ class XDRState : public XDRCoderBase {
|
||||
|
||||
XDRResult codeUint64(uint64_t* n) { return codeUintImpl(n); }
|
||||
|
||||
void codeUint32At(uint32_t* n, size_t cursor) {
|
||||
if constexpr (mode == XDR_ENCODE) {
|
||||
uint8_t* ptr = buf->bufferAt(cursor);
|
||||
memcpy(ptr, n, sizeof(uint32_t));
|
||||
} else {
|
||||
MOZ_CRASH("not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t* bufferAt(size_t cursor) const {
|
||||
if constexpr (mode == XDR_ENCODE) {
|
||||
return buf->bufferAt(cursor);
|
||||
}
|
||||
|
||||
MOZ_CRASH("not supported.");
|
||||
}
|
||||
|
||||
XDRResult peekArray(size_t n, const uint8_t** p) {
|
||||
if constexpr (mode == XDR_DECODE) {
|
||||
const uint8_t* ptr = buf->peek(n);
|
||||
if (!ptr) {
|
||||
return fail(JS::TranscodeResult::Failure_BadDecode);
|
||||
}
|
||||
|
||||
*p = ptr;
|
||||
|
||||
return mozilla::Ok();
|
||||
}
|
||||
|
||||
MOZ_CRASH("not supported.");
|
||||
}
|
||||
|
||||
/*
|
||||
* Use SFINAE to refuse any specialization which is not an enum. Uses of
|
||||
* this function do not have to specialize the type of the enumerated field
|
||||
|
Loading…
Reference in New Issue
Block a user