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;
 }
 


Reply via email to