Backed out 6 changesets (bug 1757833) for causing multiple crashes with MOZ_Z_inflateInit2_. CLOSED TREE

Backed out changeset 6a7d3034db0a (bug 1757833)
Backed out changeset faa0393886db (bug 1757833)
Backed out changeset 4bffe0cf490e (bug 1757833)
Backed out changeset 189b81cc13fd (bug 1757833)
Backed out changeset a59c66e4fb68 (bug 1757833)
Backed out changeset 2b5d9869fbcb (bug 1757833)
This commit is contained in:
Iulian Moraru 2022-05-19 01:14:05 +03:00
Родитель 1022fa6048
Коммит c49f9ffda3
11 изменённых файлов: 11 добавлений и 312 удалений

Просмотреть файл

@ -231,30 +231,6 @@
}, "Do not save bytecode on compilation errors");
promise_test(async function() {
// (see above)
await SpecialPowers.pushPrefEnv({set: [
['dom.script_loader.bytecode_cache.enabled', true],
['dom.expose_test_interfaces', true],
['dom.script_loader.bytecode_cache.strategy', -1],
['browser.cache.jsbc_compression_level', 2]
]});
// Load the test page, and verify that the code path taken by the
// nsScriptLoadRequest corresponds to the code path which is loading a
// source and saving it as compressed bytecode.
var stateMachineResult = WaitForScriptTagEvent(`file_js_cache.html`);
assert_equals(await stateMachineResult, `bytecode_saved`,
`[1-script] ScriptLoadRequest status after the first visit`);
// Reload the same test page, and verify that the code path taken by
// the nsScriptLoadRequest corresponds to the code path which is
// loading compressed bytecode, decompressing it, and executing it.
stateMachineResult = WaitForScriptTagEvent(`file_js_cache.html`);
assert_equals(await stateMachineResult, `bytecode_exec`,
`[2-script] ScriptLoadRequest status after the second visit`);
}, "Check the JS bytecode cache can save and load compressed bytecode");
done();
</script>
</head>

Просмотреть файл

