зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 2 changesets (bug 1569369, bug 1566288) for build bustages at rlbox_sandbox.hpp. CLOSED TREE
Backed out changeset 75d775daa792 (bug 1569369) Backed out changeset 0bc20fd26ca0 (bug 1566288)
This commit is contained in:
Родитель
70751f8d1b
Коммит
858cf4323e
|
@ -172,8 +172,7 @@ inline bool isInIgnoredNamespaceForImplicitCtor(const Decl *Declaration) {
|
|||
Name == "dwarf2reader" || // dwarf2reader
|
||||
Name == "arm_ex_to_module" || // arm_ex_to_module
|
||||
Name == "testing" || // gtest
|
||||
Name == "Json" || // jsoncpp
|
||||
Name == "rlbox"; // rlbox
|
||||
Name == "Json"; // jsoncpp
|
||||
}
|
||||
|
||||
inline bool isInIgnoredNamespaceForImplicitConversion(const Decl *Declaration) {
|
||||
|
@ -185,8 +184,7 @@ inline bool isInIgnoredNamespaceForImplicitConversion(const Decl *Declaration) {
|
|||
return Name == "std" || // standard C++ lib
|
||||
Name == "__gnu_cxx" || // gnu C++ lib
|
||||
Name == "google_breakpad" || // breakpad
|
||||
Name == "testing" || // gtest
|
||||
Name == "rlbox"; // rlbox
|
||||
Name == "testing"; // gtest
|
||||
}
|
||||
|
||||
inline bool isIgnoredPathForImplicitConversion(const Decl *Declaration) {
|
||||
|
|
|
@ -8,7 +8,6 @@ external_dirs = []
|
|||
|
||||
DIRS += [
|
||||
'lgpllibs',
|
||||
'rlbox',
|
||||
'sqlite',
|
||||
]
|
||||
if not CONFIG['MOZ_SYSTEM_JPEG']:
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
# -*- 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/.
|
||||
|
||||
EXPORTS.mozilla.rlbox += [
|
||||
'/third_party/rlbox/include/rlbox.hpp',
|
||||
'/third_party/rlbox/include/rlbox_conversion.hpp',
|
||||
'/third_party/rlbox/include/rlbox_helpers.hpp',
|
||||
'/third_party/rlbox/include/rlbox_noop_sandbox.hpp',
|
||||
'/third_party/rlbox/include/rlbox_policy_types.hpp',
|
||||
'/third_party/rlbox/include/rlbox_range.hpp',
|
||||
'/third_party/rlbox/include/rlbox_sandbox.hpp',
|
||||
'/third_party/rlbox/include/rlbox_stdlib.hpp',
|
||||
'/third_party/rlbox/include/rlbox_stdlib_polyfill.hpp',
|
||||
'/third_party/rlbox/include/rlbox_struct_support.hpp',
|
||||
'/third_party/rlbox/include/rlbox_type_traits.hpp',
|
||||
'/third_party/rlbox/include/rlbox_types.hpp',
|
||||
'/third_party/rlbox/include/rlbox_unwrap.hpp',
|
||||
'/third_party/rlbox/include/rlbox_wrapper_traits.hpp',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
'rlbox_thread_locals.cpp'
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
|
@ -1,13 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#define RLBOX_SINGLE_THREADED_INVOCATIONS
|
||||
#define RLBOX_EMBEDDER_PROVIDES_TLS_STATIC_VARIABLES
|
||||
|
||||
#include "mozilla/rlbox/rlbox.hpp"
|
||||
|
||||
#include "mozilla/rlbox/rlbox_noop_sandbox.hpp"
|
||||
|
||||
RLBOX_NOOP_SANDBOX_STATIC_VARIABLES();
|
|
@ -1,67 +0,0 @@
|
|||
// -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
// vim: set ts=2 et sw=2 tw=80:
|
||||
// This Source Code is subject to the terms of the Mozilla Public License
|
||||
// version 2.0 (the "License"). You can obtain a copy of the License at
|
||||
// http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef GraphiteStructsForRLBox_h__
|
||||
#define GraphiteStructsForRLBox_h__
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
|
||||
#elif defined(__GNUC__) || defined(__GNUG__)
|
||||
// Can't turn off the variadic macro warning emitted from -pedantic
|
||||
# pragma GCC system_header
|
||||
#elif defined(_MSC_VER)
|
||||
// Doesn't seem to emit the warning
|
||||
#else
|
||||
// Don't know the compiler... just let it go through
|
||||
#endif
|
||||
|
||||
#define sandbox_fields_reflection_graphite_class_gr_font_ops(f, g, ...) \
|
||||
f(size_t, size, FIELD_NORMAL, ##__VA_ARGS__) g() \
|
||||
f(float (*)(const void*, unsigned short), glyph_advance_x, FIELD_NORMAL, ##__VA_ARGS__) g() \
|
||||
f(float (*)(const void*, unsigned short), glyph_advance_y, FIELD_NORMAL, ##__VA_ARGS__) g()
|
||||
|
||||
#define sandbox_fields_reflection_graphite_class_gr_face_ops(f, g, ...) \
|
||||
f(size_t, size, FIELD_NORMAL, ##__VA_ARGS__) g() \
|
||||
f(const void* (*)(const void*, unsigned int, size_t*), get_table, FIELD_NORMAL, ##__VA_ARGS__) g() \
|
||||
f(void (*)(const void*, const void*), release_table, FIELD_NORMAL, ##__VA_ARGS__) g()
|
||||
|
||||
#define sandbox_fields_reflection_graphite_class_gr_glyph_to_char_cluster(f, g, ...) \
|
||||
f(unsigned int, baseChar, FIELD_NORMAL, ##__VA_ARGS__) g() \
|
||||
f(unsigned int, baseGlyph, FIELD_NORMAL, ##__VA_ARGS__) g() \
|
||||
f(unsigned int, nChars, FIELD_NORMAL, ##__VA_ARGS__) g() \
|
||||
f(unsigned int, nGlyphs, FIELD_NORMAL, ##__VA_ARGS__) g()
|
||||
|
||||
#define sandbox_fields_reflection_graphite_class_gr_glyph_to_char_association(f, g, ...) \
|
||||
f(gr_glyph_to_char_cluster*, clusters, FIELD_NORMAL, ##__VA_ARGS__) g() \
|
||||
f(unsigned short*, gids, FIELD_NORMAL, ##__VA_ARGS__) g() \
|
||||
f(float*, xLocs, FIELD_NORMAL, ##__VA_ARGS__) g() \
|
||||
f(float*, yLocs, FIELD_NORMAL, ##__VA_ARGS__) g() \
|
||||
f(unsigned int, cIndex, FIELD_NORMAL, ##__VA_ARGS__) g()
|
||||
|
||||
#define sandbox_fields_reflection_graphite_class_gr_faceinfo(f, g, ...) \
|
||||
f(short, extra_ascent, FIELD_NORMAL, ##__VA_ARGS__) g() \
|
||||
f(short, extra_descent, FIELD_NORMAL, ##__VA_ARGS__) g() \
|
||||
f(short, upem, FIELD_NORMAL, ##__VA_ARGS__) g() \
|
||||
f(gr_faceinfo::gr_space_contextuals, space_contextuals, FIELD_NORMAL, ##__VA_ARGS__) g() \
|
||||
f(unsigned int, has_bidi_pass, FIELD_NORMAL, ##__VA_ARGS__) g()
|
||||
// Remaining bitfields skipped, as bitfields are not fully supported
|
||||
|
||||
#define sandbox_fields_reflection_graphite_allClasses(f, ...) \
|
||||
f(gr_font_ops, graphite, ##__VA_ARGS__) \
|
||||
f(gr_face_ops, graphite, ##__VA_ARGS__) \
|
||||
f(gr_glyph_to_char_cluster, graphite, ##__VA_ARGS__) \
|
||||
f(gr_glyph_to_char_association, graphite, ##__VA_ARGS__) \
|
||||
f(gr_faceinfo, graphite, ##__VA_ARGS__)
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__) || defined(__GNUG__)
|
||||
#elif defined(_MSC_VER)
|
||||
#else
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -7,7 +7,6 @@
|
|||
# This should contain all of the _PUBLIC_HEADERS from files.mk
|
||||
EXPORTS.graphite2 += [
|
||||
'../geckoextra/include/GraphiteExtra.h',
|
||||
'../geckoextra/include/GraphiteStructsForRLBox.h',
|
||||
'../include/graphite2/Font.h',
|
||||
'../include/graphite2/Log.h',
|
||||
'../include/graphite2/Segment.h',
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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 THEBES_RLBOX
|
||||
#define THEBES_RLBOX
|
||||
|
||||
#include "ThebesRLBoxTypes.h"
|
||||
|
||||
// RLBox uses c++17's shared_locks by default, even for the noop_sandbox
|
||||
// However c++17 shared_lock is not supported on macOS 10.9 to 10.11
|
||||
// Thus we use Firefox's shared lock implementation
|
||||
// This can be removed if macOS 10.9 to 10.11 support is dropped
|
||||
#include "mozilla/RWLock.h"
|
||||
namespace rlbox {
|
||||
struct rlbox_shared_lock {
|
||||
mozilla::RWLock rwlock;
|
||||
rlbox_shared_lock() : rwlock("rlbox") {}
|
||||
};
|
||||
} // namespace rlbox
|
||||
#define RLBOX_USE_CUSTOM_SHARED_LOCK
|
||||
#define RLBOX_SHARED_LOCK(name) rlbox::rlbox_shared_lock name
|
||||
#define RLBOX_ACQUIRE_SHARED_GUARD(name, ...) \
|
||||
mozilla::AutoReadLock name((__VA_ARGS__).rwlock)
|
||||
#define RLBOX_ACQUIRE_UNIQUE_GUARD(name, ...) \
|
||||
mozilla::AutoWriteLock name((__VA_ARGS__).rwlock)
|
||||
|
||||
#define RLBOX_SINGLE_THREADED_INVOCATIONS
|
||||
|
||||
#define RLBOX_USE_STATIC_CALLS() rlbox_noop_sandbox_lookup_symbol
|
||||
|
||||
#define RLBOX_EMBEDDER_PROVIDES_TLS_STATIC_VARIABLES
|
||||
|
||||
#include "mozilla/rlbox/rlbox.hpp"
|
||||
#include "mozilla/rlbox/rlbox_noop_sandbox.hpp"
|
||||
|
||||
// Struct info needed for rlbox_load_structs_from_library
|
||||
#include "graphite2/Font.h"
|
||||
#include "graphite2/GraphiteExtra.h"
|
||||
#include "graphite2/Segment.h"
|
||||
|
||||
#include "graphite2/GraphiteStructsForRLBox.h"
|
||||
rlbox_load_structs_from_library(graphite);
|
||||
|
||||
#endif
|
|
@ -1,23 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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 THEBES_RLBOX_TYPES
|
||||
#define THEBES_RLBOX_TYPES
|
||||
|
||||
#include "mozilla/rlbox/rlbox_types.hpp"
|
||||
|
||||
using rlbox_gr_sandbox_type = rlbox::rlbox_noop_sandbox;
|
||||
using rlbox_sandbox_gr = rlbox::rlbox_sandbox<rlbox_gr_sandbox_type>;
|
||||
template <typename T>
|
||||
using sandbox_callback_gr = rlbox::sandbox_callback<T, rlbox_gr_sandbox_type>;
|
||||
template <typename T>
|
||||
using tainted_gr = rlbox::tainted<T, rlbox_gr_sandbox_type>;
|
||||
template <typename T>
|
||||
using tainted_opaque_gr = rlbox::tainted_opaque<T, rlbox_gr_sandbox_type>;
|
||||
template <typename T>
|
||||
using tainted_volatile_gr = rlbox::tainted_volatile<T, rlbox_gr_sandbox_type>;
|
||||
using rlbox::tainted_boolean_hint;
|
||||
|
||||
#endif
|
|
@ -45,8 +45,6 @@
|
|||
#include "gfx2DGlue.h"
|
||||
#include "TextDrawTarget.h"
|
||||
|
||||
#include "ThebesRLBox.h"
|
||||
|
||||
#include "GreekCasing.h"
|
||||
|
||||
#include "cairo.h"
|
||||
|
@ -1240,7 +1238,7 @@ bool gfxFont::HasSubstitutionRulesWithSpaceLookups(Script aRunScript) {
|
|||
return false;
|
||||
}
|
||||
|
||||
tainted_boolean_hint gfxFont::SpaceMayParticipateInShaping(Script aRunScript) {
|
||||
bool gfxFont::SpaceMayParticipateInShaping(Script aRunScript) {
|
||||
// avoid checking fonts known not to include default space-dependent features
|
||||
if (MOZ_UNLIKELY(mFontEntry->mSkipDefaultFeatureSpaceCheck)) {
|
||||
if (!mKerningSet && mStyle.featureSettings.IsEmpty() &&
|
||||
|
@ -3020,16 +3018,7 @@ bool gfxFont::SplitAndInitTextRun(
|
|||
// fractions), need to shape without using the word cache which segments
|
||||
// textruns on space boundaries. Word cache can be used if the textrun
|
||||
// is short enough to fit in the word cache and it lacks spaces.
|
||||
tainted_boolean_hint t_canParticipate =
|
||||
SpaceMayParticipateInShaping(aRunScript);
|
||||
bool canParticipate = t_canParticipate.unverified_safe_because(
|
||||
"We need to ensure that this function operates safely independent of "
|
||||
"t_canParticipate. The worst that can happen here is that the decision "
|
||||
"to use the cache is incorrectly made, resulting in a bad "
|
||||
"rendering/slowness. However, this would not compromise the memory "
|
||||
"safety of Firefox in any way, and can thus be permitted");
|
||||
|
||||
if (canParticipate) {
|
||||
if (SpaceMayParticipateInShaping(aRunScript)) {
|
||||
if (aRunLength > wordCacheCharLimit || HasSpaces(aString, aRunLength)) {
|
||||
TEXT_PERF_INCR(tp, wordCacheSpaceRules);
|
||||
return ShapeTextWithoutWordCache(aDrawTarget, aString, aRunStart,
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
#include "nsFontMetrics.h"
|
||||
#include "mozilla/ServoUtils.h"
|
||||
#include "TextDrawTarget.h"
|
||||
#include "ThebesRLBoxTypes.h"
|
||||
|
||||
typedef struct _cairo cairo_t;
|
||||
typedef struct _cairo_scaled_font cairo_scaled_font_t;
|
||||
|
@ -1931,10 +1930,7 @@ class gfxFont {
|
|||
bool HasSubstitutionRulesWithSpaceLookups(Script aRunScript);
|
||||
|
||||
// do spaces participate in shaping rules? if so, can't used word cache
|
||||
// Note that this function uses HasGraphiteSpaceContextuals, so it can only
|
||||
// return a "hint" to the correct answer. The calling code must ensure it
|
||||
// performs safe actions independent of the value returned.
|
||||
tainted_boolean_hint SpaceMayParticipateInShaping(Script aRunScript);
|
||||
bool SpaceMayParticipateInShaping(Script aRunScript);
|
||||
|
||||
// For 8-bit text, expand to 16-bit and then call the following method.
|
||||
bool ShapeText(DrawTarget* aContext, const uint8_t* aText,
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/ScopeExit.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StaticPrefs_layout.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
@ -41,8 +40,6 @@
|
|||
#include "harfbuzz/hb-ot.h"
|
||||
#include "graphite2/Font.h"
|
||||
|
||||
#include "ThebesRLBox.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace mozilla;
|
||||
|
@ -598,150 +595,54 @@ hb_face_t* gfxFontEntry::GetHBFace() {
|
|||
return hb_face_reference(mHBFace);
|
||||
}
|
||||
|
||||
struct gfxFontEntry::GrSandboxData {
|
||||
rlbox_sandbox_gr sandbox;
|
||||
sandbox_callback_gr<const void* (*)(const void*, unsigned int, size_t*)>
|
||||
grGetTableCallback;
|
||||
sandbox_callback_gr<void (*)(const void*, const void*)>
|
||||
grReleaseTableCallback;
|
||||
// Text Shapers register a callback to get glyph advances
|
||||
sandbox_callback_gr<float (*)(const void*, uint16_t)>
|
||||
grGetGlyphAdvanceCallback;
|
||||
|
||||
GrSandboxData() {
|
||||
sandbox.create_sandbox();
|
||||
grGetTableCallback = sandbox.register_callback(GrGetTable);
|
||||
grReleaseTableCallback = sandbox.register_callback(GrReleaseTable);
|
||||
grGetGlyphAdvanceCallback =
|
||||
sandbox.register_callback(gfxGraphiteShaper::GrGetAdvance);
|
||||
/*static*/ const void* gfxFontEntry::GrGetTable(const void* aAppFaceHandle,
|
||||
unsigned int aName,
|
||||
size_t* aLen) {
|
||||
gfxFontEntry* fontEntry =
|
||||
static_cast<gfxFontEntry*>(const_cast<void*>(aAppFaceHandle));
|
||||
hb_blob_t* blob = fontEntry->GetFontTable(aName);
|
||||
if (blob) {
|
||||
unsigned int blobLength;
|
||||
const void* tableData = hb_blob_get_data(blob, &blobLength);
|
||||
fontEntry->mGrTableMap->Put(tableData, blob);
|
||||
*aLen = blobLength;
|
||||
return tableData;
|
||||
}
|
||||
|
||||
~GrSandboxData() {
|
||||
grGetTableCallback.unregister();
|
||||
grReleaseTableCallback.unregister();
|
||||
grGetGlyphAdvanceCallback.unregister();
|
||||
sandbox.destroy_sandbox();
|
||||
}
|
||||
};
|
||||
|
||||
static thread_local gfxFontEntry* tl_grGetFontTableCallbackData = nullptr;
|
||||
|
||||
/*static*/
|
||||
tainted_opaque_gr<const void*> gfxFontEntry::GrGetTable(
|
||||
rlbox_sandbox_gr& sandbox,
|
||||
tainted_opaque_gr<const void*> /* aAppFaceHandle */,
|
||||
tainted_opaque_gr<unsigned int> aName, tainted_opaque_gr<size_t*> aLen) {
|
||||
gfxFontEntry* fontEntry = tl_grGetFontTableCallbackData;
|
||||
tainted_gr<size_t*> t_aLen = rlbox::from_opaque(aLen);
|
||||
*t_aLen = 0;
|
||||
tainted_gr<const void*> ret = nullptr;
|
||||
|
||||
if (fontEntry) {
|
||||
unsigned int fontTableKey =
|
||||
rlbox::from_opaque(aName).unverified_safe_because(
|
||||
"This is only being used to index into a hashmap, which is robust "
|
||||
"for any value. No checks needed.");
|
||||
hb_blob_t* blob = fontEntry->GetFontTable(fontTableKey);
|
||||
|
||||
if (blob) {
|
||||
unsigned int blobLength;
|
||||
const void* tableData = hb_blob_get_data(blob, &blobLength);
|
||||
// tableData is read-only data shared with the sandbox.
|
||||
// Making a copy in sandbox memory
|
||||
tainted_gr<void*> t_tableData = rlbox::sandbox_reinterpret_cast<void*>(
|
||||
sandbox.malloc_in_sandbox<char>(blobLength));
|
||||
if (t_tableData) {
|
||||
rlbox::memcpy(sandbox, t_tableData, tableData, blobLength);
|
||||
*t_aLen = blobLength;
|
||||
ret = rlbox::sandbox_const_cast<const void*>(t_tableData);
|
||||
}
|
||||
hb_blob_destroy(blob);
|
||||
}
|
||||
}
|
||||
|
||||
return ret.to_opaque();
|
||||
*aLen = 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*static*/
|
||||
void gfxFontEntry::GrReleaseTable(
|
||||
rlbox_sandbox_gr& sandbox,
|
||||
tainted_opaque_gr<const void*> /* aAppFaceHandle */,
|
||||
tainted_opaque_gr<const void*> aTableBuffer) {
|
||||
sandbox.free_in_sandbox(rlbox::from_opaque(aTableBuffer));
|
||||
void gfxFontEntry::GrReleaseTable(const void* aAppFaceHandle,
|
||||
const void* aTableBuffer) {
|
||||
gfxFontEntry* fontEntry =
|
||||
static_cast<gfxFontEntry*>(const_cast<void*>(aAppFaceHandle));
|
||||
void* value;
|
||||
if (fontEntry->mGrTableMap->Remove(aTableBuffer, &value)) {
|
||||
hb_blob_destroy(static_cast<hb_blob_t*>(value));
|
||||
}
|
||||
}
|
||||
|
||||
rlbox_sandbox_gr* gfxFontEntry::GetGrSandbox() {
|
||||
MOZ_ASSERT(mSandboxData != nullptr);
|
||||
return &mSandboxData->sandbox;
|
||||
}
|
||||
|
||||
sandbox_callback_gr<float (*)(const void*, uint16_t)>*
|
||||
gfxFontEntry::GetGrSandboxAdvanceCallbackHandle() {
|
||||
MOZ_ASSERT(mSandboxData != nullptr);
|
||||
return &mSandboxData->grGetGlyphAdvanceCallback;
|
||||
}
|
||||
|
||||
tainted_opaque_gr<gr_face*> gfxFontEntry::GetGrFace() {
|
||||
gr_face* gfxFontEntry::GetGrFace() {
|
||||
if (!mGrFaceInitialized) {
|
||||
// When possible, the below code will use WASM as a sandboxing mechanism.
|
||||
// At this time the wasm sandbox does not support threads.
|
||||
// If Thebes is updated to make callst to the sandbox on multiple threaads,
|
||||
// we need to make sure the underlying sandbox supports threading.
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
mSandboxData = new GrSandboxData();
|
||||
|
||||
auto p_faceOps = mSandboxData->sandbox.malloc_in_sandbox<gr_face_ops>();
|
||||
if (!p_faceOps) {
|
||||
MOZ_CRASH("Graphite sandbox memory allocation failed");
|
||||
}
|
||||
auto cleanup = MakeScopeExit(
|
||||
[&] { mSandboxData->sandbox.free_in_sandbox(p_faceOps); });
|
||||
p_faceOps->size = sizeof(*p_faceOps);
|
||||
p_faceOps->get_table = mSandboxData->grGetTableCallback;
|
||||
p_faceOps->release_table = mSandboxData->grReleaseTableCallback;
|
||||
|
||||
tl_grGetFontTableCallbackData = this;
|
||||
auto face = sandbox_invoke(
|
||||
mSandboxData->sandbox, gr_make_face_with_ops,
|
||||
// For security, we do not pass the callback data to this arg, and use
|
||||
// a TLS var instead. However, gr_make_face_with_ops expects this to
|
||||
// be a non null ptr. Therefore, we should pass some dummy non null
|
||||
// pointer which will be passed to callbacks, but never used. Let's just
|
||||
// pass p_faceOps again, as this is a non-null tainted pointer.
|
||||
p_faceOps /* appFaceHandle */, p_faceOps, gr_face_default);
|
||||
tl_grGetFontTableCallbackData = nullptr;
|
||||
mGrFace = face.to_opaque();
|
||||
gr_face_ops faceOps = {sizeof(gr_face_ops), GrGetTable, GrReleaseTable};
|
||||
mGrTableMap = new nsDataHashtable<nsPtrHashKey<const void>, void*>;
|
||||
mGrFace = gr_make_face_with_ops(this, &faceOps, gr_face_default);
|
||||
mGrFaceInitialized = true;
|
||||
}
|
||||
++mGrFaceRefCnt;
|
||||
return mGrFace;
|
||||
}
|
||||
|
||||
void gfxFontEntry::ReleaseGrFace(tainted_opaque_gr<gr_face*> aFace) {
|
||||
MOZ_ASSERT(
|
||||
(rlbox::from_opaque(aFace) == rlbox::from_opaque(mGrFace))
|
||||
.unverified_safe_because(
|
||||
"This is safe as the only thing we are doing is comparing "
|
||||
"addresses of two tainted pointers. Furthermore this is used "
|
||||
"merely as a debugging aid in the debug builds. This function is "
|
||||
"called only from the trusted Firefox code rather than the "
|
||||
"untrusted libGraphite.")); // sanity-check
|
||||
void gfxFontEntry::ReleaseGrFace(gr_face* aFace) {
|
||||
MOZ_ASSERT(aFace == mGrFace); // sanity-check
|
||||
MOZ_ASSERT(mGrFaceRefCnt > 0);
|
||||
if (--mGrFaceRefCnt == 0) {
|
||||
auto t_mGrFace = rlbox::from_opaque(mGrFace);
|
||||
|
||||
tl_grGetFontTableCallbackData = this;
|
||||
sandbox_invoke(mSandboxData->sandbox, gr_face_destroy, t_mGrFace);
|
||||
tl_grGetFontTableCallbackData = nullptr;
|
||||
|
||||
t_mGrFace = nullptr;
|
||||
mGrFace = t_mGrFace.to_opaque();
|
||||
|
||||
delete mSandboxData;
|
||||
mSandboxData = nullptr;
|
||||
|
||||
gr_face_destroy(mGrFace);
|
||||
mGrFace = nullptr;
|
||||
mGrFaceInitialized = false;
|
||||
delete mGrTableMap;
|
||||
mGrTableMap = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -761,32 +662,18 @@ void gfxFontEntry::CheckForGraphiteTables() {
|
|||
mHasGraphiteTables = HasFontTable(TRUETYPE_TAG('S', 'i', 'l', 'f'));
|
||||
}
|
||||
|
||||
tainted_boolean_hint gfxFontEntry::HasGraphiteSpaceContextuals() {
|
||||
bool gfxFontEntry::HasGraphiteSpaceContextuals() {
|
||||
if (!mGraphiteSpaceContextualsInitialized) {
|
||||
auto face = GetGrFace();
|
||||
auto t_face = rlbox::from_opaque(face);
|
||||
if (t_face) {
|
||||
tainted_gr<const gr_faceinfo*> faceInfo =
|
||||
sandbox_invoke(mSandboxData->sandbox, gr_face_info, t_face, 0);
|
||||
// Comparison with a value in sandboxed memory returns a
|
||||
// tainted_boolean_hint, i.e. a "hint", since the value could be changed
|
||||
// maliciously at any moment.
|
||||
tainted_boolean_hint is_not_none =
|
||||
gr_face* face = GetGrFace();
|
||||
if (face) {
|
||||
const gr_faceinfo* faceInfo = gr_face_info(face, 0);
|
||||
mHasGraphiteSpaceContextuals =
|
||||
faceInfo->space_contextuals != gr_faceinfo::gr_space_none;
|
||||
mHasGraphiteSpaceContextuals = is_not_none.unverified_safe_because(
|
||||
"Note ideally mHasGraphiteSpaceContextuals would be "
|
||||
"tainted_boolean_hint, but RLBox does not yet support bitfields, so "
|
||||
"it is not wrapped. However, its value is only ever accessed through "
|
||||
"this function which returns a tainted_boolean_hint, so unwrapping "
|
||||
"temporarily is safe. We remove the wrapper now and re-add it "
|
||||
"below.");
|
||||
}
|
||||
ReleaseGrFace(face); // always balance GetGrFace, even if face is null
|
||||
mGraphiteSpaceContextualsInitialized = true;
|
||||
}
|
||||
|
||||
bool ret = mHasGraphiteSpaceContextuals;
|
||||
return tainted_boolean_hint(ret);
|
||||
return mHasGraphiteSpaceContextuals;
|
||||
}
|
||||
|
||||
#define FEATURE_SCRIPT_MASK 0x000000ff // script index replaces low byte of tag
|
||||
|
@ -948,11 +835,8 @@ bool gfxFontEntry::SupportsGraphiteFeature(uint32_t aFeatureTag) {
|
|||
return result;
|
||||
}
|
||||
|
||||
auto face = GetGrFace();
|
||||
auto t_face = rlbox::from_opaque(face);
|
||||
result = t_face ? sandbox_invoke(mSandboxData->sandbox, gr_face_find_fref,
|
||||
t_face, aFeatureTag) != nullptr
|
||||
: false;
|
||||
gr_face* face = GetGrFace();
|
||||
result = face ? gr_face_find_fref(face, aFeatureTag) != nullptr : false;
|
||||
ReleaseGrFace(face);
|
||||
|
||||
mSupportedFeatures->Put(scriptFeature, result);
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/WeakPtr.h"
|
||||
#include "ThebesRLBoxTypes.h"
|
||||
#include <math.h>
|
||||
|
||||
typedef struct gr_face gr_face;
|
||||
|
@ -338,30 +337,14 @@ class gfxFontEntry {
|
|||
hb_face_t* GetHBFace();
|
||||
void ForgetHBFace();
|
||||
|
||||
// Get the sandbox instance that graphite is running in.
|
||||
rlbox_sandbox_gr* GetGrSandbox();
|
||||
|
||||
// Register and get the callback handle for the glyph advance firefox callback
|
||||
// Since the sandbox instance is shared with multiple test shapers, callback
|
||||
// registration must be handled centrally to ensure multiple instances don't
|
||||
// register the same callback.
|
||||
sandbox_callback_gr<float (*)(const void*, uint16_t)>*
|
||||
GetGrSandboxAdvanceCallbackHandle();
|
||||
|
||||
// Get Graphite face corresponding to this font file.
|
||||
// Caller must call gfxFontEntry::ReleaseGrFace when finished with it.
|
||||
// Graphite is run in a sandbox
|
||||
tainted_opaque_gr<gr_face*> GetGrFace();
|
||||
void ReleaseGrFace(tainted_opaque_gr<gr_face*> aFace);
|
||||
gr_face* GetGrFace();
|
||||
void ReleaseGrFace(gr_face* aFace);
|
||||
|
||||
// Does the font have graphite contextuals that involve the space glyph
|
||||
// (and therefore we should bypass the word cache)?
|
||||
// Since this function inspects data from libGraphite stored in sandbox memory
|
||||
// it can only return a "hint" to the correct return value. This is because
|
||||
// a compromised libGraphite could change the sandbox memory maliciously at
|
||||
// any moment. The caller must ensure the calling code performs safe actions
|
||||
// independent of the value returned, to unwrap this return.
|
||||
tainted_boolean_hint HasGraphiteSpaceContextuals();
|
||||
bool HasGraphiteSpaceContextuals();
|
||||
|
||||
// Release any SVG-glyphs document this font may have loaded.
|
||||
void DisconnectSVG();
|
||||
|
@ -587,16 +570,15 @@ class gfxFontEntry {
|
|||
// Callback that the hb_face will use to tell us when it is being deleted.
|
||||
static void HBFaceDeletedCallback(void* aUserData);
|
||||
|
||||
// All libGraphite functionality is sandboxed in an rlbox sandbox. This
|
||||
// contains data for the sandbox instance.
|
||||
struct GrSandboxData;
|
||||
GrSandboxData* mSandboxData = nullptr;
|
||||
|
||||
// gr_face is -not- refcounted, so it will be owned directly by the font
|
||||
// entry, and we'll keep a count of how many references we've handed out;
|
||||
// each shaper is responsible to call ReleaseGrFace on its entry when
|
||||
// finished with it, so that we know when it can be deleted.
|
||||
tainted_opaque_gr<gr_face*> mGrFace;
|
||||
gr_face* mGrFace = nullptr;
|
||||
|
||||
// hashtable to map raw table data ptr back to its owning blob, for use by
|
||||
// graphite table-release callback
|
||||
nsDataHashtable<nsPtrHashKey<const void>, void*>* mGrTableMap = nullptr;
|
||||
|
||||
// For AAT font, a strong reference to the 'trak' table (if present).
|
||||
hb_blob_t* const kTrakTableUninitialized = (hb_blob_t*)(intptr_t(-1));
|
||||
|
@ -612,12 +594,10 @@ class gfxFontEntry {
|
|||
// number of current users of this entry's mGrFace
|
||||
nsrefcnt mGrFaceRefCnt = 0;
|
||||
|
||||
static tainted_opaque_gr<const void*> GrGetTable(
|
||||
rlbox_sandbox_gr& sandbox, tainted_opaque_gr<const void*> aAppFaceHandle,
|
||||
tainted_opaque_gr<unsigned int> aName, tainted_opaque_gr<size_t*> aLen);
|
||||
static void GrReleaseTable(rlbox_sandbox_gr& sandbox,
|
||||
tainted_opaque_gr<const void*> aAppFaceHandle,
|
||||
tainted_opaque_gr<const void*> aTableBuffer);
|
||||
static const void* GrGetTable(const void* aAppFaceHandle, unsigned int aName,
|
||||
size_t* aLen);
|
||||
static void GrReleaseTable(const void* aAppFaceHandle,
|
||||
const void* aTableBuffer);
|
||||
|
||||
// For memory reporting: size of user-font data belonging to this entry.
|
||||
// We record this in the font entry because the actual data block may be
|
||||
|
|
|
@ -15,10 +15,6 @@
|
|||
|
||||
#include "harfbuzz/hb.h"
|
||||
|
||||
#include "mozilla/ScopeExit.h"
|
||||
|
||||
#include "ThebesRLBox.h"
|
||||
|
||||
#define FloatToFixed(f) (65536 * (f))
|
||||
#define FixedToFloat(f) ((f) * (1.0 / 65536.0))
|
||||
// Right shifts of negative (signed) integers are undefined, as are overflows
|
||||
|
@ -27,14 +23,6 @@
|
|||
#define FixedToIntRound(f) \
|
||||
((f) > 0 ? ((32768 + (f)) >> 16) : -((32767 - (f)) >> 16))
|
||||
|
||||
#define CopyAndVerifyOrFail(t, cond, failed) \
|
||||
(t).copy_and_verify([&](auto val) { \
|
||||
if (!(cond)) { \
|
||||
*(failed) = true; \
|
||||
} \
|
||||
return val; \
|
||||
})
|
||||
|
||||
using namespace mozilla; // for AutoSwap_* types
|
||||
|
||||
/*
|
||||
|
@ -44,41 +32,23 @@ using namespace mozilla; // for AutoSwap_* types
|
|||
gfxGraphiteShaper::gfxGraphiteShaper(gfxFont* aFont)
|
||||
: gfxFontShaper(aFont),
|
||||
mGrFace(mFont->GetFontEntry()->GetGrFace()),
|
||||
mSandbox(mFont->GetFontEntry()->GetGrSandbox()),
|
||||
mCallback(mFont->GetFontEntry()->GetGrSandboxAdvanceCallbackHandle()),
|
||||
mGrFont(nullptr),
|
||||
mFallbackToSmallCaps(false) {
|
||||
mCallbackData.mFont = aFont;
|
||||
}
|
||||
|
||||
gfxGraphiteShaper::~gfxGraphiteShaper() {
|
||||
auto t_mGrFont = rlbox::from_opaque(mGrFont);
|
||||
if (t_mGrFont) {
|
||||
sandbox_invoke(*mSandbox, gr_font_destroy, t_mGrFont);
|
||||
if (mGrFont) {
|
||||
gr_font_destroy(mGrFont);
|
||||
}
|
||||
mFont->GetFontEntry()->ReleaseGrFace(mGrFace);
|
||||
}
|
||||
|
||||
/*static*/
|
||||
thread_local gfxGraphiteShaper::CallbackData*
|
||||
gfxGraphiteShaper::tl_GrGetAdvanceData = nullptr;
|
||||
|
||||
/*static*/
|
||||
tainted_opaque_gr<float> gfxGraphiteShaper::GrGetAdvance(
|
||||
rlbox_sandbox_gr& sandbox,
|
||||
tainted_opaque_gr<const void*> /* appFontHandle */,
|
||||
tainted_opaque_gr<uint16_t> t_glyphid) {
|
||||
CallbackData* cb = tl_GrGetAdvanceData;
|
||||
if (!cb) {
|
||||
// GrGetAdvance callback called unexpectedly. Just return safe value.
|
||||
tainted_gr<float> ret = 0;
|
||||
return ret.to_opaque();
|
||||
}
|
||||
auto glyphid = rlbox::from_opaque(t_glyphid).unverified_safe_because(
|
||||
"Here the only use of a glyphid is for lookup to get a width. "
|
||||
"Implementations of GetGlyphWidth in this code base use a hashtable "
|
||||
"which is robust to unknown keys. So no validation is required.");
|
||||
tainted_gr<float> ret = FixedToFloat(cb->mFont->GetGlyphWidth(glyphid));
|
||||
return ret.to_opaque();
|
||||
float gfxGraphiteShaper::GrGetAdvance(const void* appFontHandle,
|
||||
uint16_t glyphid) {
|
||||
const CallbackData* cb = static_cast<const CallbackData*>(appFontHandle);
|
||||
return FixedToFloat(cb->mFont->GetGlyphWidth(glyphid));
|
||||
}
|
||||
|
||||
static inline uint32_t MakeGraphiteLangTag(uint32_t aTag) {
|
||||
|
@ -93,19 +63,16 @@ static inline uint32_t MakeGraphiteLangTag(uint32_t aTag) {
|
|||
}
|
||||
|
||||
struct GrFontFeatures {
|
||||
tainted_gr<gr_face*> mFace;
|
||||
tainted_gr<gr_feature_val*> mFeatures;
|
||||
rlbox_sandbox_gr* mSandbox;
|
||||
gr_face* mFace;
|
||||
gr_feature_val* mFeatures;
|
||||
};
|
||||
|
||||
static void AddFeature(const uint32_t& aTag, uint32_t& aValue, void* aUserArg) {
|
||||
GrFontFeatures* f = static_cast<GrFontFeatures*>(aUserArg);
|
||||
|
||||
tainted_gr<const gr_feature_ref*> fref =
|
||||
sandbox_invoke(*(f->mSandbox), gr_face_find_fref, f->mFace, aTag);
|
||||
const gr_feature_ref* fref = gr_face_find_fref(f->mFace, aTag);
|
||||
if (fref) {
|
||||
sandbox_invoke(*(f->mSandbox), gr_fref_set_feature_value, fref, aValue,
|
||||
f->mFeatures);
|
||||
gr_fref_set_feature_value(fref, aValue, f->mFeatures);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,39 +101,24 @@ bool gfxGraphiteShaper::ShapeText(DrawTarget* aDrawTarget,
|
|||
bool aVertical, RoundingFlags aRounding,
|
||||
gfxShapedText* aShapedText) {
|
||||
const gfxFontStyle* style = mFont->GetStyle();
|
||||
auto t_mGrFace = rlbox::from_opaque(mGrFace);
|
||||
auto t_mGrFont = rlbox::from_opaque(mGrFont);
|
||||
|
||||
if (!t_mGrFont) {
|
||||
if (!t_mGrFace) {
|
||||
if (!mGrFont) {
|
||||
if (!mGrFace) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mFont->ProvidesGlyphWidths()) {
|
||||
auto p_ops = mSandbox->malloc_in_sandbox<gr_font_ops>();
|
||||
if (!p_ops) {
|
||||
return false;
|
||||
}
|
||||
auto clean_ops = MakeScopeExit([&] { mSandbox->free_in_sandbox(p_ops); });
|
||||
p_ops->size = sizeof(*p_ops);
|
||||
p_ops->glyph_advance_x = *mCallback;
|
||||
p_ops->glyph_advance_y = nullptr; // vertical text not yet implemented
|
||||
t_mGrFont = sandbox_invoke(
|
||||
*mSandbox, gr_make_font_with_ops, mFont->GetAdjustedSize(),
|
||||
// For security, we do not pass the callback data to this arg, and use
|
||||
// a TLS var instead. However, gr_make_font_with_ops expects this to
|
||||
// be a non null ptr, and changes its behavior if it isn't. Therefore,
|
||||
// we should pass some dummy non null pointer which will be passed to
|
||||
// the GrGetAdvance callback, but never used. Let's just pass p_ops
|
||||
// again, as this is a non-null tainted pointer.
|
||||
p_ops /* mCallbackData */, p_ops, t_mGrFace);
|
||||
gr_font_ops ops = {
|
||||
sizeof(gr_font_ops), &GrGetAdvance,
|
||||
nullptr // vertical text not yet implemented
|
||||
};
|
||||
mGrFont = gr_make_font_with_ops(mFont->GetAdjustedSize(), &mCallbackData,
|
||||
&ops, mGrFace);
|
||||
} else {
|
||||
t_mGrFont = sandbox_invoke(*mSandbox, gr_make_font,
|
||||
mFont->GetAdjustedSize(), t_mGrFace);
|
||||
mGrFont = gr_make_font(mFont->GetAdjustedSize(), mGrFace);
|
||||
}
|
||||
mGrFont = t_mGrFont.to_opaque();
|
||||
|
||||
if (!t_mGrFont) {
|
||||
if (!mGrFont) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -196,11 +148,10 @@ bool gfxGraphiteShaper::ShapeText(DrawTarget* aDrawTarget,
|
|||
style->language->ToUTF8String(langString);
|
||||
grLang = GetGraphiteTagForLang(langString);
|
||||
}
|
||||
tainted_gr<gr_feature_val*> grFeatures =
|
||||
sandbox_invoke(*mSandbox, gr_face_featureval_for_lang, t_mGrFace, grLang);
|
||||
gr_feature_val* grFeatures = gr_face_featureval_for_lang(mGrFace, grLang);
|
||||
|
||||
// insert any merged features into Graphite feature list
|
||||
GrFontFeatures f = {t_mGrFace, grFeatures, mSandbox};
|
||||
GrFontFeatures f = {mGrFace, grFeatures};
|
||||
MergeFontFeatures(style, mFont->GetFontEntry()->mFeatureSettings,
|
||||
aShapedText->DisableLigatures(),
|
||||
mFont->GetFontEntry()->FamilyName(), mFallbackToSmallCaps,
|
||||
|
@ -224,199 +175,99 @@ bool gfxGraphiteShaper::ShapeText(DrawTarget* aDrawTarget,
|
|||
size_t numChars = CountUnicodes(aText, aLength);
|
||||
gr_bidirtl grBidi = gr_bidirtl(
|
||||
aShapedText->IsRightToLeft() ? (gr_rtl | gr_nobidi) : gr_nobidi);
|
||||
gr_segment* seg = gr_make_seg(mGrFont, mGrFace, 0, grFeatures, gr_utf16,
|
||||
aText, numChars, grBidi);
|
||||
|
||||
tainted_gr<char16_t*> t_aText =
|
||||
mSandbox->malloc_in_sandbox<char16_t>(aLength);
|
||||
if (!t_aText) {
|
||||
return false;
|
||||
}
|
||||
auto clean_txt = MakeScopeExit([&] { mSandbox->free_in_sandbox(t_aText); });
|
||||
|
||||
rlbox::memcpy(*mSandbox, t_aText, aText, aLength * sizeof(char16_t));
|
||||
|
||||
tl_GrGetAdvanceData = &mCallbackData;
|
||||
auto clean_adv_data = MakeScopeExit([&] { tl_GrGetAdvanceData = nullptr; });
|
||||
|
||||
tainted_gr<gr_segment*> seg =
|
||||
sandbox_invoke(*mSandbox, gr_make_seg, mGrFont, t_mGrFace, 0, grFeatures,
|
||||
gr_utf16, t_aText, numChars, grBidi);
|
||||
|
||||
sandbox_invoke(*mSandbox, gr_featureval_destroy, grFeatures);
|
||||
gr_featureval_destroy(grFeatures);
|
||||
|
||||
if (!seg) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult rv =
|
||||
SetGlyphsFromSegment(aShapedText, aOffset, aLength, aText,
|
||||
t_aText.to_opaque(), seg.to_opaque(), aRounding);
|
||||
nsresult rv = SetGlyphsFromSegment(aShapedText, aOffset, aLength, aText, seg,
|
||||
aRounding);
|
||||
|
||||
sandbox_invoke(*mSandbox, gr_seg_destroy, seg);
|
||||
gr_seg_destroy(seg);
|
||||
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
nsresult gfxGraphiteShaper::SetGlyphsFromSegment(
|
||||
gfxShapedText* aShapedText, uint32_t aOffset, uint32_t aLength,
|
||||
const char16_t* aText, tainted_opaque_gr<char16_t*> t_aText,
|
||||
tainted_opaque_gr<gr_segment*> aSegment, RoundingFlags aRounding) {
|
||||
const char16_t* aText, gr_segment* aSegment, RoundingFlags aRounding) {
|
||||
typedef gfxShapedText::CompressedGlyph CompressedGlyph;
|
||||
|
||||
int32_t dev2appUnits = aShapedText->GetAppUnitsPerDevUnit();
|
||||
bool rtl = aShapedText->IsRightToLeft();
|
||||
|
||||
// identify clusters; graphite may have reordered/expanded/ligated glyphs.
|
||||
tainted_gr<gr_glyph_to_char_association*> data =
|
||||
sandbox_invoke(*mSandbox, gr_get_glyph_to_char_association, aSegment,
|
||||
aLength, rlbox::from_opaque(t_aText));
|
||||
gr_glyph_to_char_association* data =
|
||||
gr_get_glyph_to_char_association(aSegment, aLength, aText);
|
||||
|
||||
if (!data) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
tainted_gr<gr_glyph_to_char_cluster*> clusters = data->clusters;
|
||||
tainted_gr<uint16_t*> gids = data->gids;
|
||||
tainted_gr<float*> xLocs = data->xLocs;
|
||||
tainted_gr<float*> yLocs = data->yLocs;
|
||||
uint32_t cIndex = data->cIndex;
|
||||
gr_glyph_to_char_cluster* clusters = data->clusters;
|
||||
uint16_t* gids = data->gids;
|
||||
float* xLocs = data->xLocs;
|
||||
float* yLocs = data->yLocs;
|
||||
|
||||
CompressedGlyph* charGlyphs = aShapedText->GetCharacterGlyphs() + aOffset;
|
||||
|
||||
bool roundX = bool(aRounding & RoundingFlags::kRoundX);
|
||||
bool roundY = bool(aRounding & RoundingFlags::kRoundY);
|
||||
|
||||
bool failedVerify = false;
|
||||
|
||||
// cIndex is primarily used to index into the clusters array which has size
|
||||
// aLength below. As cIndex is not changing anymore, let's just verify it
|
||||
// and remove the tainted wrapper.
|
||||
uint32_t cIndex =
|
||||
CopyAndVerifyOrFail(data->cIndex, val < aLength, &failedVerify);
|
||||
if (failedVerify) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
// now put glyphs into the textrun, one cluster at a time
|
||||
for (uint32_t i = 0; i <= cIndex; ++i) {
|
||||
// We makes a local copy of "clusters[i]" which is of type
|
||||
// tainted_gr<gr_glyph_to_char_cluster> below. We do this intentionally
|
||||
// rather than taking a reference. Taking a reference with the code
|
||||
//
|
||||
// tainted_volatile_gr<gr_glyph_to_char_cluster>& c = clusters[i];
|
||||
//
|
||||
// produces a tainted_volatile which means the value can change at any
|
||||
// moment allowing for possible time-of-check-time-of-use vuln. We thus
|
||||
// make a local copy to simplify the verification.
|
||||
tainted_gr<gr_glyph_to_char_cluster> c = clusters[i];
|
||||
const gr_glyph_to_char_cluster& c = clusters[i];
|
||||
|
||||
tainted_gr<float> t_adv; // total advance of the cluster
|
||||
float adv; // total advance of the cluster
|
||||
if (rtl) {
|
||||
if (i == 0) {
|
||||
t_adv = sandbox_invoke(*mSandbox, gr_seg_advance_X, aSegment) -
|
||||
xLocs[c.baseGlyph];
|
||||
adv = gr_seg_advance_X(aSegment) - xLocs[c.baseGlyph];
|
||||
} else {
|
||||
t_adv = xLocs[clusters[i - 1].baseGlyph] - xLocs[c.baseGlyph];
|
||||
adv = xLocs[clusters[i - 1].baseGlyph] - xLocs[c.baseGlyph];
|
||||
}
|
||||
} else {
|
||||
if (i == cIndex) {
|
||||
t_adv = sandbox_invoke(*mSandbox, gr_seg_advance_X, aSegment) -
|
||||
xLocs[c.baseGlyph];
|
||||
adv = gr_seg_advance_X(aSegment) - xLocs[c.baseGlyph];
|
||||
} else {
|
||||
t_adv = xLocs[clusters[i + 1].baseGlyph] - xLocs[c.baseGlyph];
|
||||
adv = xLocs[clusters[i + 1].baseGlyph] - xLocs[c.baseGlyph];
|
||||
}
|
||||
}
|
||||
|
||||
float adv = t_adv.unverified_safe_because(
|
||||
"Per Bug 1569464 - this is the advance width of a glyph or cluster of "
|
||||
"glyphs. There are no a-priori limits on what that might be. Incorrect "
|
||||
"values will tend to result in bad layout or missing text, or bad "
|
||||
"nscoord values. But, these will not result in safety issues.");
|
||||
|
||||
// check unexpected offset - offs used to index into aText
|
||||
uint32_t offs =
|
||||
CopyAndVerifyOrFail(c.baseChar, val < aLength, &failedVerify);
|
||||
if (failedVerify) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
// Check for default-ignorable char that didn't get filtered, combined,
|
||||
// etc by the shaping process, and skip it.
|
||||
auto one_glyph = c.nGlyphs == static_cast<uint32_t>(1);
|
||||
auto one_char = c.nChars == static_cast<uint32_t>(1);
|
||||
|
||||
if ((one_glyph && one_char)
|
||||
.unverified_safe_because(
|
||||
"using this boolean check to decide whether to ignore a "
|
||||
"character or not. The worst that can happen is a bad "
|
||||
"rendering.")) {
|
||||
if (aShapedText->FilterIfIgnorable(aOffset + offs, aText[offs])) {
|
||||
continue;
|
||||
}
|
||||
uint32_t offs = c.baseChar;
|
||||
NS_ASSERTION(offs < aLength, "unexpected offset");
|
||||
if (c.nGlyphs == 1 && c.nChars == 1 &&
|
||||
aShapedText->FilterIfIgnorable(aOffset + offs, aText[offs])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t appAdvance = roundX ? NSToIntRound(adv) * dev2appUnits
|
||||
: NSToIntRound(adv * dev2appUnits);
|
||||
|
||||
const char gid_simple_value[] =
|
||||
"Per Bug 1569464 - these are glyph IDs that can range from 0 to the "
|
||||
"maximum glyph ID supported by the font. However, out-of-range values "
|
||||
"here should not lead to safety issues; they would simply result in "
|
||||
"blank rendering, although this depends on the platform back-end.";
|
||||
|
||||
// gids[c.baseGlyph] is checked and used below. Since this is a
|
||||
// tainted_volatile, which can change at any moment, we make a local copy
|
||||
// first to prevent a time-of-check-time-of-use vuln.
|
||||
uint16_t gid_of_base_glyph =
|
||||
gids[c.baseGlyph].unverified_safe_because(gid_simple_value);
|
||||
|
||||
const char fast_path[] =
|
||||
"Even if the number of glyphs set is an incorrect value, the else "
|
||||
"branch is a more general purpose algorithm which can handle other "
|
||||
"values of nGlyphs";
|
||||
|
||||
if (one_glyph.unverified_safe_because(fast_path) &&
|
||||
CompressedGlyph::IsSimpleGlyphID(gid_of_base_glyph) &&
|
||||
if (c.nGlyphs == 1 && CompressedGlyph::IsSimpleGlyphID(gids[c.baseGlyph]) &&
|
||||
CompressedGlyph::IsSimpleAdvance(appAdvance) &&
|
||||
charGlyphs[offs].IsClusterStart() &&
|
||||
(yLocs[c.baseGlyph] == 0).unverified_safe_because(fast_path)) {
|
||||
charGlyphs[offs].SetSimpleGlyph(appAdvance, gid_of_base_glyph);
|
||||
|
||||
charGlyphs[offs].IsClusterStart() && yLocs[c.baseGlyph] == 0) {
|
||||
charGlyphs[offs].SetSimpleGlyph(appAdvance, gids[c.baseGlyph]);
|
||||
} else {
|
||||
// not a one-to-one mapping with simple metrics: use DetailedGlyph
|
||||
AutoTArray<gfxShapedText::DetailedGlyph, 8> details;
|
||||
float clusterLoc;
|
||||
|
||||
uint32_t glyph_end =
|
||||
(c.baseGlyph + c.nGlyphs)
|
||||
.unverified_safe_because(
|
||||
"This only controls the total number of glyphs set for this "
|
||||
"particular text. Worst that can happen is a bad rendering");
|
||||
|
||||
// check overflow - ensure loop start is before the end
|
||||
uint32_t glyph_start =
|
||||
CopyAndVerifyOrFail(c.baseGlyph, val <= glyph_end, &failedVerify);
|
||||
if (failedVerify) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
for (uint32_t j = glyph_start; j < glyph_end; ++j) {
|
||||
for (uint32_t j = c.baseGlyph; j < c.baseGlyph + c.nGlyphs; ++j) {
|
||||
gfxShapedText::DetailedGlyph* d = details.AppendElement();
|
||||
d->mGlyphID = gids[j].unverified_safe_because(gid_simple_value);
|
||||
|
||||
const char safe_coordinates[] =
|
||||
"There are no limits on coordinates. Worst case, bad values would "
|
||||
"force rendering off-screen, but there are no memory safety "
|
||||
"issues.";
|
||||
|
||||
float yLocs_j = yLocs[j].unverified_safe_because(safe_coordinates);
|
||||
float xLocs_j = xLocs[j].unverified_safe_because(safe_coordinates);
|
||||
|
||||
d->mOffset.y = roundY ? NSToIntRound(-yLocs_j) * dev2appUnits
|
||||
: -yLocs_j * dev2appUnits;
|
||||
if (j == glyph_start) {
|
||||
d->mGlyphID = gids[j];
|
||||
d->mOffset.y = roundY ? NSToIntRound(-yLocs[j]) * dev2appUnits
|
||||
: -yLocs[j] * dev2appUnits;
|
||||
if (j == c.baseGlyph) {
|
||||
d->mAdvance = appAdvance;
|
||||
clusterLoc = xLocs_j;
|
||||
clusterLoc = xLocs[j];
|
||||
} else {
|
||||
float dx =
|
||||
rtl ? (xLocs_j - clusterLoc) : (xLocs_j - clusterLoc - adv);
|
||||
rtl ? (xLocs[j] - clusterLoc) : (xLocs[j] - clusterLoc - adv);
|
||||
d->mOffset.x =
|
||||
roundX ? NSToIntRound(dx) * dev2appUnits : dx * dev2appUnits;
|
||||
d->mAdvance = 0;
|
||||
|
@ -429,24 +280,15 @@ nsresult gfxGraphiteShaper::SetGlyphsFromSegment(
|
|||
details.Elements());
|
||||
}
|
||||
|
||||
// check unexpected offset
|
||||
uint32_t char_end = CopyAndVerifyOrFail(c.baseChar + c.nChars,
|
||||
val <= aLength, &failedVerify);
|
||||
// check overflow - ensure loop start is before the end
|
||||
uint32_t char_start =
|
||||
CopyAndVerifyOrFail(c.baseChar + 1, val <= char_end, &failedVerify);
|
||||
if (failedVerify) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
for (uint32_t j = char_start; j < char_end; ++j) {
|
||||
for (uint32_t j = c.baseChar + 1; j < c.baseChar + c.nChars; ++j) {
|
||||
NS_ASSERTION(j < aLength, "unexpected offset");
|
||||
CompressedGlyph& g = charGlyphs[j];
|
||||
NS_ASSERTION(!g.IsSimpleGlyph(), "overwriting a simple glyph");
|
||||
g.SetComplex(g.IsClusterStart(), false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
sandbox_invoke(*mSandbox, gr_free_char_association, data);
|
||||
gr_free_char_association(data);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
|
||||
#include "mozilla/gfx/2D.h"
|
||||
|
||||
#include "ThebesRLBoxTypes.h"
|
||||
|
||||
struct gr_face;
|
||||
struct gr_font;
|
||||
struct gr_segment;
|
||||
|
@ -31,29 +29,13 @@ class gfxGraphiteShaper : public gfxFontShaper {
|
|||
protected:
|
||||
nsresult SetGlyphsFromSegment(gfxShapedText* aShapedText, uint32_t aOffset,
|
||||
uint32_t aLength, const char16_t* aText,
|
||||
tainted_opaque_gr<char16_t*> t_aText,
|
||||
tainted_opaque_gr<gr_segment*> aSegment,
|
||||
RoundingFlags aRounding);
|
||||
gr_segment* aSegment, RoundingFlags aRounding);
|
||||
|
||||
// Graphite is run in a rlbox sandbox. Callback GrGetAdvance must be
|
||||
// explicitly permitted. Since the sandbox is owned in gfxFontEntry class,
|
||||
// gfxFontEntry needs access to the protected callback.
|
||||
friend class gfxFontEntry;
|
||||
static tainted_opaque_gr<float> GrGetAdvance(
|
||||
rlbox_sandbox_gr& sandbox, tainted_opaque_gr<const void*> appFontHandle,
|
||||
tainted_opaque_gr<uint16_t> glyphid);
|
||||
static float GrGetAdvance(const void* appFontHandle, uint16_t glyphid);
|
||||
|
||||
tainted_opaque_gr<gr_face*>
|
||||
mGrFace; // owned by the font entry; shaper must call
|
||||
// gfxFontEntry::ReleaseGrFace when finished with it
|
||||
tainted_opaque_gr<gr_font*> mGrFont; // owned by the shaper itself
|
||||
|
||||
// All libGraphite functionality is sandboxed. This is the sandbox instance.
|
||||
rlbox_sandbox_gr* mSandbox;
|
||||
|
||||
// Holds the handle to the permitted callback into Firefox for the sandboxed
|
||||
// libGraphite
|
||||
sandbox_callback_gr<float (*)(const void*, uint16_t)>* mCallback;
|
||||
gr_face* mGrFace; // owned by the font entry; shaper must call
|
||||
// gfxFontEntry::ReleaseGrFace when finished with it
|
||||
gr_font* mGrFont; // owned by the shaper itself
|
||||
|
||||
struct CallbackData {
|
||||
// mFont is a pointer to the font that owns this shaper, so it will
|
||||
|
@ -62,8 +44,6 @@ class gfxGraphiteShaper : public gfxFontShaper {
|
|||
};
|
||||
|
||||
CallbackData mCallbackData;
|
||||
static thread_local CallbackData* tl_GrGetAdvanceData;
|
||||
|
||||
bool mFallbackToSmallCaps; // special fallback for the petite-caps case
|
||||
|
||||
// Convert HTML 'lang' (BCP47) to Graphite language code
|
||||
|
|
|
@ -60,7 +60,6 @@ EXPORTS += [
|
|||
'gfxUtils.h',
|
||||
'SharedFontList.h',
|
||||
'SoftwareVsyncSource.h',
|
||||
'ThebesRLBoxTypes.h',
|
||||
'VsyncSource.h',
|
||||
]
|
||||
|
||||
|
@ -69,7 +68,6 @@ EXPORTS.mozilla.gfx += [
|
|||
'DeviceManagerDx.h',
|
||||
'PrintTarget.h',
|
||||
'PrintTargetThebes.h',
|
||||
'ThebesRLBox.h',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_ENABLE_SKIA']:
|
||||
|
|
Загрузка…
Ссылка в новой задаче