Bug 1529794 - Protect DirectWrite usage in gfxDWriteFontList::CreateFontEntry with an exception handler. r=lsalzman

Differential Revision: https://phabricator.services.mozilla.com/D165944
This commit is contained in:
Jonathan Kew 2023-01-04 18:26:21 +00:00
parent 9d63ca55ff
commit 0ef2fbbdc6

View File

@ -1046,89 +1046,100 @@ gfxFontEntry* gfxDWriteFontList::CreateFontEntry(
bool foundExpectedFamily = false;
const nsCString& familyName =
aFamily->DisplayName().AsString(SharedFontList());
if (aFamily->Index() < collection->GetFontFamilyCount()) {
HRESULT hr =
collection->GetFontFamily(aFamily->Index(), getter_AddRefs(family));
// Check that the family name is what we expected; if not, fall back to
// search by name. It's sad we have to do this, but it is possible for
// Windows to have given different versions of the system font collection
// to the parent and child processes.
if (SUCCEEDED(hr) && family) {
RefPtr<IDWriteLocalizedStrings> names;
hr = family->GetFamilyNames(getter_AddRefs(names));
if (SUCCEEDED(hr) && names) {
nsAutoCString name;
if (GetEnglishOrFirstName(name, names)) {
foundExpectedFamily = name.Equals(familyName);
// The DirectWrite calls here might throw exceptions, e.g. in case of disk
// errors when trying to read the font file.
MOZ_SEH_TRY {
if (aFamily->Index() < collection->GetFontFamilyCount()) {
HRESULT hr =
collection->GetFontFamily(aFamily->Index(), getter_AddRefs(family));
// Check that the family name is what we expected; if not, fall back to
// search by name. It's sad we have to do this, but it is possible for
// Windows to have given different versions of the system font collection
// to the parent and child processes.
if (SUCCEEDED(hr) && family) {
RefPtr<IDWriteLocalizedStrings> names;
hr = family->GetFamilyNames(getter_AddRefs(names));
if (SUCCEEDED(hr) && names) {
nsAutoCString name;
if (GetEnglishOrFirstName(name, names)) {
foundExpectedFamily = name.Equals(familyName);
}
}
}
}
}
if (!foundExpectedFamily) {
// Try to get family by name instead of index (to deal with the case of
// collection mismatch).
UINT32 index;
BOOL exists;
NS_ConvertUTF8toUTF16 name16(familyName);
HRESULT hr = collection->FindFamilyName(
reinterpret_cast<const WCHAR*>(name16.BeginReading()), &index, &exists);
if (FAILED(hr) || !exists || index == UINT_MAX ||
FAILED(collection->GetFontFamily(index, getter_AddRefs(family))) ||
!family) {
if (!foundExpectedFamily) {
// Try to get family by name instead of index (to deal with the case of
// collection mismatch).
UINT32 index;
BOOL exists;
NS_ConvertUTF8toUTF16 name16(familyName);
HRESULT hr = collection->FindFamilyName(
reinterpret_cast<const WCHAR*>(name16.BeginReading()), &index,
&exists);
if (FAILED(hr) || !exists || index == UINT_MAX ||
FAILED(collection->GetFontFamily(index, getter_AddRefs(family))) ||
!family) {
return nullptr;
}
}
// Retrieve the required face by index within the family.
RefPtr<IDWriteFont> font;
if (FAILED(family->GetFont(aFace->mIndex, getter_AddRefs(font))) || !font) {
return nullptr;
}
}
// Retrieve the required face by index within the family.
RefPtr<IDWriteFont> font;
if (FAILED(family->GetFont(aFace->mIndex, getter_AddRefs(font))) || !font) {
return nullptr;
}
// Retrieve the psName from the font, so we can check we've found the
// expected face.
nsAutoCString psName;
if (FAILED(GetDirectWriteFaceName(font, PSNAME_ID, psName))) {
RefPtr<IDWriteFontFace> dwFontFace;
if (SUCCEEDED(font->CreateFontFace(getter_AddRefs(dwFontFace)))) {
GetPostScriptNameFromNameTable(dwFontFace, psName);
// Retrieve the psName from the font, so we can check we've found the
// expected face.
nsAutoCString psName;
if (FAILED(GetDirectWriteFaceName(font, PSNAME_ID, psName))) {
RefPtr<IDWriteFontFace> dwFontFace;
if (SUCCEEDED(font->CreateFontFace(getter_AddRefs(dwFontFace)))) {
GetPostScriptNameFromNameTable(dwFontFace, psName);
}
}
}
// If it doesn't match, DirectWrite must have shuffled the order of faces
// returned for the family; search by name as a fallback.
nsCString faceName = aFace->mDescriptor.AsString(SharedFontList());
if (psName != faceName) {
gfxWarning() << "Face name mismatch for index " << aFace->mIndex
<< " in family " << familyName.get() << ": expected "
<< faceName.get() << ", found " << psName.get();
for (uint32_t i = 0; i < family->GetFontCount(); ++i) {
if (i == aFace->mIndex) {
continue; // this was the face we already tried
}
if (FAILED(family->GetFont(i, getter_AddRefs(font))) || !font) {
return nullptr; // this font family is broken!
}
if (FAILED(GetDirectWriteFaceName(font, PSNAME_ID, psName))) {
RefPtr<IDWriteFontFace> dwFontFace;
if (SUCCEEDED(font->CreateFontFace(getter_AddRefs(dwFontFace)))) {
GetPostScriptNameFromNameTable(dwFontFace, psName);
// If it doesn't match, DirectWrite must have shuffled the order of faces
// returned for the family; search by name as a fallback.
nsCString faceName = aFace->mDescriptor.AsString(SharedFontList());
if (psName != faceName) {
gfxWarning() << "Face name mismatch for index " << aFace->mIndex
<< " in family " << familyName.get() << ": expected "
<< faceName.get() << ", found " << psName.get();
for (uint32_t i = 0; i < family->GetFontCount(); ++i) {
if (i == aFace->mIndex) {
continue; // this was the face we already tried
}
if (FAILED(family->GetFont(i, getter_AddRefs(font))) || !font) {
return nullptr; // this font family is broken!
}
if (FAILED(GetDirectWriteFaceName(font, PSNAME_ID, psName))) {
RefPtr<IDWriteFontFace> dwFontFace;
if (SUCCEEDED(font->CreateFontFace(getter_AddRefs(dwFontFace)))) {
GetPostScriptNameFromNameTable(dwFontFace, psName);
}
}
if (psName == faceName) {
break;
}
}
if (psName == faceName) {
break;
}
}
}
if (psName != faceName) {
return nullptr;
}
if (psName != faceName) {
return nullptr;
}
auto fe = new gfxDWriteFontEntry(faceName, font, !aFamily->IsBundled());
fe->InitializeFrom(aFace, aFamily);
fe->mForceGDIClassic = aFamily->IsForceClassic();
fe->mMayUseGDIAccess = aFamily->IsSimple();
return fe;
auto fe = new gfxDWriteFontEntry(faceName, font, !aFamily->IsBundled());
fe->InitializeFrom(aFace, aFamily);
fe->mForceGDIClassic = aFamily->IsForceClassic();
fe->mMayUseGDIAccess = aFamily->IsSimple();
return fe;
}
MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
gfxCriticalNote << "Exception occurred while creating font entry for "
<< familyName.get();
}
return nullptr;
}
FontVisibility gfxDWriteFontList::GetVisibilityForFamily(