@ -1,174 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "zlib.h"
#include "ScriptLoadRequest.h"
#include "ScriptLoader.h"
#include "mozilla/PerfStats.h"
#include "mozilla/ProfilerMarkers.h"
#include "mozilla/Vector.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/Preferences.h"
#include "mozilla/StaticPrefs_browser.h"
using namespace mozilla;
namespace JS::loader {
#undef LOG
#define LOG(args) \
MOZ_LOG(mozilla::dom::ScriptLoader::gScriptLoaderLog, \
mozilla::LogLevel::Debug, args)
/*
* ScriptBytecodeDataLayout
*
* ScriptBytecodeDataLayout provides accessors to maintain the correct data
* layout of the ScriptLoadRequest's script bytecode buffer.
*/
class ScriptBytecodeDataLayout {
public:
explicit ScriptBytecodeDataLayout(mozilla::Vector<uint8_t>& aBytecode,
size_t aBytecodeOffset)
: mBytecode(aBytecode), mBytecodeOffset(aBytecodeOffset) {}
uint8_t* prelude() const { return mBytecode.begin(); }
size_t preludeLength() const { return mBytecodeOffset; }
uint8_t* bytecode() const { return prelude() + mBytecodeOffset; }
size_t bytecodeLength() const { return mBytecode.length() - preludeLength(); }
mozilla::Vector<uint8_t>& mBytecode;
size_t mBytecodeOffset;
};
/*
* ScriptBytecodeCompressedDataLayout
*
* ScriptBytecodeCompressedDataLayout provides accessors to maintain the correct
* data layout of a compressed script bytecode buffer.
*/
class ScriptBytecodeCompressedDataLayout {
public:
using UncompressedLengthType = uint32_t;
explicit ScriptBytecodeCompressedDataLayout(
mozilla::Vector<uint8_t>& aBytecode, size_t aBytecodeOffset)
: mBytecode(aBytecode), mBytecodeOffset(aBytecodeOffset) {}
uint8_t* prelude() const { return mBytecode.begin(); }
size_t preludeLength() const { return mBytecodeOffset; }
uint8_t* uncompressedLength() const { return prelude() + mBytecodeOffset; }
size_t uncompressedLengthLength() const {
return sizeof(UncompressedLengthType);
}
uint8_t* bytecode() const {
return uncompressedLength() + uncompressedLengthLength();
}
size_t bytecodeLength() const {
return mBytecode.length() - uncompressedLengthLength() - preludeLength();
}
mozilla::Vector<uint8_t>& mBytecode;
size_t mBytecodeOffset;
};
bool ScriptBytecodeCompress(Vector<uint8_t>& aBytecodeBuf,
size_t aBytecodeOffset,
Vector<uint8_t>& aCompressedBytecodeBufOut) {
// TODO probably need to move this to a helper thread
AUTO_PROFILER_MARKER_TEXT("ScriptBytecodeCompress", JS, {}, ""_ns);
PerfStats::AutoMetricRecording<PerfStats::Metric::JSBC_Compression>
autoRecording;
ScriptBytecodeDataLayout uncompressedLayout(aBytecodeBuf, aBytecodeOffset);
ScriptBytecodeCompressedDataLayout compressedLayout(
aCompressedBytecodeBufOut, uncompressedLayout.preludeLength());
ScriptBytecodeCompressedDataLayout::UncompressedLengthType
uncompressedLength = uncompressedLayout.bytecodeLength();
z_stream zstream{.next_in = uncompressedLayout.bytecode(),
.avail_in = uncompressedLength};
auto compressedLength = deflateBound(&zstream, uncompressedLength);
if (!aCompressedBytecodeBufOut.resizeUninitialized(
compressedLength + compressedLayout.preludeLength() +
compressedLayout.uncompressedLengthLength())) {
return false;
}
memcpy(compressedLayout.prelude(), uncompressedLayout.prelude(),
uncompressedLayout.preludeLength());
memcpy(compressedLayout.uncompressedLength(), &uncompressedLength,
sizeof(uncompressedLength));
zstream.next_out = compressedLayout.bytecode();
zstream.avail_out = compressedLength;
const uint32_t compressionLevel =
StaticPrefs::browser_cache_jsbc_compression_level();
if (deflateInit(&zstream, compressionLevel) != Z_OK) {
LOG(
("ScriptLoadRequest: Unable to initialize bytecode cache "
"compression."));
return false;
}
auto autoDestroy = MakeScopeExit([&]() { deflateEnd(&zstream); });
int ret = deflate(&zstream, Z_FINISH);
if (ret == Z_MEM_ERROR) {
return false;
}
MOZ_RELEASE_ASSERT(ret == Z_STREAM_END);
aCompressedBytecodeBufOut.shrinkTo(zstream.next_out -
aCompressedBytecodeBufOut.begin());
return true;
}
bool ScriptBytecodeDecompress(Vector<uint8_t>& aCompressedBytecodeBuf,
size_t aBytecodeOffset,
Vector<uint8_t>& aBytecodeBufOut) {
AUTO_PROFILER_MARKER_TEXT("ScriptBytecodeDecompress", JS, {}, ""_ns);
PerfStats::AutoMetricRecording<PerfStats::Metric::JSBC_Decompression>
autoRecording;
ScriptBytecodeDataLayout uncompressedLayout(aBytecodeBufOut, aBytecodeOffset);
ScriptBytecodeCompressedDataLayout compressedLayout(
aCompressedBytecodeBuf, uncompressedLayout.preludeLength());
ScriptBytecodeCompressedDataLayout::UncompressedLengthType uncompressedLength;
memcpy(&uncompressedLength, compressedLayout.uncompressedLength(),
compressedLayout.uncompressedLengthLength());
if (!aBytecodeBufOut.resizeUninitialized(uncompressedLayout.preludeLength() +
uncompressedLength)) {
return false;
}
memcpy(uncompressedLayout.prelude(), compressedLayout.prelude(),
compressedLayout.preludeLength());
z_stream zstream;
zstream.next_in = compressedLayout.bytecode();
zstream.avail_in = static_cast<uint32_t>(compressedLayout.bytecodeLength());
zstream.next_out = uncompressedLayout.bytecode();
zstream.avail_out = uncompressedLength;
if (inflateInit(&zstream) != Z_OK) {
LOG(("ScriptLoadRequest: inflateInit FAILED (%s)", zstream.msg));
return false;
}
auto autoDestroy = MakeScopeExit([&]() { inflateEnd(&zstream); });
int ret = inflate(&zstream, Z_NO_FLUSH);
bool ok = (ret == Z_OK || ret == Z_STREAM_END) && zstream.avail_in == 0;
if (!ok) {
LOG(("ScriptLoadReques: inflate FAILED (%s)", zstream.msg));
return false;
}
return true;
}
#undef LOG
} // namespace JS::loader

