зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1639563 - sanitize WR fonts. r=jrmuizel
Differential Revision: https://phabricator.services.mozilla.com/D76360
This commit is contained in:
Родитель
96e684e365
Коммит
e97b3d4035
|
@ -244,10 +244,10 @@ struct TableRecord {
|
|||
CFDataRef data;
|
||||
};
|
||||
|
||||
static int maxPow2LessThan(int a) {
|
||||
static int maxPow2LessThanEqual(int a) {
|
||||
int x = 1;
|
||||
int shift = 0;
|
||||
while ((x << (shift + 1)) < a) {
|
||||
while ((x << (shift + 1)) <= a) {
|
||||
shift++;
|
||||
}
|
||||
return shift;
|
||||
|
@ -332,10 +332,10 @@ bool UnscaledFontMac::GetFontFileData(FontFileDataOutput aDataCallback,
|
|||
buf.writeElement(CFSwapInt32HostToBig(0x00010000));
|
||||
}
|
||||
buf.writeElement(CFSwapInt16HostToBig(count));
|
||||
buf.writeElement(CFSwapInt16HostToBig((1 << maxPow2LessThan(count)) * 16));
|
||||
buf.writeElement(CFSwapInt16HostToBig(maxPow2LessThan(count)));
|
||||
buf.writeElement(
|
||||
CFSwapInt16HostToBig(count * 16 - ((1 << maxPow2LessThan(count)) * 16)));
|
||||
int maxPow2Count = maxPow2LessThanEqual(count);
|
||||
buf.writeElement(CFSwapInt16HostToBig((1 << maxPow2Count) * 16));
|
||||
buf.writeElement(CFSwapInt16HostToBig(maxPow2Count));
|
||||
buf.writeElement(CFSwapInt16HostToBig((count - (1 << maxPow2Count)) * 16));
|
||||
|
||||
// write table record entries
|
||||
for (CFIndex i = 0; i < count; i++) {
|
||||
|
|
|
@ -230,12 +230,12 @@ bool ShmSegmentsReader::Read(const layers::OffsetRange& aRange,
|
|||
size_t initialLength = aInto.Length();
|
||||
|
||||
size_t srcCursor = aRange.start();
|
||||
int remainingBytesToCopy = aRange.length();
|
||||
size_t remainingBytesToCopy = aRange.length();
|
||||
while (remainingBytesToCopy > 0) {
|
||||
const size_t shm_idx = srcCursor / mChunkSize;
|
||||
const size_t ptrOffset = srcCursor % mChunkSize;
|
||||
const size_t copyRange =
|
||||
std::min<int>(remainingBytesToCopy, mChunkSize - ptrOffset);
|
||||
std::min(remainingBytesToCopy, mChunkSize - ptrOffset);
|
||||
uint8_t* srcPtr =
|
||||
RefCountedShm::GetBytes(mSmallAllocs[shm_idx]) + ptrOffset;
|
||||
|
||||
|
@ -248,6 +248,50 @@ bool ShmSegmentsReader::Read(const layers::OffsetRange& aRange,
|
|||
return aInto.Length() - initialLength == aRange.length();
|
||||
}
|
||||
|
||||
Maybe<Range<uint8_t>> ShmSegmentsReader::GetReadPointerLarge(
|
||||
const layers::OffsetRange& aRange) {
|
||||
// source = zero is for small allocs.
|
||||
MOZ_RELEASE_ASSERT(aRange.source() != 0);
|
||||
if (aRange.source() > mLargeAllocs.Length()) {
|
||||
return Nothing();
|
||||
}
|
||||
size_t id = aRange.source() - 1;
|
||||
const ipc::Shmem& shm = mLargeAllocs[id];
|
||||
if (shm.Size<uint8_t>() < aRange.length()) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
uint8_t* srcPtr = shm.get<uint8_t>();
|
||||
return Some(Range<uint8_t>(srcPtr, aRange.length()));
|
||||
}
|
||||
|
||||
Maybe<Range<uint8_t>> ShmSegmentsReader::GetReadPointer(
|
||||
const layers::OffsetRange& aRange) {
|
||||
if (aRange.length() == 0) {
|
||||
return Some(Range<uint8_t>());
|
||||
}
|
||||
|
||||
if (aRange.source() != 0) {
|
||||
return GetReadPointerLarge(aRange);
|
||||
}
|
||||
|
||||
if (mChunkSize == 0 ||
|
||||
aRange.start() + aRange.length() > mChunkSize * mSmallAllocs.Length()) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
size_t srcCursor = aRange.start();
|
||||
size_t remainingBytesToCopy = aRange.length();
|
||||
const size_t shm_idx = srcCursor / mChunkSize;
|
||||
const size_t ptrOffset = srcCursor % mChunkSize;
|
||||
// Return nothing if we can't return a pointer to the full range
|
||||
if (mChunkSize - ptrOffset < remainingBytesToCopy) {
|
||||
return Nothing();
|
||||
}
|
||||
uint8_t* srcPtr = RefCountedShm::GetBytes(mSmallAllocs[shm_idx]) + ptrOffset;
|
||||
return Some(Range<uint8_t>(srcPtr, remainingBytesToCopy));
|
||||
}
|
||||
|
||||
IpcResourceUpdateQueue::IpcResourceUpdateQueue(
|
||||
layers::WebRenderBridgeChild* aAllocator, size_t aChunkSize)
|
||||
: mWriter(aAllocator, aChunkSize) {}
|
||||
|
|
|
@ -71,9 +71,34 @@ class ShmSegmentsReader {
|
|||
|
||||
bool Read(const layers::OffsetRange& aRange, wr::Vec<uint8_t>& aInto);
|
||||
|
||||
// Get a read pointer, if possible, directly into the shm. If the range has
|
||||
// been broken up into multiple chunks that can't be represented by a single
|
||||
// range, nothing will be returned to indicate failure.
|
||||
Maybe<Range<uint8_t>> GetReadPointer(const layers::OffsetRange& aRange);
|
||||
|
||||
// Get a read pointer, if possible, directly into the shm. Otherwise, copy
|
||||
// it into the Vec and return a pointer to that contiguous memory instead.
|
||||
// If all fails, return nothing.
|
||||
Maybe<Range<uint8_t>> GetReadPointerOrCopy(const layers::OffsetRange& aRange,
|
||||
wr::Vec<uint8_t>& aInto) {
|
||||
if (Maybe<Range<uint8_t>> ptr = GetReadPointer(aRange)) {
|
||||
return ptr;
|
||||
} else {
|
||||
size_t initialLength = aInto.Length();
|
||||
if (Read(aRange, aInto)) {
|
||||
return Some(Range<uint8_t>(aInto.Data() + initialLength,
|
||||
aInto.Length() - initialLength));
|
||||
} else {
|
||||
return Nothing();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
bool ReadLarge(const layers::OffsetRange& aRange, wr::Vec<uint8_t>& aInto);
|
||||
|
||||
Maybe<Range<uint8_t>> GetReadPointerLarge(const layers::OffsetRange& aRange);
|
||||
|
||||
const nsTArray<layers::RefCountedShmem>& mSmallAllocs;
|
||||
const nsTArray<mozilla::ipc::Shmem>& mLargeAllocs;
|
||||
size_t mChunkSize;
|
||||
|
@ -87,9 +112,8 @@ class IpcResourceUpdateQueue {
|
|||
// we use here. The RefCountedShmem type used to allocate the chunks keeps a
|
||||
// 16 bytes header in the buffer which we account for here as well. So we pick
|
||||
// 64k - 2 * 4k - 16 = 57328 bytes as the default alloc size.
|
||||
explicit IpcResourceUpdateQueue(
|
||||
layers::WebRenderBridgeChild* aAllocator,
|
||||
size_t aChunkSize = 57328);
|
||||
explicit IpcResourceUpdateQueue(layers::WebRenderBridgeChild* aAllocator,
|
||||
size_t aChunkSize = 57328);
|
||||
|
||||
IpcResourceUpdateQueue(IpcResourceUpdateQueue&& aOther) noexcept;
|
||||
IpcResourceUpdateQueue& operator=(IpcResourceUpdateQueue&& aOther) noexcept;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include "CompositableHost.h"
|
||||
#include "gfxEnv.h"
|
||||
#include "gfxEnv.h"
|
||||
#include "gfxOTSUtils.h"
|
||||
#include "GeckoProfiler.h"
|
||||
#include "GLContext.h"
|
||||
#include "GLContextProvider.h"
|
||||
|
@ -430,6 +430,48 @@ void WebRenderBridgeParent::Destroy() {
|
|||
ClearResources();
|
||||
}
|
||||
|
||||
struct WROTSAlloc {
|
||||
wr::Vec<uint8_t> mVec;
|
||||
|
||||
void* Grow(void* aPtr, size_t aLength) {
|
||||
if (aLength > mVec.Length()) {
|
||||
mVec.Reserve(aLength - mVec.Length());
|
||||
}
|
||||
return mVec.inner.data;
|
||||
}
|
||||
wr::Vec<uint8_t> ShrinkToFit(void* aPtr, size_t aLength) {
|
||||
wr::Vec<uint8_t> result(std::move(mVec));
|
||||
result.inner.length = aLength;
|
||||
return result;
|
||||
}
|
||||
void Free(void* aPtr) {}
|
||||
};
|
||||
|
||||
static bool ReadRawFont(const OpAddRawFont& aOp, wr::ShmSegmentsReader& aReader,
|
||||
wr::TransactionBuilder& aUpdates) {
|
||||
wr::Vec<uint8_t> sourceBytes;
|
||||
Maybe<Range<uint8_t>> ptr =
|
||||
aReader.GetReadPointerOrCopy(aOp.bytes(), sourceBytes);
|
||||
if (ptr.isNothing()) {
|
||||
return false;
|
||||
}
|
||||
Range<uint8_t>& source = ptr.ref();
|
||||
// Attempt to sanitize the font before passing it along for updating
|
||||
size_t lengthHint = gfxOTSContext::GuessSanitizedFontSize(
|
||||
source.begin().get(), source.length());
|
||||
if (!lengthHint) {
|
||||
return false;
|
||||
}
|
||||
gfxOTSExpandingMemoryStream<WROTSAlloc> output(lengthHint);
|
||||
gfxOTSContext otsContext;
|
||||
if (!otsContext.Process(&output, source.begin().get(), source.length())) {
|
||||
return false;
|
||||
}
|
||||
wr::Vec<uint8_t> bytes = output.forget();
|
||||
aUpdates.AddRawFont(aOp.key(), bytes, aOp.fontIndex());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebRenderBridgeParent::UpdateResources(
|
||||
const nsTArray<OpUpdateResource>& aResourceUpdates,
|
||||
const nsTArray<RefCountedShmem>& aSmallShmems,
|
||||
|
@ -529,12 +571,9 @@ bool WebRenderBridgeParent::UpdateResources(
|
|||
break;
|
||||
}
|
||||
case OpUpdateResource::TOpAddRawFont: {
|
||||
const auto& op = cmd.get_OpAddRawFont();
|
||||
wr::Vec<uint8_t> bytes;
|
||||
if (!reader.Read(op.bytes(), bytes)) {
|
||||
if (!ReadRawFont(cmd.get_OpAddRawFont(), reader, aUpdates)) {
|
||||
return false;
|
||||
}
|
||||
aUpdates.AddRawFont(op.key(), bytes, op.fontIndex());
|
||||
break;
|
||||
}
|
||||
case OpUpdateResource::TOpAddFontDescriptor: {
|
||||
|
|
|
@ -27,7 +27,8 @@ class gfxOTSExpandingMemoryStream : public ots::OTSStream {
|
|||
// limit output/expansion to 256MB by default
|
||||
enum { DEFAULT_LIMIT = 256 * 1024 * 1024 };
|
||||
|
||||
gfxOTSExpandingMemoryStream(size_t initial, size_t limit = DEFAULT_LIMIT)
|
||||
explicit gfxOTSExpandingMemoryStream(size_t initial,
|
||||
size_t limit = DEFAULT_LIMIT)
|
||||
: mLength(initial), mLimit(limit), mOff(0) {
|
||||
mPtr = mAlloc.Grow(nullptr, mLength);
|
||||
}
|
||||
|
|
|
@ -652,12 +652,18 @@ struct Vec<uint8_t> final {
|
|||
inner.length = 0;
|
||||
}
|
||||
|
||||
uint8_t* Data() { return inner.data; }
|
||||
|
||||
size_t Length() { return inner.length; }
|
||||
|
||||
Range<uint8_t> GetRange() { return Range<uint8_t>(Data(), Length()); }
|
||||
|
||||
void PushBytes(Range<uint8_t> aBytes) {
|
||||
wr_vec_u8_push_bytes(&inner, RangeToByteSlice(aBytes));
|
||||
}
|
||||
|
||||
void Reserve(size_t aLength) { wr_vec_u8_reserve(&inner, aLength); }
|
||||
|
||||
~Vec() {
|
||||
if (inner.data) {
|
||||
wr_vec_u8_free(inner);
|
||||
|
|
|
@ -269,11 +269,18 @@ impl WrVecU8 {
|
|||
w
|
||||
}
|
||||
|
||||
fn reserve(&mut self, len: usize) {
|
||||
let mut vec = self.flush_into_vec();
|
||||
vec.reserve(len);
|
||||
*self = Self::from_vec(vec);
|
||||
}
|
||||
|
||||
fn push_bytes(&mut self, bytes: &[u8]) {
|
||||
let mut vec = self.flush_into_vec();
|
||||
vec.extend_from_slice(bytes);
|
||||
*self = Self::from_vec(vec);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -281,6 +288,11 @@ pub extern "C" fn wr_vec_u8_push_bytes(v: &mut WrVecU8, bytes: ByteSlice) {
|
|||
v.push_bytes(bytes.as_slice());
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_vec_u8_reserve(v: &mut WrVecU8, len: usize) {
|
||||
v.reserve(len);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_vec_u8_free(v: WrVecU8) {
|
||||
v.to_vec();
|
||||
|
|
Загрузка…
Ссылка в новой задаче