зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1732201 - Sandbox woff2 in OTS using RLBox r=bholley
Differential Revision: https://phabricator.services.mozilla.com/D126435
This commit is contained in:
Родитель
f0ef0360eb
Коммит
1ee9a841d8
|
@ -96,7 +96,9 @@ gfx/angle/.*
|
|||
gfx/cairo/.*
|
||||
gfx/graphite2/.*
|
||||
gfx/harfbuzz/.*
|
||||
gfx/ots/.*
|
||||
gfx/ots/src/.*
|
||||
gfx/ots/include/.*
|
||||
gfx/ots/tests/.*
|
||||
gfx/qcms/.*
|
||||
gfx/sfntly/.*
|
||||
gfx/skia/.*
|
||||
|
@ -167,7 +169,8 @@ modules/fdlibm/.*
|
|||
modules/freetype2/.*
|
||||
modules/libbz2/.*
|
||||
modules/pdfium/.*
|
||||
modules/woff2/.*
|
||||
modules/woff2/include/.*
|
||||
modules/woff2/src/.*
|
||||
modules/xz-embedded/.*
|
||||
modules/zlib/.*
|
||||
mozglue/misc/decimal/.*
|
||||
|
|
|
@ -217,7 +217,7 @@ endif
|
|||
ifdef MOZ_USING_WASM_SANDBOXING
|
||||
security/rlbox/target-objects: config/external/wasm2c_sandbox_compiler/host
|
||||
security/rlbox/target: security/rlbox/target-objects
|
||||
dom/media/ogg/target-objects extensions/spellcheck/hunspell/glue/target-objects gfx/thebes/target-objects parser/expat/target-objects parser/htmlparser/target-objects: security/rlbox/target-objects
|
||||
dom/media/ogg/target-objects extensions/spellcheck/hunspell/glue/target-objects gfx/thebes/target-objects parser/expat/target-objects parser/htmlparser/target-objects gfx/ots/src/target-objects: security/rlbox/target-objects
|
||||
endif
|
||||
|
||||
# Most things are built during compile (target/host), but some things happen during export
|
||||
|
|
|
@ -10,3 +10,4 @@ Additional files: README.mozilla, src/moz.build
|
|||
|
||||
Additional patch: ots-visibility.patch (bug 711079).
|
||||
Additional patch: ots-lz4.patch
|
||||
Additional patch: ots-rlbox.patch (bug 1732201).
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
/* -*- 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 "RLBoxWOFF2Host.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/RLBoxUtils.h"
|
||||
#include "mozilla/ScopeExit.h"
|
||||
|
||||
using namespace rlbox;
|
||||
using namespace mozilla;
|
||||
|
||||
tainted_woff2<BrotliDecoderResult> RLBoxBrotliDecoderDecompressCallback(
|
||||
rlbox_sandbox_woff2& aSandbox, tainted_woff2<unsigned long> aEncodedSize,
|
||||
tainted_woff2<const char*> aEncodedBuffer,
|
||||
tainted_woff2<unsigned long*> aDecodedSize,
|
||||
tainted_woff2<char*> aDecodedBuffer) {
|
||||
if (!aEncodedBuffer || !aDecodedSize || !aDecodedBuffer) {
|
||||
return BROTLI_DECODER_RESULT_ERROR;
|
||||
}
|
||||
|
||||
// We don't create temporary buffers for brotli to operate on. Instead we
|
||||
// pass a pointer to the in (encoded) and out (decoded) buffers. We check
|
||||
// (specifically, unverified_safe_pointer checks) that the buffers are within
|
||||
// the sandbox boundary (for the given sizes).
|
||||
|
||||
size_t encodedSize =
|
||||
aEncodedSize.unverified_safe_because("Any size within sandbox is ok.");
|
||||
const uint8_t* encodedBuffer = reinterpret_cast<const uint8_t*>(
|
||||
aEncodedBuffer.unverified_safe_pointer_because(
|
||||
encodedSize, "Pointer fits within sandbox"));
|
||||
|
||||
size_t decodedSize =
|
||||
(*aDecodedSize).unverified_safe_because("Any size within sandbox is ok.");
|
||||
uint8_t* decodedBuffer =
|
||||
reinterpret_cast<uint8_t*>(aDecodedBuffer.unverified_safe_pointer_because(
|
||||
decodedSize, "Pointer fits within sandbox"));
|
||||
|
||||
BrotliDecoderResult res = BrotliDecoderDecompress(
|
||||
encodedSize, encodedBuffer, &decodedSize, decodedBuffer);
|
||||
|
||||
*aDecodedSize = decodedSize;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
UniquePtr<RLBoxSandboxDataBase> RLBoxWOFF2SandboxPool::CreateSandboxData() {
|
||||
// Create woff2 sandbox
|
||||
auto sandbox = MakeUnique<rlbox_sandbox_woff2>();
|
||||
|
||||
#ifdef MOZ_WASM_SANDBOXING_WOFF2
|
||||
bool createOK = sandbox->create_sandbox(/* infallible = */ false);
|
||||
#else
|
||||
bool createOK = sandbox->create_sandbox();
|
||||
#endif
|
||||
NS_ENSURE_TRUE(createOK, nullptr);
|
||||
|
||||
UniquePtr<RLBoxWOFF2SandboxData> sbxData =
|
||||
MakeUnique<RLBoxWOFF2SandboxData>(std::move(sandbox));
|
||||
|
||||
// Register brotli callback
|
||||
sbxData->mDecompressCallback = sbxData->Sandbox()->register_callback(
|
||||
RLBoxBrotliDecoderDecompressCallback);
|
||||
sbxData->Sandbox()->invoke_sandbox_function(RegisterWOFF2Callback,
|
||||
sbxData->mDecompressCallback);
|
||||
|
||||
return sbxData;
|
||||
}
|
||||
|
||||
StaticRefPtr<RLBoxWOFF2SandboxPool> RLBoxWOFF2SandboxPool::sSingleton;
|
||||
|
||||
void RLBoxWOFF2SandboxPool::Initalize(size_t aDelaySeconds) {
|
||||
AssertIsOnMainThread();
|
||||
RLBoxWOFF2SandboxPool::sSingleton = new RLBoxWOFF2SandboxPool(aDelaySeconds);
|
||||
ClearOnShutdown(&RLBoxWOFF2SandboxPool::sSingleton);
|
||||
}
|
||||
|
||||
RLBoxWOFF2SandboxData::RLBoxWOFF2SandboxData(
|
||||
mozilla::UniquePtr<rlbox_sandbox_woff2> aSandbox)
|
||||
: mSandbox(std::move(aSandbox)) {
|
||||
MOZ_COUNT_CTOR(RLBoxWOFF2SandboxData);
|
||||
}
|
||||
|
||||
RLBoxWOFF2SandboxData::~RLBoxWOFF2SandboxData() {
|
||||
MOZ_ASSERT(mSandbox);
|
||||
mDecompressCallback.unregister();
|
||||
mSandbox->destroy_sandbox();
|
||||
MOZ_COUNT_DTOR(RLBoxWOFF2SandboxData);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
using TransferBufferToWOFF2 =
|
||||
mozilla::RLBoxTransferBufferToSandbox<T, rlbox_woff2_sandbox_type>;
|
||||
template <typename T>
|
||||
using WOFF2Alloc = mozilla::RLBoxAllocateInSandbox<T, rlbox_woff2_sandbox_type>;
|
||||
|
||||
bool RLBoxProcessWOFF2(ots::FontFile* aHeader, ots::OTSStream* aOutput,
|
||||
const uint8_t* aData, size_t aLength, uint32_t aIndex,
|
||||
ProcessTTCFunc* aProcessTTC,
|
||||
ProcessTTFFunc* aProcessTTF) {
|
||||
MOZ_ASSERT(aProcessTTC);
|
||||
MOZ_ASSERT(aProcessTTF);
|
||||
|
||||
// We index into aData before processing it (very end of this function). Our
|
||||
// validator ensures that the untrusted size is greater than aLength, so we
|
||||
// just need to conservatively ensure that aLength is greater than the highest
|
||||
// index (7).
|
||||
NS_ENSURE_TRUE(aLength >= 8, false);
|
||||
|
||||
auto sandboxPoolData = RLBoxWOFF2SandboxPool::sSingleton->PopOrCreate();
|
||||
NS_ENSURE_TRUE(sandboxPoolData, false);
|
||||
|
||||
const auto* sandboxData =
|
||||
static_cast<const RLBoxWOFF2SandboxData*>(sandboxPoolData->SandboxData());
|
||||
MOZ_ASSERT(sandboxData);
|
||||
|
||||
auto* sandbox = sandboxData->Sandbox();
|
||||
|
||||
// Transfer aData into the sandbox.
|
||||
|
||||
auto data = TransferBufferToWOFF2<uint8_t>(sandbox, aData, aLength);
|
||||
NS_ENSURE_TRUE(*data, false);
|
||||
|
||||
// Validator for the decompression size.
|
||||
// Returns the size and sets validateOK to true if size is valid (and false
|
||||
// otherwise).
|
||||
bool validateOK = false;
|
||||
auto sizeValidator = [aLength, &validateOK](auto size) {
|
||||
validateOK = false;
|
||||
if (size < aLength) {
|
||||
NS_WARNING("Size of decompressed WOFF 2.0 is less than compressed size");
|
||||
} else if (size == 0) {
|
||||
NS_WARNING("Size of decompressed WOFF 2.0 is set to 0");
|
||||
} else if (size > OTS_MAX_DECOMPRESSED_FILE_SIZE) {
|
||||
NS_WARNING(
|
||||
nsPrintfCString("Size of decompressed WOFF 2.0 font exceeds %gMB",
|
||||
OTS_MAX_DECOMPRESSED_FILE_SIZE / (1024.0 * 1024.0))
|
||||
.get());
|
||||
} else {
|
||||
validateOK = true;
|
||||
}
|
||||
return size;
|
||||
};
|
||||
|
||||
// Get the (estimated) decompression size and validate it.
|
||||
|
||||
size_t decompressedSize =
|
||||
sandbox
|
||||
->invoke_sandbox_function(RLBoxComputeWOFF2FinalSize, *data, aLength)
|
||||
.copy_and_verify(sizeValidator);
|
||||
|
||||
if (NS_WARN_IF(!validateOK)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Perform the actual conversion to TTF.
|
||||
|
||||
auto sizep = WOFF2Alloc<size_t>(sandbox);
|
||||
auto bufp = WOFF2Alloc<uint8_t*>(sandbox);
|
||||
auto bufOwnerString =
|
||||
WOFF2Alloc<void*>(sandbox); // pointer to string that owns the bufer
|
||||
|
||||
if (!sandbox
|
||||
->invoke_sandbox_function(RLBoxConvertWOFF2ToTTF, *data, aLength,
|
||||
decompressedSize, sizep.get(),
|
||||
bufOwnerString.get(), bufp.get())
|
||||
.unverified_safe_because(
|
||||
"The ProcessTT* functions validate the decompressed data.")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto bufCleanup = mozilla::MakeScopeExit([&sandbox, &bufOwnerString] {
|
||||
// Delete the string created by RLBoxConvertWOFF2ToTTF.
|
||||
sandbox->invoke_sandbox_function(RLBoxDeleteWOFF2String,
|
||||
bufOwnerString.get());
|
||||
});
|
||||
|
||||
// Get the actual decompression size and validate it.
|
||||
// We need to validate the size again. RLBoxConvertWOFF2ToTTF works even if
|
||||
// the computed size (with RLBoxComputeWOFF2FinalSize) is wrong, so we can't
|
||||
// trust the decompressedSize to be the same as size sizep.
|
||||
size_t size = (*sizep.get()).copy_and_verify(sizeValidator);
|
||||
|
||||
if (NS_WARN_IF(!validateOK)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint8_t* decompressed =
|
||||
(*bufp.get())
|
||||
.unverified_safe_pointer_because(
|
||||
size, "Only care that the buffer is within sandbox boundary.");
|
||||
|
||||
// Since ProcessTT* memcpy from the buffer, make sure it's not null.
|
||||
NS_ENSURE_TRUE(decompressed, false);
|
||||
|
||||
if (aData[4] == 't' && aData[5] == 't' && aData[6] == 'c' &&
|
||||
aData[7] == 'f') {
|
||||
return aProcessTTC(aHeader, aOutput, decompressed, size, aIndex);
|
||||
}
|
||||
ots::Font font(aHeader);
|
||||
return aProcessTTF(aHeader, &font, aOutput, decompressed, size, 0);
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/* -*- Mode: C++; tab-width: 20; 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 MODULES_WOFF2_RLBOXWOFF2_HOST_H_
|
||||
#define MODULES_WOFF2_RLBOXWOFF2_HOST_H_
|
||||
|
||||
#include "RLBoxWOFF2Types.h"
|
||||
|
||||
// Load general firefox configuration of RLBox
|
||||
#include "mozilla/rlbox/rlbox_config.h"
|
||||
|
||||
#ifdef MOZ_WASM_SANDBOXING_WOFF2
|
||||
// Include the generated header file so that we are able to resolve the symbols
|
||||
// in the wasm binary
|
||||
# include "rlbox.wasm.h"
|
||||
# define RLBOX_USE_STATIC_CALLS() rlbox_wasm2c_sandbox_lookup_symbol
|
||||
# include "mozilla/rlbox/rlbox_wasm2c_sandbox.hpp"
|
||||
#else
|
||||
// Extra configuration for no-op sandbox
|
||||
# define RLBOX_USE_STATIC_CALLS() rlbox_noop_sandbox_lookup_symbol
|
||||
# include "mozilla/rlbox/rlbox_noop_sandbox.hpp"
|
||||
#endif
|
||||
|
||||
#include "mozilla/rlbox/rlbox.hpp"
|
||||
|
||||
#include "woff2/RLBoxWOFF2Sandbox.h"
|
||||
#include "./src/ots.h"
|
||||
|
||||
class RLBoxWOFF2SandboxData : public mozilla::RLBoxSandboxDataBase {
|
||||
friend class RLBoxWOFF2SandboxPool;
|
||||
|
||||
public:
|
||||
RLBoxWOFF2SandboxData(mozilla::UniquePtr<rlbox_sandbox_woff2> aSandbox);
|
||||
~RLBoxWOFF2SandboxData();
|
||||
|
||||
rlbox_sandbox_woff2* Sandbox() const { return mSandbox.get(); }
|
||||
|
||||
private:
|
||||
mozilla::UniquePtr<rlbox_sandbox_woff2> mSandbox;
|
||||
sandbox_callback_woff2<BrotliDecompressCallback*> mDecompressCallback;
|
||||
};
|
||||
|
||||
using ProcessTTCFunc = bool(ots::FontFile* aHeader, ots::OTSStream* aOutput,
|
||||
const uint8_t* aData, size_t aLength,
|
||||
uint32_t aIndex);
|
||||
|
||||
using ProcessTTFFunc = bool(ots::FontFile* aHeader, ots::Font* aFont,
|
||||
ots::OTSStream* aOutput, const uint8_t* aData,
|
||||
size_t aLength, uint32_t aOffset);
|
||||
|
||||
bool RLBoxProcessWOFF2(ots::FontFile* aHeader, ots::OTSStream* aOutput,
|
||||
const uint8_t* aData, size_t aLength, uint32_t aIndex,
|
||||
ProcessTTCFunc* aProcessTTC,
|
||||
ProcessTTFFunc* aProcessTTF);
|
||||
#endif
|
|
@ -0,0 +1,37 @@
|
|||
/* -*- Mode: C++; tab-width: 20; 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 MODULES_WOFF2_RLBOXWOFF2TYPES_H_
|
||||
#define MODULES_WOFF2_RLBOXWOFF2TYPES_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include "mozilla/rlbox/rlbox_types.hpp"
|
||||
#include "woff2/decode.h"
|
||||
|
||||
#ifdef MOZ_WASM_SANDBOXING_WOFF2
|
||||
RLBOX_DEFINE_BASE_TYPES_FOR(woff2, wasm2c)
|
||||
#else
|
||||
RLBOX_DEFINE_BASE_TYPES_FOR(woff2, noop)
|
||||
#endif
|
||||
|
||||
#include "mozilla/RLBoxSandboxPool.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
|
||||
class RLBoxWOFF2SandboxPool : public mozilla::RLBoxSandboxPool {
|
||||
public:
|
||||
explicit RLBoxWOFF2SandboxPool(size_t aDelaySeconds)
|
||||
: RLBoxSandboxPool(aDelaySeconds) {}
|
||||
|
||||
static mozilla::StaticRefPtr<RLBoxWOFF2SandboxPool> sSingleton;
|
||||
static void Initalize(size_t aDelaySeconds = 10);
|
||||
|
||||
protected:
|
||||
mozilla::UniquePtr<mozilla::RLBoxSandboxDataBase> CreateSandboxData()
|
||||
override;
|
||||
~RLBoxWOFF2SandboxPool() = default;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,56 @@
|
|||
diff --git a/gfx/ots/src/ots.cc b/gfx/ots/src/ots.cc
|
||||
--- a/gfx/ots/src/ots.cc
|
||||
+++ b/gfx/ots/src/ots.cc
|
||||
@@ -14,7 +14,7 @@
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
-#include <woff2/decode.h>
|
||||
+#include "../RLBoxWOFF2Host.h"
|
||||
|
||||
// The OpenType Font File
|
||||
// http://www.microsoft.com/typography/otspec/otff.htm
|
||||
@@ -511,39 +511,9 @@ bool ProcessWOFF(ots::FontFile *header,
|
||||
return ProcessGeneric(header, font, woff_tag, output, data, length, tables, file);
|
||||
}
|
||||
|
||||
-bool ProcessWOFF2(ots::FontFile *header,
|
||||
- ots::OTSStream *output,
|
||||
- const uint8_t *data,
|
||||
- size_t length,
|
||||
- uint32_t index) {
|
||||
- size_t decompressed_size = woff2::ComputeWOFF2FinalSize(data, length);
|
||||
-
|
||||
- if (decompressed_size < length) {
|
||||
- return OTS_FAILURE_MSG_HDR("Size of decompressed WOFF 2.0 is less than compressed size");
|
||||
- }
|
||||
-
|
||||
- if (decompressed_size == 0) {
|
||||
- return OTS_FAILURE_MSG_HDR("Size of decompressed WOFF 2.0 is set to 0");
|
||||
- }
|
||||
- // decompressed font must be <= OTS_MAX_DECOMPRESSED_FILE_SIZE
|
||||
- if (decompressed_size > OTS_MAX_DECOMPRESSED_FILE_SIZE) {
|
||||
- return OTS_FAILURE_MSG_HDR("Size of decompressed WOFF 2.0 font exceeds %gMB",
|
||||
- OTS_MAX_DECOMPRESSED_FILE_SIZE / (1024.0 * 1024.0));
|
||||
- }
|
||||
-
|
||||
- std::string buf(decompressed_size, 0);
|
||||
- woff2::WOFF2StringOut out(&buf);
|
||||
- if (!woff2::ConvertWOFF2ToTTF(data, length, &out)) {
|
||||
- return OTS_FAILURE_MSG_HDR("Failed to convert WOFF 2.0 font to SFNT");
|
||||
- }
|
||||
- const uint8_t *decompressed = reinterpret_cast<const uint8_t*>(buf.data());
|
||||
-
|
||||
- if (data[4] == 't' && data[5] == 't' && data[6] == 'c' && data[7] == 'f') {
|
||||
- return ProcessTTC(header, output, decompressed, out.Size(), index);
|
||||
- } else {
|
||||
- ots::Font font(header);
|
||||
- return ProcessTTF(header, &font, output, decompressed, out.Size());
|
||||
- }
|
||||
+bool ProcessWOFF2(ots::FontFile* header, ots::OTSStream* output,
|
||||
+ const uint8_t* data, size_t length, uint32_t index) {
|
||||
+ return RLBoxProcessWOFF2(header, output, data, length, index, ProcessTTC, ProcessTTF);
|
||||
}
|
||||
|
||||
ots::TableAction GetTableAction(const ots::FontFile *header, uint32_t tag) {
|
||||
|
|
@ -7,6 +7,11 @@
|
|||
EXPORTS += [
|
||||
'../include/opentype-sanitiser.h',
|
||||
'../include/ots-memory-stream.h',
|
||||
'../RLBoxWOFF2Types.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'../RLBoxWOFF2Host.cpp'
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
|
@ -71,5 +76,6 @@ USE_LIBS += [
|
|||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'!/security/rlbox',
|
||||
'/modules/woff2/src',
|
||||
]
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include <woff2/decode.h>
|
||||
#include "../RLBoxWOFF2Host.h"
|
||||
|
||||
// The OpenType Font File
|
||||
// http://www.microsoft.com/typography/otspec/otff.htm
|
||||
|
@ -511,39 +511,9 @@ bool ProcessWOFF(ots::FontFile *header,
|
|||
return ProcessGeneric(header, font, woff_tag, output, data, length, tables, file);
|
||||
}
|
||||
|
||||
bool ProcessWOFF2(ots::FontFile *header,
|
||||
ots::OTSStream *output,
|
||||
const uint8_t *data,
|
||||
size_t length,
|
||||
uint32_t index) {
|
||||
size_t decompressed_size = woff2::ComputeWOFF2FinalSize(data, length);
|
||||
|
||||
if (decompressed_size < length) {
|
||||
return OTS_FAILURE_MSG_HDR("Size of decompressed WOFF 2.0 is less than compressed size");
|
||||
}
|
||||
|
||||
if (decompressed_size == 0) {
|
||||
return OTS_FAILURE_MSG_HDR("Size of decompressed WOFF 2.0 is set to 0");
|
||||
}
|
||||
// decompressed font must be <= OTS_MAX_DECOMPRESSED_FILE_SIZE
|
||||
if (decompressed_size > OTS_MAX_DECOMPRESSED_FILE_SIZE) {
|
||||
return OTS_FAILURE_MSG_HDR("Size of decompressed WOFF 2.0 font exceeds %gMB",
|
||||
OTS_MAX_DECOMPRESSED_FILE_SIZE / (1024.0 * 1024.0));
|
||||
}
|
||||
|
||||
std::string buf(decompressed_size, 0);
|
||||
woff2::WOFF2StringOut out(&buf);
|
||||
if (!woff2::ConvertWOFF2ToTTF(data, length, &out)) {
|
||||
return OTS_FAILURE_MSG_HDR("Failed to convert WOFF 2.0 font to SFNT");
|
||||
}
|
||||
const uint8_t *decompressed = reinterpret_cast<const uint8_t*>(buf.data());
|
||||
|
||||
if (data[4] == 't' && data[5] == 't' && data[6] == 'c' && data[7] == 'f') {
|
||||
return ProcessTTC(header, output, decompressed, out.Size(), index);
|
||||
} else {
|
||||
ots::Font font(header);
|
||||
return ProcessTTF(header, &font, output, decompressed, out.Size());
|
||||
}
|
||||
bool ProcessWOFF2(ots::FontFile* header, ots::OTSStream* output,
|
||||
const uint8_t* data, size_t length, uint32_t index) {
|
||||
return RLBoxProcessWOFF2(header, output, data, length, index, ProcessTTC, ProcessTTF);
|
||||
}
|
||||
|
||||
ots::TableAction GetTableAction(const ots::FontFile *header, uint32_t tag) {
|
||||
|
|
|
@ -36,3 +36,6 @@ patch -p3 < ots-visibility.patch
|
|||
|
||||
echo "Applying ots-lz4.patch..."
|
||||
patch -p3 < ots-lz4.patch
|
||||
|
||||
echo "Applying ots-rlbox.patch..."
|
||||
patch -p3 < ots-rlbox.patch
|
||||
|
|
|
@ -19,6 +19,7 @@ UNIFIED_SOURCES += [
|
|||
include("/ipc/chromium/chromium-config.mozbuild")
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
"!/security/rlbox",
|
||||
"../base",
|
||||
"../forms",
|
||||
"../generic",
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
#include "mozilla/intl/nsComplexBreaker.h"
|
||||
|
||||
#include "nsRLBoxExpatDriver.h"
|
||||
#include "RLBoxWOFF2Types.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::net;
|
||||
|
@ -298,6 +299,8 @@ nsresult nsLayoutStatics::Initialize() {
|
|||
|
||||
RLBoxExpatSandboxPool::Initialize();
|
||||
|
||||
RLBoxWOFF2SandboxPool::Initalize();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,3 +12,5 @@ The in-tree copy is updated by running
|
|||
from within the modules/woff2 directory.
|
||||
|
||||
Current version: [commit 1bccf208bca986e53a647dfe4811322adb06ecf8].
|
||||
|
||||
Additional patch: woff2-rlbox.patch (bug 1732201).
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/* -*- 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 <woff2/decode.h>
|
||||
#include <cassert>
|
||||
#include "RLBoxWOFF2Sandbox.h"
|
||||
|
||||
bool RLBoxConvertWOFF2ToTTF(const uint8_t* aData, size_t aLength,
|
||||
size_t aDecompressedSize, size_t* aResultSize,
|
||||
void** aResultOwningStr, uint8_t** aResultData) {
|
||||
std::unique_ptr<std::string> buf =
|
||||
std::make_unique<std::string>(aDecompressedSize, 0);
|
||||
woff2::WOFF2StringOut out(buf.get());
|
||||
if (!woff2::ConvertWOFF2ToTTF(aData, aLength, &out)) {
|
||||
return false;
|
||||
}
|
||||
*aResultSize = out.Size();
|
||||
// Return the string and its underlying C string. We need both to make sure we
|
||||
// can free the string (which we do with RLBoxDeleteWOFF2String).
|
||||
*aResultData = reinterpret_cast<uint8_t*>(buf->data());
|
||||
*aResultOwningStr = static_cast<void*>(buf.release());
|
||||
return true;
|
||||
}
|
||||
|
||||
void RLBoxDeleteWOFF2String(void** aStr) {
|
||||
std::string* buf = static_cast<std::string*>(*aStr);
|
||||
delete buf;
|
||||
}
|
||||
|
||||
size_t RLBoxComputeWOFF2FinalSize(const uint8_t* aData, size_t aLength) {
|
||||
return woff2::ComputeWOFF2FinalSize(aData, aLength);
|
||||
}
|
||||
|
||||
BrotliDecompressCallback* sRLBoxBrotliDecompressCallback = nullptr;
|
||||
|
||||
void RegisterWOFF2Callback(BrotliDecompressCallback* aCallback) {
|
||||
#ifdef MOZ_IN_WASM_SANDBOX
|
||||
// When Woff2 is wasmboxed, we need to register a callback for brotli
|
||||
// decompression. The easiest way to store this is in a static variable. This
|
||||
// is thread-safe because each (potentially-concurrent) woff2 instance gets
|
||||
// its own sandbox with its own copy of the statics.
|
||||
//
|
||||
// When the sandbox is disabled (replaced with the noop sandbox), setting the
|
||||
// callback is actually racey. However, we don't actually need a callback in
|
||||
// that case, and can just invoke brotli directly.
|
||||
sRLBoxBrotliDecompressCallback = aCallback;
|
||||
#endif
|
||||
}
|
||||
|
||||
BrotliDecoderResult RLBoxBrotliDecoderDecompress(size_t aEncodedSize,
|
||||
const uint8_t* aEncodedBuffer,
|
||||
size_t* aDecodedSize,
|
||||
uint8_t* aDecodedBuffer) {
|
||||
#ifdef MOZ_IN_WASM_SANDBOX
|
||||
assert(sRLBoxBrotliDecompressCallback);
|
||||
return sRLBoxBrotliDecompressCallback(
|
||||
aEncodedSize, reinterpret_cast<const char*>(aEncodedBuffer), aDecodedSize,
|
||||
reinterpret_cast<char*>(aDecodedBuffer));
|
||||
#else
|
||||
return BrotliDecoderDecompress(aEncodedSize, aEncodedBuffer, aDecodedSize,
|
||||
aDecodedBuffer);
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/* -*- Mode: C++; tab-width: 20; 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 MODULES_WOFF2_RLBOX_WOFF2_SANDBOX_H_
|
||||
#define MODULES_WOFF2_RLBOX_WOFF2_SANDBOX_H_
|
||||
|
||||
#include <brotli/decode.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
// Since RLBox doesn't support C++ APIs, we expose C wrappers for the WOFF2.
|
||||
size_t RLBoxComputeWOFF2FinalSize(const uint8_t* aData, size_t aLength);
|
||||
bool RLBoxConvertWOFF2ToTTF(const uint8_t* aData, size_t aLength,
|
||||
size_t aDecompressedSize, size_t* aResultSize,
|
||||
void** aResultOwningStr, uint8_t** aResultData);
|
||||
// RLBoxDeleteWOFF2String is used to delete the C++ string allocated by
|
||||
// RLBoxConvertWOFF2ToTTF.
|
||||
void RLBoxDeleteWOFF2String(void** aStr);
|
||||
|
||||
// Type of brotli decoder function. Because RLBox doesn't (yet) cleanly support
|
||||
// {size,uint8}_t types for callbacks, we're using unsigned long instead of
|
||||
// size_t and char instead of uint8_t.
|
||||
|
||||
typedef BrotliDecoderResult(BrotliDecompressCallback)(
|
||||
unsigned long aEncodedSize, const char* aEncodedBuffer,
|
||||
unsigned long* aDecodedSize, char* aDecodedBuffer);
|
||||
|
||||
// Callback to the unsandboxed Brotli.
|
||||
|
||||
extern BrotliDecompressCallback* sRLBoxBrotliDecompressCallback;
|
||||
|
||||
void RegisterWOFF2Callback(BrotliDecompressCallback* aCallback);
|
||||
BrotliDecoderResult RLBoxBrotliDecoderDecompress(size_t aEncodedSize,
|
||||
const uint8_t* aEncodedBuffer,
|
||||
size_t* aDecodedSize,
|
||||
uint8_t* aDecodedBuffer);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -4,24 +4,24 @@
|
|||
# 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("sources.mozbuild")
|
||||
|
||||
with Files('**'):
|
||||
BUG_COMPONENT = ('Core', 'Graphics: Text')
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'src/table_tags.cc',
|
||||
'src/variable_length.cc',
|
||||
'src/woff2_common.cc',
|
||||
'src/woff2_dec.cc',
|
||||
'src/woff2_out.cc',
|
||||
]
|
||||
UNIFIED_SOURCES += woff2_sources
|
||||
|
||||
EXPORTS.woff2 += [
|
||||
'include/woff2/decode.h',
|
||||
'include/woff2/encode.h',
|
||||
'include/woff2/output.h',
|
||||
'RLBoxWOFF2Sandbox.h',
|
||||
|
||||
]
|
||||
|
||||
# We allow warnings for third-party code that can be updated from upstream.
|
||||
AllowCompilerWarnings()
|
||||
|
||||
Library('woff2')
|
||||
|
||||
REQUIRES_UNIFIED_BUILD = True
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
woff2_sources = [
|
||||
'RLBoxWOFF2Sandbox.cpp',
|
||||
'src/table_tags.cc',
|
||||
'src/variable_length.cc',
|
||||
'src/woff2_common.cc',
|
||||
'src/woff2_dec.cc',
|
||||
'src/woff2_out.cc',
|
||||
]
|
|
@ -19,7 +19,6 @@
|
|||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include <brotli/decode.h>
|
||||
#include "./buffer.h"
|
||||
#include "./port.h"
|
||||
#include "./round.h"
|
||||
|
@ -28,6 +27,8 @@
|
|||
#include "./variable_length.h"
|
||||
#include "./woff2_common.h"
|
||||
|
||||
#include "../RLBoxWOFF2Sandbox.h"
|
||||
|
||||
namespace woff2 {
|
||||
|
||||
namespace {
|
||||
|
@ -758,7 +759,7 @@ bool ReconstructTransformedHmtx(const uint8_t* transformed_buf,
|
|||
bool Woff2Uncompress(uint8_t* dst_buf, size_t dst_size,
|
||||
const uint8_t* src_buf, size_t src_size) {
|
||||
size_t uncompressed_size = dst_size;
|
||||
BrotliDecoderResult result = BrotliDecoderDecompress(
|
||||
BrotliDecoderResult result = RLBoxBrotliDecoderDecompress(
|
||||
src_size, src_buf, &uncompressed_size, dst_buf);
|
||||
if (PREDICT_FALSE(result != BROTLI_DECODER_RESULT_SUCCESS ||
|
||||
uncompressed_size != dst_size)) {
|
||||
|
|
|
@ -22,3 +22,6 @@ echo "###"
|
|||
echo "### Updated woff2 to $COMMIT."
|
||||
echo "### Remember to verify and commit the changes to source control!"
|
||||
echo "###"
|
||||
|
||||
echo "Applying woff2-rlbox.patch..."
|
||||
patch -p3 < woff2-rlbox.patch
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
diff --git a/modules/woff2/src/woff2_dec.cc b/modules/woff2/src/woff2_dec.cc
|
||||
--- a/modules/woff2/src/woff2_dec.cc
|
||||
+++ b/modules/woff2/src/woff2_dec.cc
|
||||
@@ -19,7 +19,6 @@
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
-#include <brotli/decode.h>
|
||||
#include "./buffer.h"
|
||||
#include "./port.h"
|
||||
#include "./round.h"
|
||||
@@ -28,6 +27,8 @@
|
||||
#include "./variable_length.h"
|
||||
#include "./woff2_common.h"
|
||||
|
||||
+#include "../RLBoxWOFF2Sandbox.h"
|
||||
+
|
||||
namespace woff2 {
|
||||
|
||||
namespace {
|
||||
@@ -758,7 +759,7 @@ bool ReconstructTransformedHmtx(const uint8_t* transformed_buf,
|
||||
bool Woff2Uncompress(uint8_t* dst_buf, size_t dst_size,
|
||||
const uint8_t* src_buf, size_t src_size) {
|
||||
size_t uncompressed_size = dst_size;
|
||||
- BrotliDecoderResult result = BrotliDecoderDecompress(
|
||||
+ BrotliDecoderResult result = RLBoxBrotliDecoderDecompress(
|
||||
src_size, src_buf, &uncompressed_size, dst_buf);
|
||||
if (PREDICT_FALSE(result != BROTLI_DECODER_RESULT_SUCCESS ||
|
||||
uncompressed_size != dst_size)) {
|
|
@ -36,6 +36,7 @@
|
|||
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/RLBoxUtils.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
#include "mozilla/Logging.h"
|
||||
|
@ -106,34 +107,12 @@ static const XML_Char* unverified_xml_string(uintptr_t ptr) {
|
|||
}
|
||||
|
||||
/* The TransferBuffer class is used to copy (or directly expose in the
|
||||
* noop-sandbox case) buffers into the sandbox that are automatically freed
|
||||
* when the TransferBuffer is out of scope. NOTE: The sandbox lifetime must
|
||||
* outlive all of its TransferBuffers.
|
||||
* noop-sandbox case) buffers into the expat sandbox (and automatically
|
||||
* when out of scope).
|
||||
*/
|
||||
template <typename T>
|
||||
class MOZ_STACK_CLASS TransferBuffer {
|
||||
public:
|
||||
TransferBuffer() = delete;
|
||||
TransferBuffer(rlbox_sandbox_expat* aSandbox, const T* aBuf,
|
||||
const size_t aLen)
|
||||
: mSandbox(aSandbox), mCopied(false), mBuf(nullptr) {
|
||||
if (aBuf) {
|
||||
mBuf = rlbox::copy_memory_or_grant_access(
|
||||
*mSandbox, aBuf, aLen * sizeof(T), false, mCopied);
|
||||
}
|
||||
};
|
||||
~TransferBuffer() {
|
||||
if (mCopied) {
|
||||
mSandbox->free_in_sandbox(mBuf);
|
||||
}
|
||||
};
|
||||
tainted_expat<const T*> operator*() const { return mBuf; };
|
||||
|
||||
private:
|
||||
rlbox_sandbox_expat* mSandbox;
|
||||
bool mCopied;
|
||||
tainted_expat<const T*> mBuf;
|
||||
};
|
||||
using TransferBuffer =
|
||||
mozilla::RLBoxTransferBufferToSandbox<T, rlbox_expat_sandbox_type>;
|
||||
|
||||
/*************************** END RLBOX HELPERS ******************************/
|
||||
|
||||
|
|
|
@ -75,3 +75,8 @@ if CONFIG["MOZ_WASM_SANDBOXING_EXPAT"]:
|
|||
for k, v in expat_defines:
|
||||
WASM_DEFINES[k] = v
|
||||
LOCAL_INCLUDES += ["/parser/expat/lib/"]
|
||||
|
||||
if CONFIG["MOZ_WASM_SANDBOXING_WOFF2"]:
|
||||
include("/modules/woff2/sources.mozbuild")
|
||||
WASM_SOURCES += ["/modules/woff2/" + s for s in woff2_sources]
|
||||
LOCAL_INCLUDES += ["/modules/woff2/include"]
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/* -*- Mode: C++; tab-width: 20; 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 SECURITY_RLBOX_UTILS_H_
|
||||
#define SECURITY_RLBOX_UTILS_H_
|
||||
|
||||
#include "mozilla/rlbox/rlbox_types.hpp"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/* The RLBoxTransferBufferToSandbox class is used to copy (or directly expose in
|
||||
* the noop-sandbox case) buffers into the sandbox that are automatically freed
|
||||
* when the RLBoxTransferBufferToSandbox is out of scope. NOTE: The sandbox
|
||||
* lifetime must outlive all of its RLBoxTransferBufferToSandbox.
|
||||
*/
|
||||
template <typename T, typename S>
|
||||
class MOZ_STACK_CLASS RLBoxTransferBufferToSandbox {
|
||||
public:
|
||||
RLBoxTransferBufferToSandbox() = delete;
|
||||
RLBoxTransferBufferToSandbox(rlbox::rlbox_sandbox<S>* aSandbox, const T* aBuf,
|
||||
const size_t aLen)
|
||||
: mSandbox(aSandbox), mCopied(false), mBuf(nullptr) {
|
||||
if (aBuf) {
|
||||
mBuf = rlbox::copy_memory_or_grant_access(
|
||||
*mSandbox, aBuf, aLen * sizeof(T), false, mCopied);
|
||||
}
|
||||
};
|
||||
~RLBoxTransferBufferToSandbox() {
|
||||
if (mCopied) {
|
||||
mSandbox->free_in_sandbox(mBuf);
|
||||
}
|
||||
};
|
||||
rlbox::tainted<const T*, S> operator*() const { return mBuf; };
|
||||
|
||||
private:
|
||||
rlbox::rlbox_sandbox<S>* mSandbox;
|
||||
bool mCopied;
|
||||
rlbox::tainted<const T*, S> mBuf;
|
||||
};
|
||||
|
||||
/* The RLBoxAllocateInSandbox class is used to allocate data int sandbox that is
|
||||
* automatically freed when the RLBoxAllocateInSandbox is out of scope. NOTE:
|
||||
* The sandbox lifetime must outlive all of its RLBoxAllocateInSandbox'ations.
|
||||
*/
|
||||
template <typename T, typename S>
|
||||
class MOZ_STACK_CLASS RLBoxAllocateInSandbox {
|
||||
public:
|
||||
RLBoxAllocateInSandbox() = delete;
|
||||
explicit RLBoxAllocateInSandbox(rlbox::rlbox_sandbox<S>* aSandbox)
|
||||
: mSandbox(aSandbox) {
|
||||
mPtr = mSandbox->template malloc_in_sandbox<T>();
|
||||
};
|
||||
~RLBoxAllocateInSandbox() {
|
||||
if (mPtr) {
|
||||
mSandbox->free_in_sandbox(mPtr);
|
||||
}
|
||||
};
|
||||
rlbox::tainted<T*, S> get() const { return mPtr; };
|
||||
|
||||
private:
|
||||
rlbox::rlbox_sandbox<S>* mSandbox;
|
||||
rlbox::tainted<T*, S> mPtr;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
|
@ -131,6 +131,7 @@ EXPORTS.mozilla += [
|
|||
"NSPRLogModulesParser.h",
|
||||
"OwningNonNull.h",
|
||||
"RLBoxSandboxPool.h",
|
||||
"RLBoxUtils.h",
|
||||
"ShutdownPhase.h",
|
||||
"SizeOfState.h",
|
||||
"StaticLocalPtr.h",
|
||||
|
|
Загрузка…
Ссылка в новой задаче