Author: tkreuzer Date: Tue May 10 10:16:10 2011 New Revision: 51662 URL: http://svn.reactos.org/svn/reactos?rev=51662&view=rev Log: [GDI FONT DRIVER] - Fix size of the inverse lookup table - Add more pointer checks to FtfdInitKerningPairs - sort the FD_KERNINGPAIR array
Modified: branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/font.c branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/tttables.c Modified: branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/font.c URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/font.c?rev=51662&r1=51661&r2=51662&view=diff ============================================================================== --- branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/font.c [iso-8859-1] (original) +++ branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/font.c [iso-8859-1] Tue May 10 10:16:10 2011 @@ -268,7 +268,8 @@ TRACE("FtfdInitGlyphSet()\n"); /* Allocate an array of WCHARs */ - pwcReverseTable = EngAllocMem(0, pface->ftface->num_glyphs, 'dftF'); + cjSize = pface->cGlyphs * sizeof(WCHAR); + pwcReverseTable = EngAllocMem(0, cjSize, 'dftF'); if (!pwcReverseTable) { WARN("EngAllocMem() failed.\n"); @@ -303,6 +304,7 @@ for (i = 0, cRuns = 0; i < pface->cMappings && index; i++) { /* Create an entry in the reverse lookup table */ + ASSERT(index < pface->cGlyphs); pwcReverseTable[index] = wcCurrent; /* Use index as glyph handle */ @@ -355,6 +357,8 @@ return FMT_UNKNOWN; } +static +ULONG FtfdGetFileFormat( PFTFD_FILE pfile) { Modified: branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/tttables.c URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/tttables.c?rev=51662&r1=51661&r2=51662&view=diff ============================================================================== --- branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/tttables.c [iso-8859-1] (original) +++ branches/GSoC_2011/GdiFontDriver/drivers/video/font/ftfd/tttables.c [iso-8859-1] Tue May 10 10:16:10 2011 @@ -407,6 +407,21 @@ return nPairs; } +INT +__cdecl +CompareKernPair( + FD_KERNINGPAIR *pkp1, + FD_KERNINGPAIR *pkp2) +{ + ULONG ul1, ul2; + ul1 = pkp1->wcFirst + 65536 * pkp1->wcSecond; + ul2 = pkp2->wcFirst + 65536 * pkp2->wcSecond; + if (ul1 < ul2) return -1; + if (ul1 > ul2) return 1; + return 0; +} + + VOID NTAPI FtfdInitKerningPairs( @@ -415,33 +430,65 @@ PFTFD_FILE pfile = pface->pfile; PTT_KERNING_TABLE pKernTable; PTT_KERNING_SUBTABLE pSubTable; - ULONG i, j, cPairs = 0; + ULONG cjSize, i, j, cPairs = 0; FD_KERNINGPAIR *pKernPair; HGLYPH hgLeft, hgRight; - -__debugbreak(); + USHORT nTables; + ULONG_PTR ulLastAddress; + +//__debugbreak(); /* Get the kern table for the face */ pKernTable = FtfdFindTrueTypeTable(pfile->pvView, - pfile->cjView, - pface->iFace, - 'nrek', - NULL); - - if (!pKernTable || pKernTable->usVersion != 0) - { - TRACE("Couldn't find kerning table\n"); + pfile->cjView, + pface->iFace, + 'nrek', + &cjSize); + + if (!pKernTable || cjSize < sizeof(TT_KERNING_TABLE) || + pKernTable->usVersion != 0) + { + TRACE("Couldn't find a valid kerning table\n"); return; } - // FIXME: do an overflow check + nTables = GETW(&pKernTable->nTables); + ulLastAddress = (ULONG_PTR)pKernTable + cjSize; + + /* Loop all subtables */ pSubTable = &pKernTable->subtable; - for (i = 0; i < pKernTable->nTables; i++) - { - /* Only type 0 is interesting */ + for (i = 0; i < nTables; i++) + { + /* Check if the subtable is accessible */ + if ((ULONG_PTR)pSubTable + sizeof(TT_KERNING_SUBTABLE) > ulLastAddress) + { + __debugbreak(); + return; + } + + /* Get the table size and check if its valid */ + cjSize = GETW(&pSubTable->usLength); + if ((ULONG_PTR)pSubTable + cjSize > ulLastAddress) + { + __debugbreak(); + return; + } + + /* Check version */ if (GETW(&pSubTable->usVersion) == 0) + { + /* Get number of kerning pairs and check id its valid */ cPairs += GETW(&pSubTable->format0.nPairs); + if ((ULONG_PTR)&pSubTable->format0.akernpair[cPairs] > ulLastAddress) + { + __debugbreak(); + return; + } + } + + /* Go to next subtable */ + pSubTable = (PVOID)((PCHAR)pSubTable + cjSize); } if (cPairs == 0) @@ -450,7 +497,7 @@ } /* Allocate an FD_KERNINGPAIR array */ - pKernPair = EngAllocMem(0, (cPairs + 1) * sizeof(FD_KERNINGPAIR), '1234'); + pKernPair = EngAllocMem(0, (cPairs + 1) * sizeof(FD_KERNINGPAIR), 'dftF'); pface->pKerningPairs = pKernPair; if (!pKernPair) { @@ -460,34 +507,46 @@ /* Loop all subtables again */ pSubTable = &pKernTable->subtable; - for (i = 0; i < pKernTable->nTables; i++) - { - /* Only type 0 is interesting */ - if (GETW(&pSubTable->usVersion) != 0) continue; - - /* Loop all kern pairs in the table */ - for (j = 0; j < GETW(&pSubTable->format0.nPairs); j++) - { - /* Get the glyph handles for the kerning */ - hgLeft = GETW(&pSubTable->format0.akernpair[j].usLeft); - hgRight = GETW(&pSubTable->format0.akernpair[j].usRight); - - /* Windows wants WCHARs, convert them */ - pKernPair->wcFirst = pface->pwcReverseTable[hgLeft]; - pKernPair->wcSecond = pface->pwcReverseTable[hgLeft]; - pKernPair->fwdKern = GETW(&pSubTable->format0.akernpair[j].fwdValue); - pKernPair++; + for (i = 0; i < nTables; i++) + { + /* Check version */ + if (GETW(&pSubTable->usVersion) == 0) + { + /* Loop all kern pairs in the table */ + for (j = 0; j < GETW(&pSubTable->format0.nPairs); j++) + { + /* Get the glyph handles for the kerning */ + hgLeft = GETW(&pSubTable->format0.akernpair[j].usLeft); + hgRight = GETW(&pSubTable->format0.akernpair[j].usRight); + + /* Make sure we are inside the range */ + if (hgLeft >= pface->cGlyphs) hgLeft = 0; + if (hgRight >= pface->cGlyphs) hgRight = 0; + + /* Windows wants WCHARs, convert them */ + pKernPair->wcFirst = pface->pwcReverseTable[hgLeft]; + pKernPair->wcSecond = pface->pwcReverseTable[hgLeft]; + pKernPair->fwdKern = GETW(&pSubTable->format0.akernpair[j].fwdValue); + pKernPair++; + } } /* Go to next subtable */ - pSubTable = (PVOID)((PCHAR)pSubTable + pSubTable->usLength); - } - - /* Zero terminate last FD_KERNINGPAIR entry */ + pSubTable = (PVOID)((PCHAR)pSubTable + GETW(&pSubTable->usLength)); + } + + /* Zero terminate array */ pKernPair->wcFirst = 0; pKernPair->wcSecond = 0; pKernPair->fwdKern = 0; + /* Sort the array */ + EngSort((PBYTE)pface->pKerningPairs, + sizeof(FD_KERNINGPAIR), + cPairs, + (SORTCOMP)CompareKernPair); + + /* Set the number of kernpairs in the IFIMETRICS */ pface->ifiex.ifi.cKerningPairs = cPairs; }