[WIN32SS][NTGDI] Avoid allocation of zero size in NtGdiGetGlyphIndicesW (#1577)

In NtGdiGetGlyphIndicesW function, allocation of zero size had caused fatal failures.
Avoid allocation of zero size in ExAllocatePoolWithTag calls. Optimize for cwc == 0. CORE-12825
This commit is contained in:
Katayama Hirofumi MZ 2019-05-27 16:52:45 +09:00 committed by GitHub
parent ccd95b9880
commit c52b8288d1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -6890,37 +6890,32 @@ NtGdiGetGlyphIndicesW(
PWSTR Safepwc = NULL; PWSTR Safepwc = NULL;
LPCWSTR UnSafepwc = pwc; LPCWSTR UnSafepwc = pwc;
LPWORD UnSafepgi = pgi; LPWORD UnSafepgi = pgi;
FT_Face Face;
TT_OS2 *pOS2;
/* Check for integer overflow */ if (cwc < 0)
if (cwc & 0x80000000) // (INT_MAX + 1) == INT_MIN {
DPRINT1("cwc < 0\n");
return GDI_ERROR; return GDI_ERROR;
}
if (!UnSafepwc && !UnSafepgi) if (!UnSafepwc && !UnSafepgi && cwc > 0)
return cwc; {
DPRINT1("!UnSafepwc && !UnSafepgi && cwc > 0\n");
return GDI_ERROR;
}
if (!UnSafepwc || !UnSafepgi) if (!UnSafepwc != !UnSafepgi)
{ {
DPRINT1("UnSafepwc == %p, UnSafepgi = %p\n", UnSafepwc, UnSafepgi); DPRINT1("UnSafepwc == %p, UnSafepgi = %p\n", UnSafepwc, UnSafepgi);
return GDI_ERROR; return GDI_ERROR;
} }
// TODO: Special undocumented case! /* Get FontGDI */
if (!pwc && !pgi && (cwc == 0))
{
DPRINT1("ERR: NtGdiGetGlyphIndicesW with (!pwc && !pgi && (cwc == 0)) is UNIMPLEMENTED!\n");
return 0;
}
// FIXME: This is a hack!! (triggered by e.g. Word 2010). See CORE-12825
if (cwc == 0)
{
DPRINT1("ERR: NtGdiGetGlyphIndicesW with (cwc == 0) is UNIMPLEMENTED!\n");
return GDI_ERROR;
}
dc = DC_LockDc(hdc); dc = DC_LockDc(hdc);
if (!dc) if (!dc)
{ {
DPRINT1("!DC_LockDC\n");
return GDI_ERROR; return GDI_ERROR;
} }
pdcattr = dc->pdcattr; pdcattr = dc->pdcattr;
@ -6929,29 +6924,43 @@ NtGdiGetGlyphIndicesW(
DC_UnlockDc(dc); DC_UnlockDc(dc);
if (!TextObj) if (!TextObj)
{ {
DPRINT1("!TextObj\n");
return GDI_ERROR; return GDI_ERROR;
} }
FontGDI = ObjToGDI(TextObj->Font, FONT); FontGDI = ObjToGDI(TextObj->Font, FONT);
TEXTOBJ_UnlockText(TextObj); TEXTOBJ_UnlockText(TextObj);
if (cwc == 0)
{
if (!UnSafepwc && !UnSafepgi)
{
Face = FontGDI->SharedFace->Face;
return Face->num_glyphs;
}
else
{
Status = STATUS_UNSUCCESSFUL;
goto ErrorRet;
}
}
Buffer = ExAllocatePoolWithTag(PagedPool, cwc * sizeof(WORD), GDITAG_TEXT); Buffer = ExAllocatePoolWithTag(PagedPool, cwc * sizeof(WORD), GDITAG_TEXT);
if (!Buffer) if (!Buffer)
{ {
DPRINT1("ExAllocatePoolWithTag\n");
return GDI_ERROR; return GDI_ERROR;
} }
/* Get DefChar */
if (iMode & GGI_MARK_NONEXISTING_GLYPHS) if (iMode & GGI_MARK_NONEXISTING_GLYPHS)
{ {
DefChar = 0xffff; DefChar = 0xffff;
} }
else else
{ {
FT_Face Face = FontGDI->SharedFace->Face; Face = FontGDI->SharedFace->Face;
if (FT_IS_SFNT(Face)) if (FT_IS_SFNT(Face))
{ {
TT_OS2 *pOS2;
IntLockFreeType(); IntLockFreeType();
pOS2 = FT_Get_Sfnt_Table(Face, ft_sfnt_os2); pOS2 = FT_Get_Sfnt_Table(Face, ft_sfnt_os2);
DefChar = (pOS2->usDefaultChar ? get_glyph_index(Face, pOS2->usDefaultChar) : 0); DefChar = (pOS2->usDefaultChar ? get_glyph_index(Face, pOS2->usDefaultChar) : 0);
@ -6960,10 +6969,17 @@ NtGdiGetGlyphIndicesW(
else else
{ {
Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL); Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
if (!Size)
{
Status = STATUS_UNSUCCESSFUL;
DPRINT1("!Size\n");
goto ErrorRet;
}
potm = ExAllocatePoolWithTag(PagedPool, Size, GDITAG_TEXT); potm = ExAllocatePoolWithTag(PagedPool, Size, GDITAG_TEXT);
if (!potm) if (!potm)
{ {
cwc = GDI_ERROR; Status = STATUS_INSUFFICIENT_RESOURCES;
DPRINT1("!potm\n");
goto ErrorRet; goto ErrorRet;
} }
Size = IntGetOutlineTextMetrics(FontGDI, Size, potm); Size = IntGetOutlineTextMetrics(FontGDI, Size, potm);
@ -6973,12 +6989,13 @@ NtGdiGetGlyphIndicesW(
} }
} }
/* Allocate for Safepwc */
pwcSize = cwc * sizeof(WCHAR); pwcSize = cwc * sizeof(WCHAR);
Safepwc = ExAllocatePoolWithTag(PagedPool, pwcSize, GDITAG_TEXT); Safepwc = ExAllocatePoolWithTag(PagedPool, pwcSize, GDITAG_TEXT);
if (!Safepwc) if (!Safepwc)
{ {
Status = STATUS_NO_MEMORY; Status = STATUS_NO_MEMORY;
DPRINT1("!Safepwc\n");
goto ErrorRet; goto ErrorRet;
} }
@ -6993,10 +7010,14 @@ NtGdiGetGlyphIndicesW(
} }
_SEH2_END; _SEH2_END;
if (!NT_SUCCESS(Status)) goto ErrorRet; if (!NT_SUCCESS(Status))
{
DPRINT1("Status: %08lX\n", Status);
goto ErrorRet;
}
/* Get glyph indeces */
IntLockFreeType(); IntLockFreeType();
for (i = 0; i < cwc; i++) for (i = 0; i < cwc; i++)
{ {
Buffer[i] = get_glyph_index(FontGDI->SharedFace->Face, Safepwc[i]); Buffer[i] = get_glyph_index(FontGDI->SharedFace->Face, Safepwc[i]);
@ -7005,7 +7026,6 @@ NtGdiGetGlyphIndicesW(
Buffer[i] = DefChar; Buffer[i] = DefChar;
} }
} }
IntUnLockFreeType(); IntUnLockFreeType();
_SEH2_TRY _SEH2_TRY
@ -7020,12 +7040,18 @@ NtGdiGetGlyphIndicesW(
_SEH2_END; _SEH2_END;
ErrorRet: ErrorRet:
if (Buffer != NULL)
{
ExFreePoolWithTag(Buffer, GDITAG_TEXT); ExFreePoolWithTag(Buffer, GDITAG_TEXT);
}
if (Safepwc != NULL) if (Safepwc != NULL)
{ {
ExFreePoolWithTag(Safepwc, GDITAG_TEXT); ExFreePoolWithTag(Safepwc, GDITAG_TEXT);
} }
if (NT_SUCCESS(Status)) return cwc;
if (NT_SUCCESS(Status))
return cwc;
return GDI_ERROR; return GDI_ERROR;
} }