Просмотреть файл

@ -1,43 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef js_loader_ScriptCompression_h
#define js_loader_ScriptCompression_h
#include "ErrorList.h"
#include "mozilla/Vector.h"
namespace JS::loader {
class ScriptLoadRequest;
/**
* Compress the bytecode stored in a buffer. All data before the bytecode is
* copied into the output buffer without modification.
*
* @param aBytecodeBuf buffer containing the uncompressed bytecode
* @param aBytecodeOffset offset of the bytecode in the buffer
* @param aCompressedBytecodeBufOut buffer to store the compressed bytecode in
*/
bool ScriptBytecodeCompress(
mozilla::Vector<uint8_t>& aBytecodeBuf, size_t aBytecodeOffset,
mozilla::Vector<uint8_t>& aCompressedBytecodeBufOut);
/**
* Uncompress the bytecode stored in a buffer. All data before the bytecode is
* copied into the output buffer without modification.
*
* @param aCompressedBytecodeBuf buffer containing the compressed bytecode
* @param aBytecodeOffset offset of the bytecode in the buffer
* @param aBytecodeBufOut buffer to store the uncompressed bytecode in
*/
bool ScriptBytecodeDecompress(mozilla::Vector<uint8_t>& aCompressedBytecodeBuf,
size_t aBytecodeOffset,
mozilla::Vector<uint8_t>& aBytecodeBufOut);
} // namespace JS::loader
#endif // js_loader_ScriptCompression_h

Просмотреть файл

