Bug 1455848 - validate access to DWrite font files in WR and output helpful log messages on failure. r=jrmuizel

This commit is contained in:
Lee Salzman 2018-12-11 15:58:02 -05:00
parent c13d380a26
commit f7066e0fb7
6 changed files with 128 additions and 1 deletions

View File

@ -302,6 +302,23 @@ class Log {
} }
return *this; return *this;
} }
#ifdef WIN32
Log& operator<<(const wchar_t aWStr[]) {
if (MOZ_UNLIKELY(LogIt())) {
int wLen = (int)wcslen(aWStr);
std::vector<char> str;
int n = WideCharToMultiByte(0, 0, aWStr, wLen, nullptr, 0, nullptr,
nullptr);
if (n > 0) {
std::vector<char> str(n+1);
WideCharToMultiByte(0, 0, aWStr, wLen, str.data(), n+1, nullptr,
nullptr);
mMessage << str.data();
}
}
return *this;
}
#endif
Log& operator<<(bool aBool) { Log& operator<<(bool aBool) {
if (MOZ_UNLIKELY(LogIt())) { if (MOZ_UNLIKELY(LogIt())) {
mMessage << (aBool ? "true" : "false"); mMessage << (aBool ? "true" : "false");

View File

@ -385,6 +385,56 @@ bool UnscaledFontDWrite::GetWRFontDescriptor(WRFontDescriptorOutput aCb,
return false; return false;
} }
// FIXME: Debugging kluge for bug 1455848. Remove once debugged!
UINT32 numFiles;
hr = mFontFace->GetFiles(&numFiles, nullptr);
if (FAILED(hr) || !numFiles) {
return false;
}
std::vector<RefPtr<IDWriteFontFile>> files;
files.resize(numFiles);
hr = mFontFace->GetFiles(&numFiles, getter_AddRefs(files[0]));
if (FAILED(hr)) {
return false;
}
MOZ_ASSERT(familyName.size() >= 1 && familyName.back() == 0);
for(auto& file : files) {
const void* key;
UINT32 keySize;
hr = file->GetReferenceKey(&key, &keySize);
if (FAILED(hr)) {
return false;
}
RefPtr<IDWriteFontFileLoader> loader;
hr = file->GetLoader(getter_AddRefs(loader));
if (FAILED(hr)) {
return false;
}
RefPtr<IDWriteLocalFontFileLoader> localLoader;
loader->QueryInterface(__uuidof(IDWriteLocalFontFileLoader), (void**)getter_AddRefs(localLoader));
if (!localLoader) {
return false;
}
UINT32 pathLen;
hr = localLoader->GetFilePathLengthFromKey(key, keySize, &pathLen);
if (FAILED(hr)) {
return false;
}
size_t offset = familyName.size();
familyName.resize(offset + pathLen + 1);
hr = localLoader->GetFilePathFromKey(key, keySize, &familyName[offset], pathLen + 1);
if (FAILED(hr)) {
return false;
}
MOZ_ASSERT(familyName.back() == 0);
DWORD attribs = GetFileAttributesW(&familyName[offset]);
if (attribs == INVALID_FILE_ATTRIBUTES) {
gfxCriticalNote << "sending font family \"" << &familyName[0]
<< "\" with invalid file \"" << &familyName[offset]
<< "\"";
}
}
// The style information that identifies the font can be encoded easily in // The style information that identifies the font can be encoded easily in
// less than 32 bits. Since the index is needed for font descriptors, only // less than 32 bits. Since the index is needed for font descriptors, only
// the family name and style information, pass along the style in the index // the family name and style information, pass along the style in the index
@ -392,7 +442,7 @@ bool UnscaledFontDWrite::GetWRFontDescriptor(WRFontDescriptorOutput aCb,
// the data payload. // the data payload.
uint32_t index = weight | (stretch << 16) | (style << 24); uint32_t index = weight | (stretch << 16) | (style << 24);
aCb(reinterpret_cast<const uint8_t*>(familyName.data()), aCb(reinterpret_cast<const uint8_t*>(familyName.data()),
(familyName.size() - 1) * sizeof(WCHAR), index, aBaton); familyName.size() * sizeof(WCHAR), index, aBaton);
return true; return true;
} }

View File

@ -82,6 +82,9 @@ parent:
async FlushApzRepaints(); async FlushApzRepaints();
sync GetAPZTestData() returns (APZTestData data); sync GetAPZTestData() returns (APZTestData data);
// Debugging routine for bug 1455848.
async ValidateFontDescriptor(uint8_t[] desc);
async Shutdown(); async Shutdown();
sync ShutdownSync(); sync ShutdownSync();
child: child:

View File

@ -225,6 +225,14 @@ static void WriteFontDescriptor(const uint8_t* aData, uint32_t aLength,
*sink->mFontKey = sink->mWrBridge->GetNextFontKey(); *sink->mFontKey = sink->mWrBridge->GetNextFontKey();
#ifdef XP_WIN
// FIXME: Debugging kluge for bug 1455848. Remove once debugged!
nsTArray<uint8_t> data;
data.AppendElements(aData, aLength);
sink->mWrBridge->SendValidateFontDescriptor(data);
aLength = uint32_t(wcsnlen_s((const wchar_t*)aData, aLength / sizeof(wchar_t)) * sizeof(wchar_t));
#endif
sink->mResources->AddFontDescriptor( sink->mResources->AddFontDescriptor(
*sink->mFontKey, Range<uint8_t>(const_cast<uint8_t*>(aData), aLength), *sink->mFontKey, Range<uint8_t>(const_cast<uint8_t*>(aData), aLength),
aIndex); aIndex);

View File

@ -35,6 +35,10 @@
#include "mozilla/webrender/RenderThread.h" #include "mozilla/webrender/RenderThread.h"
#include "mozilla/widget/CompositorWidget.h" #include "mozilla/widget/CompositorWidget.h"
#ifdef XP_WIN
#include "dwrite.h"
#endif
using mozilla::Telemetry::LABELS_CONTENT_FRAME_TIME_REASON; using mozilla::Telemetry::LABELS_CONTENT_FRAME_TIME_REASON;
#ifdef MOZ_GECKO_PROFILER #ifdef MOZ_GECKO_PROFILER
@ -697,6 +701,48 @@ void WebRenderBridgeParent::ObserveSharedSurfaceRelease(
} }
} }
// Debugging kluge for bug 1455848. Remove once debugged!
mozilla::ipc::IPCResult WebRenderBridgeParent::RecvValidateFontDescriptor(
nsTArray<uint8_t>&& aData) {
if (mDestroyed) {
return IPC_OK();
}
#ifdef XP_WIN
nsTArray<uint8_t> data(aData);
wchar_t* family = (wchar_t*)data.Elements();
size_t remaining = data.Length() / sizeof(wchar_t);
size_t familyLength = wcsnlen_s(family, remaining);
MOZ_ASSERT(familyLength < remaining && family[familyLength] == 0);
remaining -= familyLength + 1;
wchar_t* files = family + familyLength + 1;
BOOL exists = FALSE;
if (RefPtr<IDWriteFontCollection> systemFonts = Factory::GetDWriteSystemFonts()) {
UINT32 idx;
systemFonts->FindFamilyName(family, &idx, &exists);
}
if (!remaining) {
gfxCriticalNote << (exists ? "found" : "MISSING")
<< " font family \"" << family
<< "\" has no files!";
}
while (remaining > 0) {
size_t fileLength = wcsnlen_s(files, remaining);
MOZ_ASSERT(fileLength < remaining && files[fileLength] == 0);
DWORD attribs = GetFileAttributesW(files);
if (!exists || attribs == INVALID_FILE_ATTRIBUTES) {
gfxCriticalNote << (exists ? "found" : "MISSING")
<< " font family \"" << family
<< "\" has " << (attribs == INVALID_FILE_ATTRIBUTES ? "INVALID" : "valid")
<< " file \"" << files
<< "\"";
}
remaining -= fileLength + 1;
files += fileLength + 1;
}
#endif
return IPC_OK();
}
mozilla::ipc::IPCResult WebRenderBridgeParent::RecvUpdateResources( mozilla::ipc::IPCResult WebRenderBridgeParent::RecvUpdateResources(
nsTArray<OpUpdateResource>&& aResourceUpdates, nsTArray<OpUpdateResource>&& aResourceUpdates,
nsTArray<RefCountedShmem>&& aSmallShmems, nsTArray<RefCountedShmem>&& aSmallShmems,

View File

@ -123,6 +123,9 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
nsTArray<WebRenderParentCommand>&& commands) override; nsTArray<WebRenderParentCommand>&& commands) override;
mozilla::ipc::IPCResult RecvGetSnapshot(PTextureParent* aTexture) override; mozilla::ipc::IPCResult RecvGetSnapshot(PTextureParent* aTexture) override;
mozilla::ipc::IPCResult RecvValidateFontDescriptor(
nsTArray<uint8_t>&& aData) override;
mozilla::ipc::IPCResult RecvSetLayersObserverEpoch( mozilla::ipc::IPCResult RecvSetLayersObserverEpoch(
const LayersObserverEpoch& aChildEpoch) override; const LayersObserverEpoch& aChildEpoch) override;