mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-01 00:32:11 +00:00
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:
parent
9d63ca55ff
commit
0ef2fbbdc6
@ -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(
|
||||
|
Loading…
Reference in New Issue
Block a user