@ -8,7 +8,6 @@
#include <stdlib.h>
#include <utility>
#include "ScriptCompression.h"
#include "ScriptLoader.h"
#include "ScriptTrace.h"
#include "js/Transcoding.h"
@ -19,7 +18,6 @@
#include "mozilla/Encoding.h"
#include "mozilla/Logging.h"
#include "mozilla/NotNull.h"
#include "mozilla/PerfStats.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/StaticPrefs_dom.h"
#include "mozilla/Utf8.h"
@ -40,7 +38,6 @@
#include "nsMimeTypes.h"
#include "nsString.h"
#include "nsTArray.h"
#include "zlib.h"
namespace mozilla::dom {
@ -122,7 +119,6 @@ ScriptLoadHandler::OnIncrementalData(nsIIncrementalStreamLoader* aLoader,
nsCOMPtr<nsIRequest> channelRequest;
aLoader->GetRequest(getter_AddRefs(channelRequest));
auto firstTime = !mPreloadStartNotified;
if (!mPreloadStartNotified) {
mPreloadStartNotified = true;
mRequest->GetScriptLoadContext()->NotifyStart(channelRequest);
@ -140,10 +136,6 @@ ScriptLoadHandler::OnIncrementalData(nsIIncrementalStreamLoader* aLoader,
NS_ENSURE_SUCCESS(rv, rv);
}
if (mRequest->IsBytecode() && firstTime) {
PerfStats::RecordMeasurementStart(PerfStats::Metric::JSBC_IO_Read);
}
if (mRequest->IsTextSource()) {
if (!EnsureDecoder(aLoader, aData, aDataLength,
/* aEndOfStream = */ false)) {
@ -347,7 +339,6 @@ ScriptLoadHandler::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
nsCOMPtr<nsIRequest> channelRequest;
aLoader->GetRequest(getter_AddRefs(channelRequest));
auto firstMessage = !mPreloadStartNotified;
if (!mPreloadStartNotified) {
mPreloadStartNotified = true;
mRequest->GetScriptLoadContext()->NotifyStart(channelRequest);
@ -363,12 +354,6 @@ ScriptLoadHandler::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
NS_ENSURE_SUCCESS(rv, rv);
}
if (mRequest->IsBytecode() && !firstMessage) {
// if firstMessage, then entire stream is in aData, and PerfStats would
// measure 0 time
PerfStats::RecordMeasurementEnd(PerfStats::Metric::JSBC_IO_Read);
}
if (mRequest->IsTextSource()) {
DebugOnly<bool> encoderSet =
EnsureDecoder(aLoader, aData, aDataLength, /* aEndOfStream = */ true);
@ -415,16 +400,6 @@ ScriptLoadHandler::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
}
mRequest->mBytecodeOffset = JS::AlignTranscodingBytecodeOffset(sriLength);
Vector<uint8_t> compressedBytecode;
// mRequest has the compressed bytecode, but will be filled with the
// uncompressed bytecode
compressedBytecode.swap(mRequest->mScriptBytecode);
if (!JS::loader::ScriptBytecodeDecompress(compressedBytecode,
mRequest->mBytecodeOffset,
mRequest->mScriptBytecode)) {
return NS_ERROR_UNEXPECTED;
}
}
}

Просмотреть файл

@ -9,8 +9,6 @@
#include "ScriptTrace.h"
#include "ModuleLoader.h"
#include "zlib.h"
#include "prsystem.h"
#include "jsapi.h"
#include "jsfriendapi.h"
@ -19,7 +17,6 @@
#include "js/ContextOptions.h" // JS::ContextOptionsRef
#include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_*
#include "js/loader/ScriptLoadRequest.h"
#include "ScriptCompression.h"
#include "js/loader/LoadedScript.h"
#include "js/loader/ModuleLoadRequest.h"
#include "js/MemoryFunctions.h"
@ -2555,14 +2552,7 @@ void ScriptLoader::EncodeRequestBytecode(JSContext* aCx,
return;
}
Vector<uint8_t> compressedBytecode;
// TODO probably need to move this to a helper thread
if (!ScriptBytecodeCompress(aRequest->mScriptBytecode,
aRequest->mBytecodeOffset, compressedBytecode)) {
return;
}
if (compressedBytecode.length() >= UINT32_MAX) {
if (aRequest->mScriptBytecode.length() >= UINT32_MAX) {
LOG(
("ScriptLoadRequest (%p): Bytecode cache is too large to be decoded "
"correctly.",
@ -2575,8 +2565,7 @@ void ScriptLoader::EncodeRequestBytecode(JSContext* aCx,
// case, we just ignore the current one.
nsCOMPtr<nsIAsyncOutputStream> output;
rv = aRequest->mCacheInfo->OpenAlternativeOutputStream(
BytecodeMimeTypeFor(aRequest),
static_cast<int64_t>(compressedBytecode.length()),
BytecodeMimeTypeFor(aRequest), aRequest->mScriptBytecode.length(),
getter_AddRefs(output));
if (NS_FAILED(rv)) {
LOG(
@ -2593,17 +2582,17 @@ void ScriptLoader::EncodeRequestBytecode(JSContext* aCx,
});
uint32_t n;
rv = output->Write(reinterpret_cast<char*>(compressedBytecode.begin()),
compressedBytecode.length(), &n);
LOG(
("ScriptLoadRequest (%p): Write bytecode cache (rv = %X, length = %u, "
"written = %u)",
aRequest, unsigned(rv), unsigned(compressedBytecode.length()), n));
rv = output->Write(reinterpret_cast<char*>(aRequest->mScriptBytecode.begin()),
aRequest->mScriptBytecode.length(), &n);
LOG((
"ScriptLoadRequest (%p): Write bytecode cache (rv = %X, length = %u, "
"written = %u)",
aRequest, unsigned(rv), unsigned(aRequest->mScriptBytecode.length()), n));
if (NS_FAILED(rv)) {
return;
}
MOZ_RELEASE_ASSERT(compressedBytecode.length() == n);
MOZ_RELEASE_ASSERT(aRequest->mScriptBytecode.length() == n);
bytecodeFailed.release();
TRACE_FOR_TEST_NONE(aRequest->GetScriptLoadContext()->GetScriptElement(),

Просмотреть файл

@ -20,7 +20,6 @@ EXPORTS += [
EXPORTS.mozilla.dom += [
"AutoEntryScript.h",
"ModuleLoader.h",
"ScriptCompression.h",
"ScriptDecoding.h",
"ScriptElement.h",
"ScriptLoadContext.h",
@ -33,7 +32,6 @@ UNIFIED_SOURCES += [
"AutoEntryScript.cpp",
"ModuleLoader.cpp",
"nsIScriptElement.cpp",
"ScriptCompression.cpp",
"ScriptElement.cpp",
"ScriptLoadContext.cpp",
"ScriptLoader.cpp",

Просмотреть файл

@ -325,8 +325,7 @@ class ScriptLoadRequest
size_t mScriptTextLength;
// Holds the SRI serialized hash and the script bytecode for non-inline
// scripts. The data is laid out according to ScriptBytecodeDataLayout
// or, if compression is enabled, ScriptBytecodeCompressedDataLayout.
// scripts.
mozilla::Vector<uint8_t> mScriptBytecode;
uint32_t mBytecodeOffset; // Offset of the bytecode in mScriptBytecode

Просмотреть файл

@ -985,15 +985,6 @@
value: 3
mirror: always
# Compression level for cached JavaScript bytecode
# 0 = do not compress,
# 1 = minimal compression,
# 9 = maximal compression
- name: browser.cache.jsbc_compression_level
type: RelaxedAtomicUint32
value: 0
mirror: always
- name: browser.contentblocking.database.enabled
type: bool
value: false

Просмотреть файл

@ -6,7 +6,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/net/AltDataOutputStreamParent.h"
#include "mozilla/PerfStats.h"
#include "mozilla/Unused.h"
#include "nsIAsyncOutputStream.h"
@ -18,7 +17,6 @@ NS_IMPL_ISUPPORTS0(AltDataOutputStreamParent)
AltDataOutputStreamParent::AltDataOutputStreamParent(nsIOutputStream* aStream)
: mOutputStream(aStream), mStatus(NS_OK), mIPCOpen(true) {
MOZ_ASSERT(NS_IsMainThread(), "Main thread only");
PerfStats::RecordMeasurementStart(PerfStats::Metric::JSBC_IO_Write);
}
AltDataOutputStreamParent::~AltDataOutputStreamParent() {
@ -47,8 +45,6 @@ mozilla::ipc::IPCResult AltDataOutputStreamParent::RecvWriteData(
mozilla::ipc::IPCResult AltDataOutputStreamParent::RecvClose(
const nsresult& aStatus) {
PerfStats::RecordMeasurementEnd(PerfStats::Metric::JSBC_IO_Write);
if (NS_FAILED(mStatus)) {
if (mIPCOpen) {
Unused << SendError(mStatus);

Просмотреть файл

@ -29,11 +29,7 @@ static const char* const sMetricNames[] = {"DisplayListBuilding",
"Styling",
"HttpChannelCompletion",
"HttpChannelCompletion_Network",
"HttpChannelCompletion_Cache",
"JSBC_Compression",
"JSBC_Decompression",
"JSBC_IO_Read",
"JSBC_IO_Write"};
"HttpChannelCompletion_Cache"};
static_assert(sizeof(sMetricNames) / sizeof(sMetricNames[0]) ==
static_cast<uint64_t>(PerfStats::Metric::Max));

Просмотреть файл

@ -32,10 +32,6 @@ class PerfStats {
HttpChannelCompletion,
HttpChannelCompletion_Network,
HttpChannelCompletion_Cache,
JSBC_Compression,
JSBC_Decompression,
JSBC_IO_Read,
JSBC_IO_Write,
Max
};