Fix potential memory access violation issues
LOGFONT docs clearly states `lfFaceName` member is a null-terminated string of length not longer than LF_FACESIZE, including trailing null. This patch covers two cases at once: 1. If family name is longer than LF_FACESIZE - 1, it would be truncated and terminated with null, to prevent memory access beyond the LOGFONT instance. 2. If family name is a fromRawData QString, we don't assume it is null-terminated either and guarantee trailing null ourselves. Change-Id: I8f607efc7d0901537a4179e36cc51df94203f08d Reviewed-by: Friedemann Kleint <Friedemann.Kleint@theqtcompany.com> Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@theqtcompany.com>bb10
parent
5b11e43e9f
commit
e9dbaa328e
|
|
@ -923,7 +923,11 @@ public:
|
|||
static const char keyC[] = "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes";
|
||||
const QString familyName = QString::fromWCharArray(lf.lfFaceName);
|
||||
const QString nameSubstitute = QSettings(QLatin1String(keyC), QSettings::NativeFormat).value(familyName, familyName).toString();
|
||||
memcpy(lf.lfFaceName, nameSubstitute.utf16(), sizeof(wchar_t) * qMin(nameSubstitute.length() + 1, LF_FACESIZE));
|
||||
if (nameSubstitute != familyName) {
|
||||
const int nameSubstituteLength = qMin(nameSubstitute.length(), LF_FACESIZE - 1);
|
||||
memcpy(lf.lfFaceName, nameSubstitute.utf16(), nameSubstituteLength * sizeof(wchar_t));
|
||||
lf.lfFaceName[nameSubstituteLength] = 0;
|
||||
}
|
||||
|
||||
ComPtr<IDWriteFont> dwriteFont;
|
||||
HRESULT hr = QWindowsDirect2DContext::instance()->dwriteGdiInterop()->CreateFontFromLOGFONT(&lf, &dwriteFont);
|
||||
|
|
|
|||
|
|
@ -794,7 +794,7 @@ QString getEnglishName(const QString &familyName)
|
|||
HDC hdc = GetDC( 0 );
|
||||
LOGFONT lf;
|
||||
memset(&lf, 0, sizeof(LOGFONT));
|
||||
memcpy(lf.lfFaceName, familyName.utf16(), qMin(LF_FACESIZE, familyName.length()) * sizeof(wchar_t));
|
||||
memcpy(lf.lfFaceName, familyName.utf16(), qMin(familyName.length(), LF_FACESIZE - 1) * sizeof(wchar_t));
|
||||
lf.lfCharSet = DEFAULT_CHARSET;
|
||||
HFONT hfont = CreateFontIndirect(&lf);
|
||||
|
||||
|
|
@ -958,14 +958,9 @@ static int QT_WIN_CALLBACK storeFontSub(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textm
|
|||
|
||||
HDC dummy = GetDC(0);
|
||||
LOGFONT lf;
|
||||
memset(&lf, 0, sizeof(LOGFONT));
|
||||
lf.lfCharSet = DEFAULT_CHARSET;
|
||||
if (wcslen(f->elfLogFont.lfFaceName) >= LF_FACESIZE) {
|
||||
qWarning("%s: Unable to enumerate family '%s'.",
|
||||
__FUNCTION__, qPrintable(QString::fromWCharArray(f->elfLogFont.lfFaceName)));
|
||||
return 1;
|
||||
}
|
||||
wmemcpy(lf.lfFaceName, f->elfLogFont.lfFaceName,
|
||||
wcslen(f->elfLogFont.lfFaceName) + 1);
|
||||
memcpy(lf.lfFaceName, f->elfLogFont.lfFaceName, LF_FACESIZE * sizeof(wchar_t));
|
||||
lf.lfPitchAndFamily = 0;
|
||||
EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)storeFont,
|
||||
(LPARAM)namesSetIn, 0);
|
||||
|
|
@ -1001,20 +996,21 @@ void QWindowsFontDatabase::populate(const QString &family)
|
|||
|
||||
HDC dummy = GetDC(0);
|
||||
LOGFONT lf;
|
||||
memset(&lf, 0, sizeof(LOGFONT));
|
||||
lf.lfCharSet = DEFAULT_CHARSET;
|
||||
if (family.size() >= LF_FACESIZE) {
|
||||
qWarning("%s: Unable to enumerate family '%s'.",
|
||||
__FUNCTION__, qPrintable(family));
|
||||
return;
|
||||
}
|
||||
wmemcpy(lf.lfFaceName, reinterpret_cast<const wchar_t*>(family.utf16()),
|
||||
family.size() + 1);
|
||||
|
||||
lf.lfPitchAndFamily = 0;
|
||||
|
||||
if (family.isEmpty()) {
|
||||
EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)storeFontSub,
|
||||
(LPARAM)&m_families, 0);
|
||||
} else {
|
||||
memcpy(lf.lfFaceName, family.utf16(), family.size() * sizeof(wchar_t));
|
||||
EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)storeFont,
|
||||
(LPARAM)&m_families, 0);
|
||||
}
|
||||
|
|
@ -1350,7 +1346,7 @@ QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData,
|
|||
HDC hdc = GetDC(0);
|
||||
LOGFONT lf;
|
||||
memset(&lf, 0, sizeof(LOGFONT));
|
||||
memcpy(lf.lfFaceName, familyName.utf16(), sizeof(wchar_t) * qMin(LF_FACESIZE, familyName.size()));
|
||||
memcpy(lf.lfFaceName, familyName.utf16(), sizeof(wchar_t) * qMin(LF_FACESIZE - 1, familyName.size()));
|
||||
lf.lfCharSet = DEFAULT_CHARSET;
|
||||
HFONT hfont = CreateFontIndirect(&lf);
|
||||
HGDIOBJ oldobj = SelectObject(hdc, hfont);
|
||||
|
|
@ -1575,6 +1571,10 @@ LOGFONT QWindowsFontDatabase::fontDefToLOGFONT(const QFontDef &request)
|
|||
lf.lfPitchAndFamily = DEFAULT_PITCH | hint;
|
||||
|
||||
QString fam = request.family;
|
||||
if (fam.size() >= LF_FACESIZE) {
|
||||
qCritical("%s: Family name '%s' is too long.", __FUNCTION__, qPrintable(fam));
|
||||
fam.truncate(LF_FACESIZE - 1);
|
||||
}
|
||||
|
||||
if (fam.isEmpty())
|
||||
fam = QStringLiteral("MS Sans Serif");
|
||||
|
|
@ -1586,7 +1586,7 @@ LOGFONT QWindowsFontDatabase::fontDefToLOGFONT(const QFontDef &request)
|
|||
if (fam == QLatin1String("Courier") && !(request.styleStrategy & QFont::PreferBitmap))
|
||||
fam = QStringLiteral("Courier New");
|
||||
|
||||
memcpy(lf.lfFaceName, fam.utf16(), sizeof(wchar_t) * qMin(fam.length() + 1, 32)); // 32 = Windows hard-coded
|
||||
memcpy(lf.lfFaceName, fam.utf16(), fam.size() * sizeof(wchar_t));
|
||||
|
||||
return lf;
|
||||
}
|
||||
|
|
@ -1767,9 +1767,13 @@ QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request,
|
|||
// turns out okay)
|
||||
useDirectWrite = false;
|
||||
if (initDirectWrite(data.data())) {
|
||||
const QString nameSubstitute = QWindowsFontEngineDirectWrite::fontNameSubstitute(QString::fromWCharArray(lf.lfFaceName));
|
||||
memcpy(lf.lfFaceName, nameSubstitute.utf16(),
|
||||
sizeof(wchar_t) * qMin(nameSubstitute.length() + 1, LF_FACESIZE));
|
||||
const QString fam = QString::fromWCharArray(lf.lfFaceName);
|
||||
const QString nameSubstitute = QWindowsFontEngineDirectWrite::fontNameSubstitute(fam);
|
||||
if (nameSubstitute != fam) {
|
||||
const int nameSubstituteLength = qMin(nameSubstitute.length(), LF_FACESIZE - 1);
|
||||
memcpy(lf.lfFaceName, nameSubstitute.utf16(), nameSubstituteLength * sizeof(wchar_t));
|
||||
lf.lfFaceName[nameSubstituteLength] = 0;
|
||||
}
|
||||
|
||||
HRESULT hr = data->directWriteGdiInterop->CreateFontFromLOGFONT(
|
||||
&lf,
|
||||
|
|
|
|||
|
|
@ -369,14 +369,9 @@ static int QT_WIN_CALLBACK storeFontSub(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textm
|
|||
|
||||
HDC dummy = GetDC(0);
|
||||
LOGFONT lf;
|
||||
memset(&lf, 0, sizeof(LOGFONT));
|
||||
lf.lfCharSet = DEFAULT_CHARSET;
|
||||
if (wcslen(f->elfLogFont.lfFaceName) >= LF_FACESIZE) {
|
||||
qWarning("%s: Unable to enumerate family '%s'.",
|
||||
__FUNCTION__, qPrintable(QString::fromWCharArray(f->elfLogFont.lfFaceName)));
|
||||
return 1;
|
||||
}
|
||||
wmemcpy(lf.lfFaceName, f->elfLogFont.lfFaceName,
|
||||
wcslen(f->elfLogFont.lfFaceName) + 1);
|
||||
memcpy(lf.lfFaceName, f->elfLogFont.lfFaceName, LF_FACESIZE * sizeof(wchar_t));
|
||||
lf.lfPitchAndFamily = 0;
|
||||
EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)storeFont,
|
||||
(LPARAM)namesSetIn, 0);
|
||||
|
|
@ -411,20 +406,21 @@ void QWindowsFontDatabaseFT::populate(const QString &family)
|
|||
|
||||
HDC dummy = GetDC(0);
|
||||
LOGFONT lf;
|
||||
memset(&lf, 0, sizeof(LOGFONT));
|
||||
lf.lfCharSet = DEFAULT_CHARSET;
|
||||
if (family.size() >= LF_FACESIZE) {
|
||||
qWarning("%s: Unable to enumerate family '%s'.",
|
||||
__FUNCTION__, qPrintable(family));
|
||||
return;
|
||||
}
|
||||
wmemcpy(lf.lfFaceName, reinterpret_cast<const wchar_t*>(family.utf16()),
|
||||
family.size() + 1);
|
||||
|
||||
lf.lfPitchAndFamily = 0;
|
||||
|
||||
if (family.isEmpty()) {
|
||||
EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)storeFontSub,
|
||||
(LPARAM)&m_families, 0);
|
||||
} else {
|
||||
memcpy(lf.lfFaceName, family.utf16(), family.size() * sizeof(wchar_t));
|
||||
EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)storeFont,
|
||||
(LPARAM)&m_families, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1329,13 +1329,18 @@ QFontEngine *QWindowsMultiFontEngine::loadEngine(int at)
|
|||
}
|
||||
|
||||
const QString fam = fallbackFamilyAt(at - 1);
|
||||
memcpy(lf.lfFaceName, fam.utf16(), sizeof(wchar_t) * qMin(fam.length() + 1, 32)); // 32 = Windows hard-coded
|
||||
const int faceNameLength = qMin(fam.length(), LF_FACESIZE - 1);
|
||||
memcpy(lf.lfFaceName, fam.utf16(), faceNameLength * sizeof(wchar_t));
|
||||
lf.lfFaceName[faceNameLength] = 0;
|
||||
|
||||
#ifndef QT_NO_DIRECTWRITE
|
||||
if (fontEngine->type() == QFontEngine::DirectWrite) {
|
||||
const QString nameSubstitute = QWindowsFontEngineDirectWrite::fontNameSubstitute(QString::fromWCharArray(lf.lfFaceName));
|
||||
memcpy(lf.lfFaceName, nameSubstitute.utf16(),
|
||||
sizeof(wchar_t) * qMin(nameSubstitute.length() + 1, LF_FACESIZE));
|
||||
const QString nameSubstitute = QWindowsFontEngineDirectWrite::fontNameSubstitute(fam);
|
||||
if (nameSubstitute != fam) {
|
||||
const int nameSubstituteLength = qMin(nameSubstitute.length(), LF_FACESIZE - 1);
|
||||
memcpy(lf.lfFaceName, nameSubstitute.utf16(), nameSubstituteLength * sizeof(wchar_t));
|
||||
lf.lfFaceName[nameSubstituteLength] = 0;
|
||||
}
|
||||
|
||||
IDWriteFont *directWriteFont = 0;
|
||||
HRESULT hr = data->directWriteGdiInterop->CreateFontFromLOGFONT(&lf, &directWriteFont);
|
||||
|
|
|
|||
Loading…
Reference in New Issue