richard pushed to branch tor-browser-115.9.0esr-13.5-1 at The Tor Project / Applications / Tor Browser
Commits: 4255b354 by Pier Angelo Vendrame at 2024-04-08T19:55:24+00:00 Bug 41901: Hardcode normalized FontSubstitutes.
Windows has a system to set font aliases through the registry. This allows some customization that could be used as a fingerprinting vector. Moreover, this mechanism is used by Windows itself, and different SKUs might have different default FontSubstitutes.
- - - - -
4 changed files:
- gfx/thebes/StandardFonts-win10.inc - gfx/thebes/gfxDWriteFontList.cpp - gfx/thebes/gfxDWriteFontList.h - gfx/thebes/gfxGDIFontList.cpp
Changes:
===================================== gfx/thebes/StandardFonts-win10.inc ===================================== @@ -199,3 +199,68 @@ static const char* kLangPackFonts[] = { // "Rockwell Nova", // Pan-European Supplemental Fonts - EXCLUDED // "Verdana Pro", // Pan-European Supplemental Fonts - EXCLUDED }; + +struct FontSubstitute { + const char *substituteName; + const char *actualFontName; +}; + +static const FontSubstitute kFontSubstitutes[] = { + // Common substitutions + {"Arabic Transparent", "Arial"}, + {"Arabic Transparent Bold", "Arial Bold"}, + {"Arial Baltic", "Arial"}, + {"Arial CE", "Arial"}, + {"Arial CYR", "Arial"}, + {"Arial Greek", "Arial"}, + {"Arial TUR", "Arial"}, + {"Courier New Baltic", "Courier New"}, + {"Courier New CE", "Courier New"}, + {"Courier New CYR", "Courier New"}, + {"Courier New Greek", "Courier New"}, + {"Courier New TUR", "Courier New"}, + {"Helv", "MS Sans Serif"}, + {"Helvetica", "Arial"}, + {"MS Shell Dlg 2", "Tahoma"}, + {"Tahoma Armenian", "Tahoma"}, + {"Times", "Times New Roman"}, + {"Times New Roman Baltic", "Times New Roman"}, + {"Times New Roman CE", "Times New Roman"}, + {"Times New Roman CYR", "Times New Roman"}, + {"Times New Roman Greek", "Times New Roman"}, + {"Times New Roman TUR", "Times New Roman"}, + {"Tms Rmn", "MS Serif"}, + // Common, except Japanese (which uses MS UI Gothic, instead) + {"MS Shell Dlg", "Microsoft Sans Serif"}, + // Arabic + {"Arial (Arabic)", "Arial"}, + {"Courier New (Arabic)", "Courier New"}, + {"Times New Roman (Arabic)", "Times New Roman"}, + // Cyrillic + Greek + {"Courier", "Courier New"}, + // Greek + {"Fixedsys Greek", "Fixedsys"}, + {"MS Serif Greek", "MS Serif"}, + {"MS Sans Serif Greek", "MS Sans Serif"}, + {"Small Fonts Greek", "Small Fonts"}, + {"System Greek", "System"}, + // Hebrew + {"Arial (Hebrew)", "Arial"}, + {"Courier New (Hebrew)", "Courier New"}, + {"David Transparent", "David"}, + {"Fixed Miriam Transparent", "Miriam Fixed"}, + {"Miriam Transparent", "Miriam"}, + {"Rod Transparent", "Rod"}, + {"Times New Roman (Hebrew)", "Times New Roman"}, + // Japanese + {"標準明朝", "MS 明朝"}, + {"標準ゴシック", "MS ゴシック"}, + {"ゴシック", "MS ゴシック"}, + {"ゴシック", "MS ゴシック"}, + {"クーリエ", "Courier"}, + {"タイムズロマン", "Times New Roman"}, + {"ヘルベチカ", "Arial"}, + // Simplified Chinese + {"FangSong_GB2312", "FangSong"}, + {"KaiTi_GB2312", "KaiTi"}, +};
===================================== gfx/thebes/gfxDWriteFontList.cpp ===================================== @@ -1923,6 +1923,20 @@ static void RemoveCharsetFromFontSubstitute(nsACString& aName) { #define MAX_VALUE_DATA 512
nsresult gfxDWriteFontList::GetFontSubstitutes() { + if (nsContentUtils::ShouldResistFingerprinting( + "Ignore any fingerprintable user font customization and normalize " + "font substitutes across different Windows SKUs.", + RFPTarget::Unknown)) { + for (const FontSubstitute& fs : kFontSubstitutes) { + nsAutoCString substituteName(fs.substituteName); + nsAutoCString actualFontName(fs.actualFontName); + BuildKeyNameFromFontName(substituteName); + BuildKeyNameFromFontName(actualFontName); + AddSubstitute(substituteName, actualFontName); + } + return NS_OK; + } + HKEY hKey; DWORD i, rv, lenAlias, lenActual, valueType; WCHAR aliasName[MAX_VALUE_NAME]; @@ -1957,39 +1971,46 @@ nsresult gfxDWriteFontList::GetFontSubstitutes() { BuildKeyNameFromFontName(substituteName); RemoveCharsetFromFontSubstitute(actualFontName); BuildKeyNameFromFontName(actualFontName); - if (SharedFontList()) { - // Skip substitution if the original font is available, unless the option - // to apply substitutions unconditionally is enabled. - if (!StaticPrefs::gfx_windows_font_substitutes_always_AtStartup()) { - // Font substitutions are recorded for the canonical family names; we - // don't need FindFamily to consider localized aliases when searching. - if (SharedFontList()->FindFamily(substituteName, - /*aPrimaryNameOnly*/ true)) { - continue; - } - } - if (SharedFontList()->FindFamily(actualFontName, + AddSubstitute(substituteName, actualFontName); + } + + return NS_OK; +} + +void gfxDWriteFontList::AddSubstitute(const nsCString& substituteName, + const nsCString& actualFontName) { + if (SharedFontList()) { + // Skip substitution if the original font is available, unless the + // option to apply substitutions unconditionally is enabled. + if (!StaticPrefs::gfx_windows_font_substitutes_always_AtStartup()) { + // Font substitutions are recorded for the canonical family names; + // we don't need FindFamily to consider localized aliases when + // searching. + if (SharedFontList()->FindFamily(substituteName, /*aPrimaryNameOnly*/ true)) { - mSubstitutions.InsertOrUpdate(substituteName, - MakeUnique<nsCString>(actualFontName)); - } else if (mSubstitutions.Get(actualFontName)) { - mSubstitutions.InsertOrUpdate( - substituteName, - MakeUnique<nsCString>(*mSubstitutions.Get(actualFontName))); - } else { - mNonExistingFonts.AppendElement(substituteName); + return; } + } + if (SharedFontList()->FindFamily(actualFontName, + /*aPrimaryNameOnly*/ true)) { + mSubstitutions.InsertOrUpdate(substituteName, + MakeUnique<nsCString>(actualFontName)); + } else if (mSubstitutions.Get(actualFontName)) { + mSubstitutions.InsertOrUpdate( + substituteName, + MakeUnique<nsCString>(*mSubstitutions.Get(actualFontName))); } else { - gfxFontFamily* ff; - if (!actualFontName.IsEmpty() && - (ff = mFontFamilies.GetWeak(actualFontName))) { - mFontSubstitutes.InsertOrUpdate(substituteName, RefPtr{ff}); - } else { - mNonExistingFonts.AppendElement(substituteName); - } + mNonExistingFonts.AppendElement(substituteName); + } + } else { + gfxFontFamily* ff; + if (!actualFontName.IsEmpty() && + (ff = mFontFamilies.GetWeak(actualFontName))) { + mFontSubstitutes.InsertOrUpdate(substituteName, RefPtr{ff}); + } else { + mNonExistingFonts.AppendElement(substituteName); } } - return NS_OK; }
struct FontSubstitution {
===================================== gfx/thebes/gfxDWriteFontList.h ===================================== @@ -466,6 +466,9 @@ class gfxDWriteFontList final : public gfxPlatformFontList { const nsTArray<nsCString>* aForceClassicFams = nullptr) MOZ_REQUIRES(mLock);
+ void AddSubstitute(const nsCString& substituteName, + const nsCString& actualFontName); + #ifdef MOZ_BUNDLED_FONTS already_AddRefed<IDWriteFontCollection> CreateBundledFontsCollection( IDWriteFactory* aFactory);
===================================== gfx/thebes/gfxGDIFontList.cpp ===================================== @@ -31,6 +31,10 @@ #include "mozilla/StaticPrefs_gfx.h" #include "mozilla/Telemetry.h"
+#include "nsContentUtils.h" + +#include "StandardFonts-win10.inc" + #include <usp10.h>
using namespace mozilla; @@ -50,6 +54,10 @@ static __inline void BuildKeyNameFromFontName(nsAString& aName) { if (aName.Length() >= LF_FACESIZE) aName.Truncate(LF_FACESIZE - 1); ToLowerCase(aName); } +static __inline void BuildKeyNameFromFontName(nsACString& aName) { + if (aName.Length() >= LF_FACESIZE) aName.Truncate(LF_FACESIZE - 1); + ToLowerCase(aName); +}
// Implementation of gfxPlatformFontList for Win32 GDI, // using GDI font enumeration APIs to get the list of fonts @@ -529,6 +537,26 @@ static void RemoveCharsetFromFontSubstitute(nsAString& aName) { #define MAX_VALUE_DATA 512
nsresult gfxGDIFontList::GetFontSubstitutes() { + if (nsContentUtils::ShouldResistFingerprinting( + "Ignore any fingerprintable user font customization and normalize " + "font substitutes across different Windows SKUs.", + RFPTarget::Unknown)) { + for (const FontSubstitute& fs : kFontSubstitutes) { + nsAutoCString substituteName(fs.substituteName); + nsAutoCString actualFontName(fs.actualFontName); + BuildKeyNameFromFontName(substituteName); + BuildKeyNameFromFontName(actualFontName); + gfxFontFamily* ff; + if (!actualFontName.IsEmpty() && + (ff = mFontFamilies.GetWeak(actualFontName))) { + mFontSubstitutes.InsertOrUpdate(substituteName, RefPtr{ff}); + } else { + mNonExistingFonts.AppendElement(substituteName); + } + } + return NS_OK; + } + HKEY hKey; DWORD i, rv, lenAlias, lenActual, valueType; WCHAR aliasName[MAX_VALUE_NAME];
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/4255b354...