Pier Angelo Vendrame pushed to branch firefox-android-115.2.1-13.5-1 at The Tor Project / Applications / firefox-android
Commits:
c11e7b38 by Pier Angelo Vendrame at 2024-05-09T18:06:03+02:00
Bug 42652: Pass the list of supported languages to GeckoView.
It will be used to prevent leaks about regional preferences.
- - - - -
1 changed file:
- fenix/app/src/main/java/org/mozilla/fenix/gecko/GeckoProvider.kt
Changes:
=====================================
fenix/app/src/main/java/org/mozilla/fenix/gecko/GeckoProvider.kt
=====================================
@@ -14,6 +14,7 @@ import mozilla.components.concept.storage.LoginsStorage
import mozilla.components.lib.crash.handler.CrashHandlerService
import mozilla.components.service.sync.autofill.GeckoCreditCardsAddressesStorageDelegate
import mozilla.components.service.sync.logins.GeckoLoginStorageDelegate
+import org.mozilla.fenix.BuildConfig
import org.mozilla.fenix.Config
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.settings
@@ -58,6 +59,7 @@ object GeckoProvider {
.contentBlocking(policy.toContentBlockingSetting())
.debugLogging(Config.channel.isDebug || context.components.settings.enableGeckoLogs)
.aboutConfigEnabled(Config.channel.isBeta || Config.channel.isNightlyOrDebug)
+ .supportedLocales(BuildConfig.SUPPORTED_LOCALE_ARRAY.toList())
.build()
val settings = context.components.settings
View it on GitLab: https://gitlab.torproject.org/tpo/applications/firefox-android/-/commit/c11…
--
This project does not include diff previews in email notifications.
View it on GitLab: https://gitlab.torproject.org/tpo/applications/firefox-android/-/commit/c11…
You're receiving this email because of your account on gitlab.torproject.org.
Pier Angelo Vendrame pushed to branch tor-browser-115.11.0esr-13.5-1 at The Tor Project / Applications / Tor Browser
Commits:
83a3762f by Pier Angelo Vendrame at 2024-05-09T18:04:04+02:00
fixup! Bug 40199: Avoid using system locale for intl.accept_languages in GeckoView
Revert "Bug 40199: Avoid using system locale for intl.accept_languages in GeckoView"
This reverts commit ff97b6fb06850784785e6993c256bef315b2525f.
- - - - -
e6f7f151 by Pier Angelo Vendrame at 2024-05-09T18:04:07+02:00
Bug 42562: Normalized the Accepted Languages on Android.
The OS language might be outside the list of actually supported
languages and it might leak the user's region.
Therefore, we force the locale reported in Accept-Language to match one
we support with translations, even when it means using a not exact
region tag.
- - - - -
1 changed file:
- mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java
Changes:
=====================================
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java
=====================================
@@ -22,7 +22,8 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
import java.util.Locale;
import org.mozilla.gecko.EventDispatcher;
import org.mozilla.gecko.GeckoSystemStateListener;
@@ -455,6 +456,16 @@ public final class GeckoRuntimeSettings extends RuntimeSettings {
return this;
}
+ public @NonNull Builder supportedLocales(final Collection<String> locales) {
+ getSettings().mSupportedLocales.clear();
+ for (String tag : locales) {
+ Locale locale = Locale.forLanguageTag(tag);
+ getSettings().mSupportedLocales.put(locale, locale);
+ getSettings().mSupportedLocales.put(new Locale(locale.getLanguage()), locale);
+ }
+ return this;
+ }
+
/**
* Sets whether we should spoof locale to English for webpages.
*
@@ -546,6 +557,7 @@ public final class GeckoRuntimeSettings extends RuntimeSettings {
/* package */ int mScreenHeightOverride;
/* package */ Class<? extends Service> mCrashHandler;
/* package */ String[] mRequestedLocales;
+ /* package */ HashMap<Locale, Locale> mSupportedLocales = new HashMap<>();
/* package */ RuntimeTelemetry.Proxy mTelemetryProxy;
/**
@@ -602,6 +614,7 @@ public final class GeckoRuntimeSettings extends RuntimeSettings {
mRequestedLocales = settings.mRequestedLocales;
mConfigFilePath = settings.mConfigFilePath;
mTelemetryProxy = settings.mTelemetryProxy;
+ mSupportedLocales = settings.mSupportedLocales;
}
/* package */ void commit() {
@@ -810,30 +823,39 @@ public final class GeckoRuntimeSettings extends RuntimeSettings {
EventDispatcher.getInstance().dispatch("GeckoView:SetLocale", data);
}
+ private Locale getLocaleIfSupported(String tag) {
+ Locale exact = Locale.forLanguageTag(tag);
+ if (mSupportedLocales.containsKey(exact)) {
+ return exact;
+ }
+ Locale fallback = new Locale(exact.getLanguage());
+ return mSupportedLocales.get(fallback);
+ }
+
private String computeAcceptLanguages() {
- final ArrayList<String> locales = new ArrayList<String>();
-
- // In Desktop, these are defined in the `intl.accept_languages` localized property.
- // At some point we should probably use the same values here, but for now we use a simple
- // strategy which will hopefully result in reasonable acceptLanguage values.
- if (mRequestedLocales != null && mRequestedLocales.length > 0) {
- String locale = mRequestedLocales[0].toLowerCase(Locale.ROOT);
- // No need to include `en-us` twice.
- if (!locale.equals("en-us")) {
- locales.add(locale);
- if (locale.contains("-")) {
- String lang = locale.split("-")[0];
- // No need to include `en` twice.
- if (!lang.equals("en")) {
- locales.add(lang);
- }
+ Locale locale = null;
+ if (mRequestedLocales != null) {
+ for (String tag : mRequestedLocales) {
+ locale = getLocaleIfSupported(tag);
+ if (locale != null) {
+ break;
}
}
}
- locales.add("en-us");
- locales.add("en");
-
- return TextUtils.join(",", locales);
+ if (locale == null) {
+ for (final String tag : getDefaultLocales()) {
+ locale = getLocaleIfSupported(tag);
+ if (locale != null) {
+ break;
+ }
+ }
+ }
+ String acceptLanguages = locale != null ? locale.toString().replace('_', '-') : "en-US";
+ if (acceptLanguages.equals("en-US")) {
+ // For consistency with spoof English.
+ acceptLanguages += ", en";
+ }
+ return acceptLanguages;
}
private static String[] getDefaultLocales() {
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/66e2e3…
--
This project does not include diff previews in email notifications.
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/66e2e3…
You're receiving this email because of your account on gitlab.torproject.org.
ma1 pushed to branch base-browser-115.11.0esr-13.5-1 at The Tor Project / Applications / Tor Browser
Commits:
6d5a0677 by Nuohan Li at 2024-05-09T13:38:19+02:00
Bug 1871109 - generateHash in Manifest.sys.mjs should use sha256 r=peterv, a=dmeehan
Differential Revision: https://phabricator.services.mozilla.com/D204928
- - - - -
58dc31a0 by Jonathan Kew at 2024-05-09T13:38:20+02:00
Bug 1890204 - Ensure font entry's unitsPerEm and font extents are initialized when gfxFont is created. r=gfx-reviewers,lsalzman
This means that by the time we potentially call GetFontExtents() when drawing,
the extents fields are guaranteed to have been been initialized, and there's no
risk of the (read-only) access here racing with setting them in UnitsPerEm().
Differential Revision: https://phabricator.services.mozilla.com/D206920
- - - - -
e7430547 by Jonathan Kew at 2024-05-09T13:38:21+02:00
Bug 1893891 - Clear mSharedBlobData if blob creation failed. a=dmeehan
Original Revision: https://phabricator.services.mozilla.com/D208983
Differential Revision: https://phabricator.services.mozilla.com/D209209
- - - - -
5 changed files:
- dom/manifest/Manifest.sys.mjs
- dom/manifest/test/browser_Manifest_install.js
- gfx/thebes/gfxFont.cpp
- gfx/thebes/gfxFontEntry.cpp
- gfx/thebes/gfxFontEntry.h
Changes:
=====================================
dom/manifest/Manifest.sys.mjs
=====================================
@@ -29,11 +29,11 @@ ChromeUtils.defineESModuleGetters(lazy, {
* @note The generated hash is returned in base64 form. Mind the fact base64
* is case-sensitive if you are going to reuse this code.
*/
-function generateHash(aString) {
+function generateHash(aString, hashAlg) {
const cryptoHash = Cc["@mozilla.org/security/hash;1"].createInstance(
Ci.nsICryptoHash
);
- cryptoHash.init(Ci.nsICryptoHash.MD5);
+ cryptoHash.init(hashAlg);
const stringStream = Cc[
"@mozilla.org/io/string-input-stream;1"
].createInstance(Ci.nsIStringInputStream);
@@ -66,11 +66,39 @@ class Manifest {
this._manifestUrl = manifestUrl;
// The key for this is the manifests URL that is required to be unique.
// However arbitrary urls are not safe file paths so lets hash it.
- const fileName = generateHash(manifestUrl) + ".json";
- this._path = PathUtils.join(MANIFESTS_DIR, fileName);
+ const filename =
+ generateHash(manifestUrl, Ci.nsICryptoHash.SHA256) + ".json";
+ this._path = PathUtils.join(MANIFESTS_DIR, filename);
this.browser = browser;
}
+ /**
+ * See Bug 1871109
+ * This function is called at the beginning of initialize() to check if a given
+ * manifest has MD5 based filename, if so we remove it and migrate the content to
+ * a new file with SHA256 based name.
+ * This is done due to security concern, as MD5 is an outdated hashing algorithm and
+ * shouldn't be used anymore
+ */
+ async removeMD5BasedFilename() {
+ const filenameMD5 =
+ generateHash(this._manifestUrl, Ci.nsICryptoHash.MD5) + ".json";
+ const MD5Path = PathUtils.join(MANIFESTS_DIR, filenameMD5);
+ try {
+ await IOUtils.copy(MD5Path, this._path, { noOverwrite: true });
+ } catch (error) {
+ // we are ignoring the failures returned from copy as it should not stop us from
+ // installing a new manifest
+ }
+
+ // Remove the old MD5 based file unconditionally to ensure it's no longer used
+ try {
+ await IOUtils.remove(MD5Path);
+ } catch {
+ // ignore the error in case MD5 based file does not exist
+ }
+ }
+
get browser() {
return this._browser;
}
@@ -80,6 +108,7 @@ class Manifest {
}
async initialize() {
+ await this.removeMD5BasedFilename();
this._store = new lazy.JSONFile({ path: this._path, saveDelayMs: 100 });
await this._store.load();
}
=====================================
dom/manifest/test/browser_Manifest_install.js
=====================================
@@ -23,18 +23,59 @@ function makeTestURL() {
return url.href;
}
+function generateHash(aString, hashAlg) {
+ const cryptoHash = Cc["@mozilla.org/security/hash;1"].createInstance(
+ Ci.nsICryptoHash
+ );
+ cryptoHash.init(hashAlg);
+ const stringStream = Cc[
+ "@mozilla.org/io/string-input-stream;1"
+ ].createInstance(Ci.nsIStringInputStream);
+ stringStream.data = aString;
+ cryptoHash.updateFromStream(stringStream, -1);
+ // base64 allows the '/' char, but we can't use it for filenames.
+ return cryptoHash.finish(true).replace(/\//g, "-");
+}
+
+const MANIFESTS_DIR = PathUtils.join(PathUtils.profileDir, "manifests");
+
add_task(async function () {
const tabOptions = { gBrowser, url: makeTestURL() };
+ const filenameMD5 = generateHash(manifestUrl, Ci.nsICryptoHash.MD5) + ".json";
+ const filenameSHA =
+ generateHash(manifestUrl, Ci.nsICryptoHash.SHA256) + ".json";
+ const manifestMD5Path = PathUtils.join(MANIFESTS_DIR, filenameMD5);
+ const manifestSHAPath = PathUtils.join(MANIFESTS_DIR, filenameSHA);
+
await BrowserTestUtils.withNewTab(tabOptions, async function (browser) {
- let manifest = await Manifests.getManifest(browser, manifestUrl);
- is(manifest.installed, false, "We haven't installed this manifest yet");
+ let tmpManifest = await Manifests.getManifest(browser, manifestUrl);
+ is(tmpManifest.installed, false, "We haven't installed this manifest yet");
+
+ await tmpManifest.install();
+ // making sure the manifest is actually installed before proceeding
+ await tmpManifest._store._save();
+ await IOUtils.move(tmpManifest.path, manifestMD5Path);
+
+ let exists = await IOUtils.exists(tmpManifest.path);
+ is(
+ exists,
+ false,
+ "Manually moved manifest from SHA256 based path to MD5 based path"
+ );
+ Manifests.manifestObjs.delete(manifestUrl);
+
+ let manifest = await Manifests.getManifest(browser, manifestUrl);
await manifest.install(browser);
is(manifest.name, "hello World", "Manifest has correct name");
is(manifest.installed, true, "Manifest is installed");
is(manifest.url, manifestUrl, "has correct url");
is(manifest.browser, browser, "has correct browser");
+ is(manifest.path, manifestSHAPath, "has correct path");
+
+ exists = await IOUtils.exists(manifestMD5Path);
+ is(exists, false, "MD5 based manifest removed");
manifest = await Manifests.getManifest(browser, manifestUrl);
is(manifest.installed, true, "New instances are installed");
=====================================
gfx/thebes/gfxFont.cpp
=====================================
@@ -952,6 +952,10 @@ gfxFont::gfxFont(const RefPtr<UnscaledFont>& aUnscaledFont,
}
mKerningSet = HasFeatureSet(HB_TAG('k', 'e', 'r', 'n'), mKerningEnabled);
+
+ // Ensure the gfxFontEntry's unitsPerEm and extents fields are initialized,
+ // so that GetFontExtents can use them without risk of races.
+ Unused << mFontEntry->UnitsPerEm();
}
gfxFont::~gfxFont() {
=====================================
gfx/thebes/gfxFontEntry.cpp
=====================================
@@ -262,14 +262,22 @@ already_AddRefed<gfxFont> gfxFontEntry::FindOrMakeFont(
}
uint16_t gfxFontEntry::UnitsPerEm() {
+ {
+ AutoReadLock lock(mLock);
+ if (mUnitsPerEm) {
+ return mUnitsPerEm;
+ }
+ }
+
+ AutoTable headTable(this, TRUETYPE_TAG('h', 'e', 'a', 'd'));
+ AutoWriteLock lock(mLock);
+
if (!mUnitsPerEm) {
- AutoTable headTable(this, TRUETYPE_TAG('h', 'e', 'a', 'd'));
if (headTable) {
uint32_t len;
const HeadTable* head =
reinterpret_cast<const HeadTable*>(hb_blob_get_data(headTable, &len));
if (len >= sizeof(HeadTable)) {
- mUnitsPerEm = head->unitsPerEm;
if (int16_t(head->xMax) > int16_t(head->xMin) &&
int16_t(head->yMax) > int16_t(head->yMin)) {
mXMin = head->xMin;
@@ -277,6 +285,7 @@ uint16_t gfxFontEntry::UnitsPerEm() {
mXMax = head->xMax;
mYMax = head->yMax;
}
+ mUnitsPerEm = head->unitsPerEm;
}
}
@@ -286,12 +295,13 @@ uint16_t gfxFontEntry::UnitsPerEm() {
mUnitsPerEm = kInvalidUPEM;
}
}
+
return mUnitsPerEm;
}
bool gfxFontEntry::HasSVGGlyph(uint32_t aGlyphId) {
- NS_ASSERTION(mSVGInitialized,
- "SVG data has not yet been loaded. TryGetSVGData() first.");
+ MOZ_ASSERT(mSVGInitialized,
+ "SVG data has not yet been loaded. TryGetSVGData() first.");
return GetSVGGlyphs()->HasSVGGlyph(aGlyphId);
}
@@ -309,8 +319,8 @@ bool gfxFontEntry::GetSVGGlyphExtents(DrawTarget* aDrawTarget,
void gfxFontEntry::RenderSVGGlyph(gfxContext* aContext, uint32_t aGlyphId,
SVGContextPaint* aContextPaint) {
- NS_ASSERTION(mSVGInitialized,
- "SVG data has not yet been loaded. TryGetSVGData() first.");
+ MOZ_ASSERT(mSVGInitialized,
+ "SVG data has not yet been loaded. TryGetSVGData() first.");
GetSVGGlyphs()->RenderGlyph(aContext, aGlyphId, aContextPaint);
}
@@ -467,8 +477,9 @@ hb_blob_t* gfxFontEntry::FontTableHashEntry::ShareTableAndGetBlob(
HB_MEMORY_MODE_READONLY, mSharedBlobData, DeleteFontTableBlobData);
if (mBlob == hb_blob_get_empty()) {
// The FontTableBlobData was destroyed during hb_blob_create().
- // The (empty) blob is still be held in the hashtable with a strong
+ // The (empty) blob will still be held in the hashtable with a strong
// reference.
+ mSharedBlobData = nullptr;
return hb_blob_reference(mBlob);
}
=====================================
gfx/thebes/gfxFontEntry.h
=====================================
@@ -538,6 +538,9 @@ class gfxFontEntry {
mozilla::gfx::Rect GetFontExtents(float aFUnitScaleFactor) const {
// Flip the y-axis here to match the orientation of Gecko's coordinates.
+ // We don't need to take a lock here because the min/max fields are inert
+ // after initialization, and we make sure to initialize them at gfxFont-
+ // creation time.
return mozilla::gfx::Rect(float(mXMin) * aFUnitScaleFactor,
float(-mYMax) * aFUnitScaleFactor,
float(mXMax - mXMin) * aFUnitScaleFactor,
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/98625d…
--
This project does not include diff previews in email notifications.
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/98625d…
You're receiving this email because of your account on gitlab.torproject.org.
ma1 pushed to branch tor-browser-115.11.0esr-13.5-1 at The Tor Project / Applications / Tor Browser
Commits:
62619558 by Nuohan Li at 2024-05-09T13:37:32+02:00
Bug 1871109 - generateHash in Manifest.sys.mjs should use sha256 r=peterv, a=dmeehan
Differential Revision: https://phabricator.services.mozilla.com/D204928
- - - - -
4846c1da by Jonathan Kew at 2024-05-09T13:37:33+02:00
Bug 1890204 - Ensure font entry's unitsPerEm and font extents are initialized when gfxFont is created. r=gfx-reviewers,lsalzman
This means that by the time we potentially call GetFontExtents() when drawing,
the extents fields are guaranteed to have been been initialized, and there's no
risk of the (read-only) access here racing with setting them in UnitsPerEm().
Differential Revision: https://phabricator.services.mozilla.com/D206920
- - - - -
66e2e3ef by Jonathan Kew at 2024-05-09T13:37:34+02:00
Bug 1893891 - Clear mSharedBlobData if blob creation failed. a=dmeehan
Original Revision: https://phabricator.services.mozilla.com/D208983
Differential Revision: https://phabricator.services.mozilla.com/D209209
- - - - -
5 changed files:
- dom/manifest/Manifest.sys.mjs
- dom/manifest/test/browser_Manifest_install.js
- gfx/thebes/gfxFont.cpp
- gfx/thebes/gfxFontEntry.cpp
- gfx/thebes/gfxFontEntry.h
Changes:
=====================================
dom/manifest/Manifest.sys.mjs
=====================================
@@ -29,11 +29,11 @@ ChromeUtils.defineESModuleGetters(lazy, {
* @note The generated hash is returned in base64 form. Mind the fact base64
* is case-sensitive if you are going to reuse this code.
*/
-function generateHash(aString) {
+function generateHash(aString, hashAlg) {
const cryptoHash = Cc["@mozilla.org/security/hash;1"].createInstance(
Ci.nsICryptoHash
);
- cryptoHash.init(Ci.nsICryptoHash.MD5);
+ cryptoHash.init(hashAlg);
const stringStream = Cc[
"@mozilla.org/io/string-input-stream;1"
].createInstance(Ci.nsIStringInputStream);
@@ -66,11 +66,39 @@ class Manifest {
this._manifestUrl = manifestUrl;
// The key for this is the manifests URL that is required to be unique.
// However arbitrary urls are not safe file paths so lets hash it.
- const fileName = generateHash(manifestUrl) + ".json";
- this._path = PathUtils.join(MANIFESTS_DIR, fileName);
+ const filename =
+ generateHash(manifestUrl, Ci.nsICryptoHash.SHA256) + ".json";
+ this._path = PathUtils.join(MANIFESTS_DIR, filename);
this.browser = browser;
}
+ /**
+ * See Bug 1871109
+ * This function is called at the beginning of initialize() to check if a given
+ * manifest has MD5 based filename, if so we remove it and migrate the content to
+ * a new file with SHA256 based name.
+ * This is done due to security concern, as MD5 is an outdated hashing algorithm and
+ * shouldn't be used anymore
+ */
+ async removeMD5BasedFilename() {
+ const filenameMD5 =
+ generateHash(this._manifestUrl, Ci.nsICryptoHash.MD5) + ".json";
+ const MD5Path = PathUtils.join(MANIFESTS_DIR, filenameMD5);
+ try {
+ await IOUtils.copy(MD5Path, this._path, { noOverwrite: true });
+ } catch (error) {
+ // we are ignoring the failures returned from copy as it should not stop us from
+ // installing a new manifest
+ }
+
+ // Remove the old MD5 based file unconditionally to ensure it's no longer used
+ try {
+ await IOUtils.remove(MD5Path);
+ } catch {
+ // ignore the error in case MD5 based file does not exist
+ }
+ }
+
get browser() {
return this._browser;
}
@@ -80,6 +108,7 @@ class Manifest {
}
async initialize() {
+ await this.removeMD5BasedFilename();
this._store = new lazy.JSONFile({ path: this._path, saveDelayMs: 100 });
await this._store.load();
}
=====================================
dom/manifest/test/browser_Manifest_install.js
=====================================
@@ -23,18 +23,59 @@ function makeTestURL() {
return url.href;
}
+function generateHash(aString, hashAlg) {
+ const cryptoHash = Cc["@mozilla.org/security/hash;1"].createInstance(
+ Ci.nsICryptoHash
+ );
+ cryptoHash.init(hashAlg);
+ const stringStream = Cc[
+ "@mozilla.org/io/string-input-stream;1"
+ ].createInstance(Ci.nsIStringInputStream);
+ stringStream.data = aString;
+ cryptoHash.updateFromStream(stringStream, -1);
+ // base64 allows the '/' char, but we can't use it for filenames.
+ return cryptoHash.finish(true).replace(/\//g, "-");
+}
+
+const MANIFESTS_DIR = PathUtils.join(PathUtils.profileDir, "manifests");
+
add_task(async function () {
const tabOptions = { gBrowser, url: makeTestURL() };
+ const filenameMD5 = generateHash(manifestUrl, Ci.nsICryptoHash.MD5) + ".json";
+ const filenameSHA =
+ generateHash(manifestUrl, Ci.nsICryptoHash.SHA256) + ".json";
+ const manifestMD5Path = PathUtils.join(MANIFESTS_DIR, filenameMD5);
+ const manifestSHAPath = PathUtils.join(MANIFESTS_DIR, filenameSHA);
+
await BrowserTestUtils.withNewTab(tabOptions, async function (browser) {
- let manifest = await Manifests.getManifest(browser, manifestUrl);
- is(manifest.installed, false, "We haven't installed this manifest yet");
+ let tmpManifest = await Manifests.getManifest(browser, manifestUrl);
+ is(tmpManifest.installed, false, "We haven't installed this manifest yet");
+
+ await tmpManifest.install();
+ // making sure the manifest is actually installed before proceeding
+ await tmpManifest._store._save();
+ await IOUtils.move(tmpManifest.path, manifestMD5Path);
+
+ let exists = await IOUtils.exists(tmpManifest.path);
+ is(
+ exists,
+ false,
+ "Manually moved manifest from SHA256 based path to MD5 based path"
+ );
+ Manifests.manifestObjs.delete(manifestUrl);
+
+ let manifest = await Manifests.getManifest(browser, manifestUrl);
await manifest.install(browser);
is(manifest.name, "hello World", "Manifest has correct name");
is(manifest.installed, true, "Manifest is installed");
is(manifest.url, manifestUrl, "has correct url");
is(manifest.browser, browser, "has correct browser");
+ is(manifest.path, manifestSHAPath, "has correct path");
+
+ exists = await IOUtils.exists(manifestMD5Path);
+ is(exists, false, "MD5 based manifest removed");
manifest = await Manifests.getManifest(browser, manifestUrl);
is(manifest.installed, true, "New instances are installed");
=====================================
gfx/thebes/gfxFont.cpp
=====================================
@@ -952,6 +952,10 @@ gfxFont::gfxFont(const RefPtr<UnscaledFont>& aUnscaledFont,
}
mKerningSet = HasFeatureSet(HB_TAG('k', 'e', 'r', 'n'), mKerningEnabled);
+
+ // Ensure the gfxFontEntry's unitsPerEm and extents fields are initialized,
+ // so that GetFontExtents can use them without risk of races.
+ Unused << mFontEntry->UnitsPerEm();
}
gfxFont::~gfxFont() {
=====================================
gfx/thebes/gfxFontEntry.cpp
=====================================
@@ -262,14 +262,22 @@ already_AddRefed<gfxFont> gfxFontEntry::FindOrMakeFont(
}
uint16_t gfxFontEntry::UnitsPerEm() {
+ {
+ AutoReadLock lock(mLock);
+ if (mUnitsPerEm) {
+ return mUnitsPerEm;
+ }
+ }
+
+ AutoTable headTable(this, TRUETYPE_TAG('h', 'e', 'a', 'd'));
+ AutoWriteLock lock(mLock);
+
if (!mUnitsPerEm) {
- AutoTable headTable(this, TRUETYPE_TAG('h', 'e', 'a', 'd'));
if (headTable) {
uint32_t len;
const HeadTable* head =
reinterpret_cast<const HeadTable*>(hb_blob_get_data(headTable, &len));
if (len >= sizeof(HeadTable)) {
- mUnitsPerEm = head->unitsPerEm;
if (int16_t(head->xMax) > int16_t(head->xMin) &&
int16_t(head->yMax) > int16_t(head->yMin)) {
mXMin = head->xMin;
@@ -277,6 +285,7 @@ uint16_t gfxFontEntry::UnitsPerEm() {
mXMax = head->xMax;
mYMax = head->yMax;
}
+ mUnitsPerEm = head->unitsPerEm;
}
}
@@ -286,12 +295,13 @@ uint16_t gfxFontEntry::UnitsPerEm() {
mUnitsPerEm = kInvalidUPEM;
}
}
+
return mUnitsPerEm;
}
bool gfxFontEntry::HasSVGGlyph(uint32_t aGlyphId) {
- NS_ASSERTION(mSVGInitialized,
- "SVG data has not yet been loaded. TryGetSVGData() first.");
+ MOZ_ASSERT(mSVGInitialized,
+ "SVG data has not yet been loaded. TryGetSVGData() first.");
return GetSVGGlyphs()->HasSVGGlyph(aGlyphId);
}
@@ -309,8 +319,8 @@ bool gfxFontEntry::GetSVGGlyphExtents(DrawTarget* aDrawTarget,
void gfxFontEntry::RenderSVGGlyph(gfxContext* aContext, uint32_t aGlyphId,
SVGContextPaint* aContextPaint) {
- NS_ASSERTION(mSVGInitialized,
- "SVG data has not yet been loaded. TryGetSVGData() first.");
+ MOZ_ASSERT(mSVGInitialized,
+ "SVG data has not yet been loaded. TryGetSVGData() first.");
GetSVGGlyphs()->RenderGlyph(aContext, aGlyphId, aContextPaint);
}
@@ -467,8 +477,9 @@ hb_blob_t* gfxFontEntry::FontTableHashEntry::ShareTableAndGetBlob(
HB_MEMORY_MODE_READONLY, mSharedBlobData, DeleteFontTableBlobData);
if (mBlob == hb_blob_get_empty()) {
// The FontTableBlobData was destroyed during hb_blob_create().
- // The (empty) blob is still be held in the hashtable with a strong
+ // The (empty) blob will still be held in the hashtable with a strong
// reference.
+ mSharedBlobData = nullptr;
return hb_blob_reference(mBlob);
}
=====================================
gfx/thebes/gfxFontEntry.h
=====================================
@@ -538,6 +538,9 @@ class gfxFontEntry {
mozilla::gfx::Rect GetFontExtents(float aFUnitScaleFactor) const {
// Flip the y-axis here to match the orientation of Gecko's coordinates.
+ // We don't need to take a lock here because the min/max fields are inert
+ // after initialization, and we make sure to initialize them at gfxFont-
+ // creation time.
return mozilla::gfx::Rect(float(mXMin) * aFUnitScaleFactor,
float(-mYMax) * aFUnitScaleFactor,
float(mXMax - mXMin) * aFUnitScaleFactor,
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/410bb2…
--
This project does not include diff previews in email notifications.
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/410bb2…
You're receiving this email because of your account on gitlab.torproject.org.
ma1 pushed to branch mullvad-browser-115.11.0esr-13.5-1 at The Tor Project / Applications / Mullvad Browser
Commits:
ac1e73ce by Nuohan Li at 2024-05-09T13:36:35+02:00
Bug 1871109 - generateHash in Manifest.sys.mjs should use sha256 r=peterv, a=dmeehan
Differential Revision: https://phabricator.services.mozilla.com/D204928
- - - - -
f0b17745 by Jonathan Kew at 2024-05-09T13:36:36+02:00
Bug 1890204 - Ensure font entry's unitsPerEm and font extents are initialized when gfxFont is created. r=gfx-reviewers,lsalzman
This means that by the time we potentially call GetFontExtents() when drawing,
the extents fields are guaranteed to have been been initialized, and there's no
risk of the (read-only) access here racing with setting them in UnitsPerEm().
Differential Revision: https://phabricator.services.mozilla.com/D206920
- - - - -
29322606 by Jonathan Kew at 2024-05-09T13:36:37+02:00
Bug 1893891 - Clear mSharedBlobData if blob creation failed. a=dmeehan
Original Revision: https://phabricator.services.mozilla.com/D208983
Differential Revision: https://phabricator.services.mozilla.com/D209209
- - - - -
5 changed files:
- dom/manifest/Manifest.sys.mjs
- dom/manifest/test/browser_Manifest_install.js
- gfx/thebes/gfxFont.cpp
- gfx/thebes/gfxFontEntry.cpp
- gfx/thebes/gfxFontEntry.h
Changes:
=====================================
dom/manifest/Manifest.sys.mjs
=====================================
@@ -29,11 +29,11 @@ ChromeUtils.defineESModuleGetters(lazy, {
* @note The generated hash is returned in base64 form. Mind the fact base64
* is case-sensitive if you are going to reuse this code.
*/
-function generateHash(aString) {
+function generateHash(aString, hashAlg) {
const cryptoHash = Cc["@mozilla.org/security/hash;1"].createInstance(
Ci.nsICryptoHash
);
- cryptoHash.init(Ci.nsICryptoHash.MD5);
+ cryptoHash.init(hashAlg);
const stringStream = Cc[
"@mozilla.org/io/string-input-stream;1"
].createInstance(Ci.nsIStringInputStream);
@@ -66,11 +66,39 @@ class Manifest {
this._manifestUrl = manifestUrl;
// The key for this is the manifests URL that is required to be unique.
// However arbitrary urls are not safe file paths so lets hash it.
- const fileName = generateHash(manifestUrl) + ".json";
- this._path = PathUtils.join(MANIFESTS_DIR, fileName);
+ const filename =
+ generateHash(manifestUrl, Ci.nsICryptoHash.SHA256) + ".json";
+ this._path = PathUtils.join(MANIFESTS_DIR, filename);
this.browser = browser;
}
+ /**
+ * See Bug 1871109
+ * This function is called at the beginning of initialize() to check if a given
+ * manifest has MD5 based filename, if so we remove it and migrate the content to
+ * a new file with SHA256 based name.
+ * This is done due to security concern, as MD5 is an outdated hashing algorithm and
+ * shouldn't be used anymore
+ */
+ async removeMD5BasedFilename() {
+ const filenameMD5 =
+ generateHash(this._manifestUrl, Ci.nsICryptoHash.MD5) + ".json";
+ const MD5Path = PathUtils.join(MANIFESTS_DIR, filenameMD5);
+ try {
+ await IOUtils.copy(MD5Path, this._path, { noOverwrite: true });
+ } catch (error) {
+ // we are ignoring the failures returned from copy as it should not stop us from
+ // installing a new manifest
+ }
+
+ // Remove the old MD5 based file unconditionally to ensure it's no longer used
+ try {
+ await IOUtils.remove(MD5Path);
+ } catch {
+ // ignore the error in case MD5 based file does not exist
+ }
+ }
+
get browser() {
return this._browser;
}
@@ -80,6 +108,7 @@ class Manifest {
}
async initialize() {
+ await this.removeMD5BasedFilename();
this._store = new lazy.JSONFile({ path: this._path, saveDelayMs: 100 });
await this._store.load();
}
=====================================
dom/manifest/test/browser_Manifest_install.js
=====================================
@@ -23,18 +23,59 @@ function makeTestURL() {
return url.href;
}
+function generateHash(aString, hashAlg) {
+ const cryptoHash = Cc["@mozilla.org/security/hash;1"].createInstance(
+ Ci.nsICryptoHash
+ );
+ cryptoHash.init(hashAlg);
+ const stringStream = Cc[
+ "@mozilla.org/io/string-input-stream;1"
+ ].createInstance(Ci.nsIStringInputStream);
+ stringStream.data = aString;
+ cryptoHash.updateFromStream(stringStream, -1);
+ // base64 allows the '/' char, but we can't use it for filenames.
+ return cryptoHash.finish(true).replace(/\//g, "-");
+}
+
+const MANIFESTS_DIR = PathUtils.join(PathUtils.profileDir, "manifests");
+
add_task(async function () {
const tabOptions = { gBrowser, url: makeTestURL() };
+ const filenameMD5 = generateHash(manifestUrl, Ci.nsICryptoHash.MD5) + ".json";
+ const filenameSHA =
+ generateHash(manifestUrl, Ci.nsICryptoHash.SHA256) + ".json";
+ const manifestMD5Path = PathUtils.join(MANIFESTS_DIR, filenameMD5);
+ const manifestSHAPath = PathUtils.join(MANIFESTS_DIR, filenameSHA);
+
await BrowserTestUtils.withNewTab(tabOptions, async function (browser) {
- let manifest = await Manifests.getManifest(browser, manifestUrl);
- is(manifest.installed, false, "We haven't installed this manifest yet");
+ let tmpManifest = await Manifests.getManifest(browser, manifestUrl);
+ is(tmpManifest.installed, false, "We haven't installed this manifest yet");
+
+ await tmpManifest.install();
+ // making sure the manifest is actually installed before proceeding
+ await tmpManifest._store._save();
+ await IOUtils.move(tmpManifest.path, manifestMD5Path);
+
+ let exists = await IOUtils.exists(tmpManifest.path);
+ is(
+ exists,
+ false,
+ "Manually moved manifest from SHA256 based path to MD5 based path"
+ );
+ Manifests.manifestObjs.delete(manifestUrl);
+
+ let manifest = await Manifests.getManifest(browser, manifestUrl);
await manifest.install(browser);
is(manifest.name, "hello World", "Manifest has correct name");
is(manifest.installed, true, "Manifest is installed");
is(manifest.url, manifestUrl, "has correct url");
is(manifest.browser, browser, "has correct browser");
+ is(manifest.path, manifestSHAPath, "has correct path");
+
+ exists = await IOUtils.exists(manifestMD5Path);
+ is(exists, false, "MD5 based manifest removed");
manifest = await Manifests.getManifest(browser, manifestUrl);
is(manifest.installed, true, "New instances are installed");
=====================================
gfx/thebes/gfxFont.cpp
=====================================
@@ -952,6 +952,10 @@ gfxFont::gfxFont(const RefPtr<UnscaledFont>& aUnscaledFont,
}
mKerningSet = HasFeatureSet(HB_TAG('k', 'e', 'r', 'n'), mKerningEnabled);
+
+ // Ensure the gfxFontEntry's unitsPerEm and extents fields are initialized,
+ // so that GetFontExtents can use them without risk of races.
+ Unused << mFontEntry->UnitsPerEm();
}
gfxFont::~gfxFont() {
=====================================
gfx/thebes/gfxFontEntry.cpp
=====================================
@@ -262,14 +262,22 @@ already_AddRefed<gfxFont> gfxFontEntry::FindOrMakeFont(
}
uint16_t gfxFontEntry::UnitsPerEm() {
+ {
+ AutoReadLock lock(mLock);
+ if (mUnitsPerEm) {
+ return mUnitsPerEm;
+ }
+ }
+
+ AutoTable headTable(this, TRUETYPE_TAG('h', 'e', 'a', 'd'));
+ AutoWriteLock lock(mLock);
+
if (!mUnitsPerEm) {
- AutoTable headTable(this, TRUETYPE_TAG('h', 'e', 'a', 'd'));
if (headTable) {
uint32_t len;
const HeadTable* head =
reinterpret_cast<const HeadTable*>(hb_blob_get_data(headTable, &len));
if (len >= sizeof(HeadTable)) {
- mUnitsPerEm = head->unitsPerEm;
if (int16_t(head->xMax) > int16_t(head->xMin) &&
int16_t(head->yMax) > int16_t(head->yMin)) {
mXMin = head->xMin;
@@ -277,6 +285,7 @@ uint16_t gfxFontEntry::UnitsPerEm() {
mXMax = head->xMax;
mYMax = head->yMax;
}
+ mUnitsPerEm = head->unitsPerEm;
}
}
@@ -286,12 +295,13 @@ uint16_t gfxFontEntry::UnitsPerEm() {
mUnitsPerEm = kInvalidUPEM;
}
}
+
return mUnitsPerEm;
}
bool gfxFontEntry::HasSVGGlyph(uint32_t aGlyphId) {
- NS_ASSERTION(mSVGInitialized,
- "SVG data has not yet been loaded. TryGetSVGData() first.");
+ MOZ_ASSERT(mSVGInitialized,
+ "SVG data has not yet been loaded. TryGetSVGData() first.");
return GetSVGGlyphs()->HasSVGGlyph(aGlyphId);
}
@@ -309,8 +319,8 @@ bool gfxFontEntry::GetSVGGlyphExtents(DrawTarget* aDrawTarget,
void gfxFontEntry::RenderSVGGlyph(gfxContext* aContext, uint32_t aGlyphId,
SVGContextPaint* aContextPaint) {
- NS_ASSERTION(mSVGInitialized,
- "SVG data has not yet been loaded. TryGetSVGData() first.");
+ MOZ_ASSERT(mSVGInitialized,
+ "SVG data has not yet been loaded. TryGetSVGData() first.");
GetSVGGlyphs()->RenderGlyph(aContext, aGlyphId, aContextPaint);
}
@@ -467,8 +477,9 @@ hb_blob_t* gfxFontEntry::FontTableHashEntry::ShareTableAndGetBlob(
HB_MEMORY_MODE_READONLY, mSharedBlobData, DeleteFontTableBlobData);
if (mBlob == hb_blob_get_empty()) {
// The FontTableBlobData was destroyed during hb_blob_create().
- // The (empty) blob is still be held in the hashtable with a strong
+ // The (empty) blob will still be held in the hashtable with a strong
// reference.
+ mSharedBlobData = nullptr;
return hb_blob_reference(mBlob);
}
=====================================
gfx/thebes/gfxFontEntry.h
=====================================
@@ -538,6 +538,9 @@ class gfxFontEntry {
mozilla::gfx::Rect GetFontExtents(float aFUnitScaleFactor) const {
// Flip the y-axis here to match the orientation of Gecko's coordinates.
+ // We don't need to take a lock here because the min/max fields are inert
+ // after initialization, and we make sure to initialize them at gfxFont-
+ // creation time.
return mozilla::gfx::Rect(float(mXMin) * aFUnitScaleFactor,
float(-mYMax) * aFUnitScaleFactor,
float(mXMax - mXMin) * aFUnitScaleFactor,
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/compare/d5…
--
This project does not include diff previews in email notifications.
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/compare/d5…
You're receiving this email because of your account on gitlab.torproject.org.
ma1 pushed to branch mullvad-browser-115.11.0esr-13.0-1 at The Tor Project / Applications / Mullvad Browser
Commits:
50b53983 by Nuohan Li at 2024-05-09T13:04:13+02:00
Bug 1871109 - generateHash in Manifest.sys.mjs should use sha256 r=peterv, a=dmeehan
Differential Revision: https://phabricator.services.mozilla.com/D204928
- - - - -
7269657b by Jonathan Kew at 2024-05-09T13:04:14+02:00
Bug 1890204 - Ensure font entry's unitsPerEm and font extents are initialized when gfxFont is created. r=gfx-reviewers,lsalzman
This means that by the time we potentially call GetFontExtents() when drawing,
the extents fields are guaranteed to have been been initialized, and there's no
risk of the (read-only) access here racing with setting them in UnitsPerEm().
Differential Revision: https://phabricator.services.mozilla.com/D206920
- - - - -
b4147595 by Jonathan Kew at 2024-05-09T13:04:15+02:00
Bug 1893891 - Clear mSharedBlobData if blob creation failed. a=dmeehan
Original Revision: https://phabricator.services.mozilla.com/D208983
Differential Revision: https://phabricator.services.mozilla.com/D209209
- - - - -
5 changed files:
- dom/manifest/Manifest.sys.mjs
- dom/manifest/test/browser_Manifest_install.js
- gfx/thebes/gfxFont.cpp
- gfx/thebes/gfxFontEntry.cpp
- gfx/thebes/gfxFontEntry.h
Changes:
=====================================
dom/manifest/Manifest.sys.mjs
=====================================
@@ -29,11 +29,11 @@ ChromeUtils.defineESModuleGetters(lazy, {
* @note The generated hash is returned in base64 form. Mind the fact base64
* is case-sensitive if you are going to reuse this code.
*/
-function generateHash(aString) {
+function generateHash(aString, hashAlg) {
const cryptoHash = Cc["@mozilla.org/security/hash;1"].createInstance(
Ci.nsICryptoHash
);
- cryptoHash.init(Ci.nsICryptoHash.MD5);
+ cryptoHash.init(hashAlg);
const stringStream = Cc[
"@mozilla.org/io/string-input-stream;1"
].createInstance(Ci.nsIStringInputStream);
@@ -66,11 +66,39 @@ class Manifest {
this._manifestUrl = manifestUrl;
// The key for this is the manifests URL that is required to be unique.
// However arbitrary urls are not safe file paths so lets hash it.
- const fileName = generateHash(manifestUrl) + ".json";
- this._path = PathUtils.join(MANIFESTS_DIR, fileName);
+ const filename =
+ generateHash(manifestUrl, Ci.nsICryptoHash.SHA256) + ".json";
+ this._path = PathUtils.join(MANIFESTS_DIR, filename);
this.browser = browser;
}
+ /**
+ * See Bug 1871109
+ * This function is called at the beginning of initialize() to check if a given
+ * manifest has MD5 based filename, if so we remove it and migrate the content to
+ * a new file with SHA256 based name.
+ * This is done due to security concern, as MD5 is an outdated hashing algorithm and
+ * shouldn't be used anymore
+ */
+ async removeMD5BasedFilename() {
+ const filenameMD5 =
+ generateHash(this._manifestUrl, Ci.nsICryptoHash.MD5) + ".json";
+ const MD5Path = PathUtils.join(MANIFESTS_DIR, filenameMD5);
+ try {
+ await IOUtils.copy(MD5Path, this._path, { noOverwrite: true });
+ } catch (error) {
+ // we are ignoring the failures returned from copy as it should not stop us from
+ // installing a new manifest
+ }
+
+ // Remove the old MD5 based file unconditionally to ensure it's no longer used
+ try {
+ await IOUtils.remove(MD5Path);
+ } catch {
+ // ignore the error in case MD5 based file does not exist
+ }
+ }
+
get browser() {
return this._browser;
}
@@ -80,6 +108,7 @@ class Manifest {
}
async initialize() {
+ await this.removeMD5BasedFilename();
this._store = new lazy.JSONFile({ path: this._path, saveDelayMs: 100 });
await this._store.load();
}
=====================================
dom/manifest/test/browser_Manifest_install.js
=====================================
@@ -23,18 +23,59 @@ function makeTestURL() {
return url.href;
}
+function generateHash(aString, hashAlg) {
+ const cryptoHash = Cc["@mozilla.org/security/hash;1"].createInstance(
+ Ci.nsICryptoHash
+ );
+ cryptoHash.init(hashAlg);
+ const stringStream = Cc[
+ "@mozilla.org/io/string-input-stream;1"
+ ].createInstance(Ci.nsIStringInputStream);
+ stringStream.data = aString;
+ cryptoHash.updateFromStream(stringStream, -1);
+ // base64 allows the '/' char, but we can't use it for filenames.
+ return cryptoHash.finish(true).replace(/\//g, "-");
+}
+
+const MANIFESTS_DIR = PathUtils.join(PathUtils.profileDir, "manifests");
+
add_task(async function () {
const tabOptions = { gBrowser, url: makeTestURL() };
+ const filenameMD5 = generateHash(manifestUrl, Ci.nsICryptoHash.MD5) + ".json";
+ const filenameSHA =
+ generateHash(manifestUrl, Ci.nsICryptoHash.SHA256) + ".json";
+ const manifestMD5Path = PathUtils.join(MANIFESTS_DIR, filenameMD5);
+ const manifestSHAPath = PathUtils.join(MANIFESTS_DIR, filenameSHA);
+
await BrowserTestUtils.withNewTab(tabOptions, async function (browser) {
- let manifest = await Manifests.getManifest(browser, manifestUrl);
- is(manifest.installed, false, "We haven't installed this manifest yet");
+ let tmpManifest = await Manifests.getManifest(browser, manifestUrl);
+ is(tmpManifest.installed, false, "We haven't installed this manifest yet");
+
+ await tmpManifest.install();
+ // making sure the manifest is actually installed before proceeding
+ await tmpManifest._store._save();
+ await IOUtils.move(tmpManifest.path, manifestMD5Path);
+
+ let exists = await IOUtils.exists(tmpManifest.path);
+ is(
+ exists,
+ false,
+ "Manually moved manifest from SHA256 based path to MD5 based path"
+ );
+ Manifests.manifestObjs.delete(manifestUrl);
+
+ let manifest = await Manifests.getManifest(browser, manifestUrl);
await manifest.install(browser);
is(manifest.name, "hello World", "Manifest has correct name");
is(manifest.installed, true, "Manifest is installed");
is(manifest.url, manifestUrl, "has correct url");
is(manifest.browser, browser, "has correct browser");
+ is(manifest.path, manifestSHAPath, "has correct path");
+
+ exists = await IOUtils.exists(manifestMD5Path);
+ is(exists, false, "MD5 based manifest removed");
manifest = await Manifests.getManifest(browser, manifestUrl);
is(manifest.installed, true, "New instances are installed");
=====================================
gfx/thebes/gfxFont.cpp
=====================================
@@ -952,6 +952,10 @@ gfxFont::gfxFont(const RefPtr<UnscaledFont>& aUnscaledFont,
}
mKerningSet = HasFeatureSet(HB_TAG('k', 'e', 'r', 'n'), mKerningEnabled);
+
+ // Ensure the gfxFontEntry's unitsPerEm and extents fields are initialized,
+ // so that GetFontExtents can use them without risk of races.
+ Unused << mFontEntry->UnitsPerEm();
}
gfxFont::~gfxFont() {
=====================================
gfx/thebes/gfxFontEntry.cpp
=====================================
@@ -262,14 +262,22 @@ already_AddRefed<gfxFont> gfxFontEntry::FindOrMakeFont(
}
uint16_t gfxFontEntry::UnitsPerEm() {
+ {
+ AutoReadLock lock(mLock);
+ if (mUnitsPerEm) {
+ return mUnitsPerEm;
+ }
+ }
+
+ AutoTable headTable(this, TRUETYPE_TAG('h', 'e', 'a', 'd'));
+ AutoWriteLock lock(mLock);
+
if (!mUnitsPerEm) {
- AutoTable headTable(this, TRUETYPE_TAG('h', 'e', 'a', 'd'));
if (headTable) {
uint32_t len;
const HeadTable* head =
reinterpret_cast<const HeadTable*>(hb_blob_get_data(headTable, &len));
if (len >= sizeof(HeadTable)) {
- mUnitsPerEm = head->unitsPerEm;
if (int16_t(head->xMax) > int16_t(head->xMin) &&
int16_t(head->yMax) > int16_t(head->yMin)) {
mXMin = head->xMin;
@@ -277,6 +285,7 @@ uint16_t gfxFontEntry::UnitsPerEm() {
mXMax = head->xMax;
mYMax = head->yMax;
}
+ mUnitsPerEm = head->unitsPerEm;
}
}
@@ -286,12 +295,13 @@ uint16_t gfxFontEntry::UnitsPerEm() {
mUnitsPerEm = kInvalidUPEM;
}
}
+
return mUnitsPerEm;
}
bool gfxFontEntry::HasSVGGlyph(uint32_t aGlyphId) {
- NS_ASSERTION(mSVGInitialized,
- "SVG data has not yet been loaded. TryGetSVGData() first.");
+ MOZ_ASSERT(mSVGInitialized,
+ "SVG data has not yet been loaded. TryGetSVGData() first.");
return GetSVGGlyphs()->HasSVGGlyph(aGlyphId);
}
@@ -309,8 +319,8 @@ bool gfxFontEntry::GetSVGGlyphExtents(DrawTarget* aDrawTarget,
void gfxFontEntry::RenderSVGGlyph(gfxContext* aContext, uint32_t aGlyphId,
SVGContextPaint* aContextPaint) {
- NS_ASSERTION(mSVGInitialized,
- "SVG data has not yet been loaded. TryGetSVGData() first.");
+ MOZ_ASSERT(mSVGInitialized,
+ "SVG data has not yet been loaded. TryGetSVGData() first.");
GetSVGGlyphs()->RenderGlyph(aContext, aGlyphId, aContextPaint);
}
@@ -467,8 +477,9 @@ hb_blob_t* gfxFontEntry::FontTableHashEntry::ShareTableAndGetBlob(
HB_MEMORY_MODE_READONLY, mSharedBlobData, DeleteFontTableBlobData);
if (mBlob == hb_blob_get_empty()) {
// The FontTableBlobData was destroyed during hb_blob_create().
- // The (empty) blob is still be held in the hashtable with a strong
+ // The (empty) blob will still be held in the hashtable with a strong
// reference.
+ mSharedBlobData = nullptr;
return hb_blob_reference(mBlob);
}
=====================================
gfx/thebes/gfxFontEntry.h
=====================================
@@ -538,6 +538,9 @@ class gfxFontEntry {
mozilla::gfx::Rect GetFontExtents(float aFUnitScaleFactor) const {
// Flip the y-axis here to match the orientation of Gecko's coordinates.
+ // We don't need to take a lock here because the min/max fields are inert
+ // after initialization, and we make sure to initialize them at gfxFont-
+ // creation time.
return mozilla::gfx::Rect(float(mXMin) * aFUnitScaleFactor,
float(-mYMax) * aFUnitScaleFactor,
float(mXMax - mXMin) * aFUnitScaleFactor,
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/compare/d3…
--
This project does not include diff previews in email notifications.
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/compare/d3…
You're receiving this email because of your account on gitlab.torproject.org.
ma1 pushed to branch base-browser-115.11.0esr-13.0-1 at The Tor Project / Applications / Tor Browser
Commits:
ac2c9355 by Nuohan Li at 2024-05-09T13:01:34+02:00
Bug 1871109 - generateHash in Manifest.sys.mjs should use sha256 r=peterv, a=dmeehan
Differential Revision: https://phabricator.services.mozilla.com/D204928
- - - - -
9d85032c by Jonathan Kew at 2024-05-09T13:01:39+02:00
Bug 1890204 - Ensure font entry's unitsPerEm and font extents are initialized when gfxFont is created. r=gfx-reviewers,lsalzman
This means that by the time we potentially call GetFontExtents() when drawing,
the extents fields are guaranteed to have been been initialized, and there's no
risk of the (read-only) access here racing with setting them in UnitsPerEm().
Differential Revision: https://phabricator.services.mozilla.com/D206920
- - - - -
8a728aa8 by Jonathan Kew at 2024-05-09T13:01:40+02:00
Bug 1893891 - Clear mSharedBlobData if blob creation failed. a=dmeehan
Original Revision: https://phabricator.services.mozilla.com/D208983
Differential Revision: https://phabricator.services.mozilla.com/D209209
- - - - -
5 changed files:
- dom/manifest/Manifest.sys.mjs
- dom/manifest/test/browser_Manifest_install.js
- gfx/thebes/gfxFont.cpp
- gfx/thebes/gfxFontEntry.cpp
- gfx/thebes/gfxFontEntry.h
Changes:
=====================================
dom/manifest/Manifest.sys.mjs
=====================================
@@ -29,11 +29,11 @@ ChromeUtils.defineESModuleGetters(lazy, {
* @note The generated hash is returned in base64 form. Mind the fact base64
* is case-sensitive if you are going to reuse this code.
*/
-function generateHash(aString) {
+function generateHash(aString, hashAlg) {
const cryptoHash = Cc["@mozilla.org/security/hash;1"].createInstance(
Ci.nsICryptoHash
);
- cryptoHash.init(Ci.nsICryptoHash.MD5);
+ cryptoHash.init(hashAlg);
const stringStream = Cc[
"@mozilla.org/io/string-input-stream;1"
].createInstance(Ci.nsIStringInputStream);
@@ -66,11 +66,39 @@ class Manifest {
this._manifestUrl = manifestUrl;
// The key for this is the manifests URL that is required to be unique.
// However arbitrary urls are not safe file paths so lets hash it.
- const fileName = generateHash(manifestUrl) + ".json";
- this._path = PathUtils.join(MANIFESTS_DIR, fileName);
+ const filename =
+ generateHash(manifestUrl, Ci.nsICryptoHash.SHA256) + ".json";
+ this._path = PathUtils.join(MANIFESTS_DIR, filename);
this.browser = browser;
}
+ /**
+ * See Bug 1871109
+ * This function is called at the beginning of initialize() to check if a given
+ * manifest has MD5 based filename, if so we remove it and migrate the content to
+ * a new file with SHA256 based name.
+ * This is done due to security concern, as MD5 is an outdated hashing algorithm and
+ * shouldn't be used anymore
+ */
+ async removeMD5BasedFilename() {
+ const filenameMD5 =
+ generateHash(this._manifestUrl, Ci.nsICryptoHash.MD5) + ".json";
+ const MD5Path = PathUtils.join(MANIFESTS_DIR, filenameMD5);
+ try {
+ await IOUtils.copy(MD5Path, this._path, { noOverwrite: true });
+ } catch (error) {
+ // we are ignoring the failures returned from copy as it should not stop us from
+ // installing a new manifest
+ }
+
+ // Remove the old MD5 based file unconditionally to ensure it's no longer used
+ try {
+ await IOUtils.remove(MD5Path);
+ } catch {
+ // ignore the error in case MD5 based file does not exist
+ }
+ }
+
get browser() {
return this._browser;
}
@@ -80,6 +108,7 @@ class Manifest {
}
async initialize() {
+ await this.removeMD5BasedFilename();
this._store = new lazy.JSONFile({ path: this._path, saveDelayMs: 100 });
await this._store.load();
}
=====================================
dom/manifest/test/browser_Manifest_install.js
=====================================
@@ -23,18 +23,59 @@ function makeTestURL() {
return url.href;
}
+function generateHash(aString, hashAlg) {
+ const cryptoHash = Cc["@mozilla.org/security/hash;1"].createInstance(
+ Ci.nsICryptoHash
+ );
+ cryptoHash.init(hashAlg);
+ const stringStream = Cc[
+ "@mozilla.org/io/string-input-stream;1"
+ ].createInstance(Ci.nsIStringInputStream);
+ stringStream.data = aString;
+ cryptoHash.updateFromStream(stringStream, -1);
+ // base64 allows the '/' char, but we can't use it for filenames.
+ return cryptoHash.finish(true).replace(/\//g, "-");
+}
+
+const MANIFESTS_DIR = PathUtils.join(PathUtils.profileDir, "manifests");
+
add_task(async function () {
const tabOptions = { gBrowser, url: makeTestURL() };
+ const filenameMD5 = generateHash(manifestUrl, Ci.nsICryptoHash.MD5) + ".json";
+ const filenameSHA =
+ generateHash(manifestUrl, Ci.nsICryptoHash.SHA256) + ".json";
+ const manifestMD5Path = PathUtils.join(MANIFESTS_DIR, filenameMD5);
+ const manifestSHAPath = PathUtils.join(MANIFESTS_DIR, filenameSHA);
+
await BrowserTestUtils.withNewTab(tabOptions, async function (browser) {
- let manifest = await Manifests.getManifest(browser, manifestUrl);
- is(manifest.installed, false, "We haven't installed this manifest yet");
+ let tmpManifest = await Manifests.getManifest(browser, manifestUrl);
+ is(tmpManifest.installed, false, "We haven't installed this manifest yet");
+
+ await tmpManifest.install();
+ // making sure the manifest is actually installed before proceeding
+ await tmpManifest._store._save();
+ await IOUtils.move(tmpManifest.path, manifestMD5Path);
+
+ let exists = await IOUtils.exists(tmpManifest.path);
+ is(
+ exists,
+ false,
+ "Manually moved manifest from SHA256 based path to MD5 based path"
+ );
+ Manifests.manifestObjs.delete(manifestUrl);
+
+ let manifest = await Manifests.getManifest(browser, manifestUrl);
await manifest.install(browser);
is(manifest.name, "hello World", "Manifest has correct name");
is(manifest.installed, true, "Manifest is installed");
is(manifest.url, manifestUrl, "has correct url");
is(manifest.browser, browser, "has correct browser");
+ is(manifest.path, manifestSHAPath, "has correct path");
+
+ exists = await IOUtils.exists(manifestMD5Path);
+ is(exists, false, "MD5 based manifest removed");
manifest = await Manifests.getManifest(browser, manifestUrl);
is(manifest.installed, true, "New instances are installed");
=====================================
gfx/thebes/gfxFont.cpp
=====================================
@@ -952,6 +952,10 @@ gfxFont::gfxFont(const RefPtr<UnscaledFont>& aUnscaledFont,
}
mKerningSet = HasFeatureSet(HB_TAG('k', 'e', 'r', 'n'), mKerningEnabled);
+
+ // Ensure the gfxFontEntry's unitsPerEm and extents fields are initialized,
+ // so that GetFontExtents can use them without risk of races.
+ Unused << mFontEntry->UnitsPerEm();
}
gfxFont::~gfxFont() {
=====================================
gfx/thebes/gfxFontEntry.cpp
=====================================
@@ -262,14 +262,22 @@ already_AddRefed<gfxFont> gfxFontEntry::FindOrMakeFont(
}
uint16_t gfxFontEntry::UnitsPerEm() {
+ {
+ AutoReadLock lock(mLock);
+ if (mUnitsPerEm) {
+ return mUnitsPerEm;
+ }
+ }
+
+ AutoTable headTable(this, TRUETYPE_TAG('h', 'e', 'a', 'd'));
+ AutoWriteLock lock(mLock);
+
if (!mUnitsPerEm) {
- AutoTable headTable(this, TRUETYPE_TAG('h', 'e', 'a', 'd'));
if (headTable) {
uint32_t len;
const HeadTable* head =
reinterpret_cast<const HeadTable*>(hb_blob_get_data(headTable, &len));
if (len >= sizeof(HeadTable)) {
- mUnitsPerEm = head->unitsPerEm;
if (int16_t(head->xMax) > int16_t(head->xMin) &&
int16_t(head->yMax) > int16_t(head->yMin)) {
mXMin = head->xMin;
@@ -277,6 +285,7 @@ uint16_t gfxFontEntry::UnitsPerEm() {
mXMax = head->xMax;
mYMax = head->yMax;
}
+ mUnitsPerEm = head->unitsPerEm;
}
}
@@ -286,12 +295,13 @@ uint16_t gfxFontEntry::UnitsPerEm() {
mUnitsPerEm = kInvalidUPEM;
}
}
+
return mUnitsPerEm;
}
bool gfxFontEntry::HasSVGGlyph(uint32_t aGlyphId) {
- NS_ASSERTION(mSVGInitialized,
- "SVG data has not yet been loaded. TryGetSVGData() first.");
+ MOZ_ASSERT(mSVGInitialized,
+ "SVG data has not yet been loaded. TryGetSVGData() first.");
return GetSVGGlyphs()->HasSVGGlyph(aGlyphId);
}
@@ -309,8 +319,8 @@ bool gfxFontEntry::GetSVGGlyphExtents(DrawTarget* aDrawTarget,
void gfxFontEntry::RenderSVGGlyph(gfxContext* aContext, uint32_t aGlyphId,
SVGContextPaint* aContextPaint) {
- NS_ASSERTION(mSVGInitialized,
- "SVG data has not yet been loaded. TryGetSVGData() first.");
+ MOZ_ASSERT(mSVGInitialized,
+ "SVG data has not yet been loaded. TryGetSVGData() first.");
GetSVGGlyphs()->RenderGlyph(aContext, aGlyphId, aContextPaint);
}
@@ -467,8 +477,9 @@ hb_blob_t* gfxFontEntry::FontTableHashEntry::ShareTableAndGetBlob(
HB_MEMORY_MODE_READONLY, mSharedBlobData, DeleteFontTableBlobData);
if (mBlob == hb_blob_get_empty()) {
// The FontTableBlobData was destroyed during hb_blob_create().
- // The (empty) blob is still be held in the hashtable with a strong
+ // The (empty) blob will still be held in the hashtable with a strong
// reference.
+ mSharedBlobData = nullptr;
return hb_blob_reference(mBlob);
}
=====================================
gfx/thebes/gfxFontEntry.h
=====================================
@@ -538,6 +538,9 @@ class gfxFontEntry {
mozilla::gfx::Rect GetFontExtents(float aFUnitScaleFactor) const {
// Flip the y-axis here to match the orientation of Gecko's coordinates.
+ // We don't need to take a lock here because the min/max fields are inert
+ // after initialization, and we make sure to initialize them at gfxFont-
+ // creation time.
return mozilla::gfx::Rect(float(mXMin) * aFUnitScaleFactor,
float(-mYMax) * aFUnitScaleFactor,
float(mXMax - mXMin) * aFUnitScaleFactor,
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/5cc512…
--
This project does not include diff previews in email notifications.
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/5cc512…
You're receiving this email because of your account on gitlab.torproject.org.
ma1 pushed to branch tor-browser-115.11.0esr-13.0-1 at The Tor Project / Applications / Tor Browser
Commits:
a52dc31b by Nuohan Li at 2024-05-09T10:55:04+00:00
Bug 1871109 - generateHash in Manifest.sys.mjs should use sha256 r=peterv, a=dmeehan
Differential Revision: https://phabricator.services.mozilla.com/D204928
- - - - -
88affd4a by Jonathan Kew at 2024-05-09T10:55:04+00:00
Bug 1890204 - Ensure font entry's unitsPerEm and font extents are initialized when gfxFont is created. r=gfx-reviewers,lsalzman
This means that by the time we potentially call GetFontExtents() when drawing,
the extents fields are guaranteed to have been been initialized, and there's no
risk of the (read-only) access here racing with setting them in UnitsPerEm().
Differential Revision: https://phabricator.services.mozilla.com/D206920
- - - - -
fc0ee191 by Jonathan Kew at 2024-05-09T10:55:04+00:00
Bug 1893891 - Clear mSharedBlobData if blob creation failed. a=dmeehan
Original Revision: https://phabricator.services.mozilla.com/D208983
Differential Revision: https://phabricator.services.mozilla.com/D209209
- - - - -
5 changed files:
- dom/manifest/Manifest.sys.mjs
- dom/manifest/test/browser_Manifest_install.js
- gfx/thebes/gfxFont.cpp
- gfx/thebes/gfxFontEntry.cpp
- gfx/thebes/gfxFontEntry.h
Changes:
=====================================
dom/manifest/Manifest.sys.mjs
=====================================
@@ -29,11 +29,11 @@ ChromeUtils.defineESModuleGetters(lazy, {
* @note The generated hash is returned in base64 form. Mind the fact base64
* is case-sensitive if you are going to reuse this code.
*/
-function generateHash(aString) {
+function generateHash(aString, hashAlg) {
const cryptoHash = Cc["@mozilla.org/security/hash;1"].createInstance(
Ci.nsICryptoHash
);
- cryptoHash.init(Ci.nsICryptoHash.MD5);
+ cryptoHash.init(hashAlg);
const stringStream = Cc[
"@mozilla.org/io/string-input-stream;1"
].createInstance(Ci.nsIStringInputStream);
@@ -66,11 +66,39 @@ class Manifest {
this._manifestUrl = manifestUrl;
// The key for this is the manifests URL that is required to be unique.
// However arbitrary urls are not safe file paths so lets hash it.
- const fileName = generateHash(manifestUrl) + ".json";
- this._path = PathUtils.join(MANIFESTS_DIR, fileName);
+ const filename =
+ generateHash(manifestUrl, Ci.nsICryptoHash.SHA256) + ".json";
+ this._path = PathUtils.join(MANIFESTS_DIR, filename);
this.browser = browser;
}
+ /**
+ * See Bug 1871109
+ * This function is called at the beginning of initialize() to check if a given
+ * manifest has MD5 based filename, if so we remove it and migrate the content to
+ * a new file with SHA256 based name.
+ * This is done due to security concern, as MD5 is an outdated hashing algorithm and
+ * shouldn't be used anymore
+ */
+ async removeMD5BasedFilename() {
+ const filenameMD5 =
+ generateHash(this._manifestUrl, Ci.nsICryptoHash.MD5) + ".json";
+ const MD5Path = PathUtils.join(MANIFESTS_DIR, filenameMD5);
+ try {
+ await IOUtils.copy(MD5Path, this._path, { noOverwrite: true });
+ } catch (error) {
+ // we are ignoring the failures returned from copy as it should not stop us from
+ // installing a new manifest
+ }
+
+ // Remove the old MD5 based file unconditionally to ensure it's no longer used
+ try {
+ await IOUtils.remove(MD5Path);
+ } catch {
+ // ignore the error in case MD5 based file does not exist
+ }
+ }
+
get browser() {
return this._browser;
}
@@ -80,6 +108,7 @@ class Manifest {
}
async initialize() {
+ await this.removeMD5BasedFilename();
this._store = new lazy.JSONFile({ path: this._path, saveDelayMs: 100 });
await this._store.load();
}
=====================================
dom/manifest/test/browser_Manifest_install.js
=====================================
@@ -23,18 +23,59 @@ function makeTestURL() {
return url.href;
}
+function generateHash(aString, hashAlg) {
+ const cryptoHash = Cc["@mozilla.org/security/hash;1"].createInstance(
+ Ci.nsICryptoHash
+ );
+ cryptoHash.init(hashAlg);
+ const stringStream = Cc[
+ "@mozilla.org/io/string-input-stream;1"
+ ].createInstance(Ci.nsIStringInputStream);
+ stringStream.data = aString;
+ cryptoHash.updateFromStream(stringStream, -1);
+ // base64 allows the '/' char, but we can't use it for filenames.
+ return cryptoHash.finish(true).replace(/\//g, "-");
+}
+
+const MANIFESTS_DIR = PathUtils.join(PathUtils.profileDir, "manifests");
+
add_task(async function () {
const tabOptions = { gBrowser, url: makeTestURL() };
+ const filenameMD5 = generateHash(manifestUrl, Ci.nsICryptoHash.MD5) + ".json";
+ const filenameSHA =
+ generateHash(manifestUrl, Ci.nsICryptoHash.SHA256) + ".json";
+ const manifestMD5Path = PathUtils.join(MANIFESTS_DIR, filenameMD5);
+ const manifestSHAPath = PathUtils.join(MANIFESTS_DIR, filenameSHA);
+
await BrowserTestUtils.withNewTab(tabOptions, async function (browser) {
- let manifest = await Manifests.getManifest(browser, manifestUrl);
- is(manifest.installed, false, "We haven't installed this manifest yet");
+ let tmpManifest = await Manifests.getManifest(browser, manifestUrl);
+ is(tmpManifest.installed, false, "We haven't installed this manifest yet");
+
+ await tmpManifest.install();
+ // making sure the manifest is actually installed before proceeding
+ await tmpManifest._store._save();
+ await IOUtils.move(tmpManifest.path, manifestMD5Path);
+
+ let exists = await IOUtils.exists(tmpManifest.path);
+ is(
+ exists,
+ false,
+ "Manually moved manifest from SHA256 based path to MD5 based path"
+ );
+ Manifests.manifestObjs.delete(manifestUrl);
+
+ let manifest = await Manifests.getManifest(browser, manifestUrl);
await manifest.install(browser);
is(manifest.name, "hello World", "Manifest has correct name");
is(manifest.installed, true, "Manifest is installed");
is(manifest.url, manifestUrl, "has correct url");
is(manifest.browser, browser, "has correct browser");
+ is(manifest.path, manifestSHAPath, "has correct path");
+
+ exists = await IOUtils.exists(manifestMD5Path);
+ is(exists, false, "MD5 based manifest removed");
manifest = await Manifests.getManifest(browser, manifestUrl);
is(manifest.installed, true, "New instances are installed");
=====================================
gfx/thebes/gfxFont.cpp
=====================================
@@ -952,6 +952,10 @@ gfxFont::gfxFont(const RefPtr<UnscaledFont>& aUnscaledFont,
}
mKerningSet = HasFeatureSet(HB_TAG('k', 'e', 'r', 'n'), mKerningEnabled);
+
+ // Ensure the gfxFontEntry's unitsPerEm and extents fields are initialized,
+ // so that GetFontExtents can use them without risk of races.
+ Unused << mFontEntry->UnitsPerEm();
}
gfxFont::~gfxFont() {
=====================================
gfx/thebes/gfxFontEntry.cpp
=====================================
@@ -262,14 +262,22 @@ already_AddRefed<gfxFont> gfxFontEntry::FindOrMakeFont(
}
uint16_t gfxFontEntry::UnitsPerEm() {
+ {
+ AutoReadLock lock(mLock);
+ if (mUnitsPerEm) {
+ return mUnitsPerEm;
+ }
+ }
+
+ AutoTable headTable(this, TRUETYPE_TAG('h', 'e', 'a', 'd'));
+ AutoWriteLock lock(mLock);
+
if (!mUnitsPerEm) {
- AutoTable headTable(this, TRUETYPE_TAG('h', 'e', 'a', 'd'));
if (headTable) {
uint32_t len;
const HeadTable* head =
reinterpret_cast<const HeadTable*>(hb_blob_get_data(headTable, &len));
if (len >= sizeof(HeadTable)) {
- mUnitsPerEm = head->unitsPerEm;
if (int16_t(head->xMax) > int16_t(head->xMin) &&
int16_t(head->yMax) > int16_t(head->yMin)) {
mXMin = head->xMin;
@@ -277,6 +285,7 @@ uint16_t gfxFontEntry::UnitsPerEm() {
mXMax = head->xMax;
mYMax = head->yMax;
}
+ mUnitsPerEm = head->unitsPerEm;
}
}
@@ -286,12 +295,13 @@ uint16_t gfxFontEntry::UnitsPerEm() {
mUnitsPerEm = kInvalidUPEM;
}
}
+
return mUnitsPerEm;
}
bool gfxFontEntry::HasSVGGlyph(uint32_t aGlyphId) {
- NS_ASSERTION(mSVGInitialized,
- "SVG data has not yet been loaded. TryGetSVGData() first.");
+ MOZ_ASSERT(mSVGInitialized,
+ "SVG data has not yet been loaded. TryGetSVGData() first.");
return GetSVGGlyphs()->HasSVGGlyph(aGlyphId);
}
@@ -309,8 +319,8 @@ bool gfxFontEntry::GetSVGGlyphExtents(DrawTarget* aDrawTarget,
void gfxFontEntry::RenderSVGGlyph(gfxContext* aContext, uint32_t aGlyphId,
SVGContextPaint* aContextPaint) {
- NS_ASSERTION(mSVGInitialized,
- "SVG data has not yet been loaded. TryGetSVGData() first.");
+ MOZ_ASSERT(mSVGInitialized,
+ "SVG data has not yet been loaded. TryGetSVGData() first.");
GetSVGGlyphs()->RenderGlyph(aContext, aGlyphId, aContextPaint);
}
@@ -467,8 +477,9 @@ hb_blob_t* gfxFontEntry::FontTableHashEntry::ShareTableAndGetBlob(
HB_MEMORY_MODE_READONLY, mSharedBlobData, DeleteFontTableBlobData);
if (mBlob == hb_blob_get_empty()) {
// The FontTableBlobData was destroyed during hb_blob_create().
- // The (empty) blob is still be held in the hashtable with a strong
+ // The (empty) blob will still be held in the hashtable with a strong
// reference.
+ mSharedBlobData = nullptr;
return hb_blob_reference(mBlob);
}
=====================================
gfx/thebes/gfxFontEntry.h
=====================================
@@ -538,6 +538,9 @@ class gfxFontEntry {
mozilla::gfx::Rect GetFontExtents(float aFUnitScaleFactor) const {
// Flip the y-axis here to match the orientation of Gecko's coordinates.
+ // We don't need to take a lock here because the min/max fields are inert
+ // after initialization, and we make sure to initialize them at gfxFont-
+ // creation time.
return mozilla::gfx::Rect(float(mXMin) * aFUnitScaleFactor,
float(-mYMax) * aFUnitScaleFactor,
float(mXMax - mXMin) * aFUnitScaleFactor,
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/10474e…
--
This project does not include diff previews in email notifications.
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/10474e…
You're receiving this email because of your account on gitlab.torproject.org.