about summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2017-08-11 02:23:00 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2017-08-11 02:23:00 +0000
commit8328a88016a1c371f40ee280386c4db473df0630 (patch)
treea219ba5340dc3fdb67bbfaf0bb38b9c06cfc36a0 /lib
parent4ca940a010e203480e6b9aa6a466f11b6c3c9792 (diff)
downloadnetpbm-mirror-8328a88016a1c371f40ee280386c4db473df0630.tar.gz
netpbm-mirror-8328a88016a1c371f40ee280386c4db473df0630.tar.xz
netpbm-mirror-8328a88016a1c371f40ee280386c4db473df0630.zip
Fix buffer overflow in font routines, recognize width=0, height=0 glyphs as valid space glyphs, limit size of glyphs, improve handling of font files corrupt at the beginning
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@3042 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'lib')
-rw-r--r--lib/libpbmfont.c69
1 files changed, 53 insertions, 16 deletions
diff --git a/lib/libpbmfont.c b/lib/libpbmfont.c
index 5193cd35..4c6ab1e2 100644
--- a/lib/libpbmfont.c
+++ b/lib/libpbmfont.c
@@ -307,10 +307,13 @@ pbm_loadfont(const char * const filename) {
 
     FILE * fileP;
     struct font * fontP;
-    char line[256];
+    char line[10] = "\0\0\0\0\0\0\0\0\0\0";
+        /* Initialize to suppress Valgrind error which is reported when file
+           is empty or very small.
+        */
 
     fileP = pm_openr(filename);
-    fgets(line, 256, fileP);
+    fgets(line, 10, fileP);
     pm_close(fileP);
 
     if (line[0] == PBM_MAGIC1 && 
@@ -339,8 +342,23 @@ pbm_loadpbmfont(const char * const filename) {
     int fcols, frows;
 
     ifP = pm_openr(filename);
+
     font = pbm_readpbm(ifP, &fcols, &frows);
+
+    if ((fcols - 1) / 16 >= pbm_maxfontwidth() ||
+       (frows - 1) / 12 >= pbm_maxfontheight())
+        pm_error("Absurdly large PBM font file: %s", filename);
+    else if (fcols < 31 || frows < 23) {
+        /* Need at least one pixel per character, and this is too small to
+           have that.
+        */
+        pm_error("PBM font file '%s' too small to be a font file: %u x %u.  "
+                 "Minimum sensible size is 31 x 23",
+                 filename, fcols, frows);
+    }
+
     pm_close(ifP);
+
     return pbm_dissectfont((const bit **)font, frows, fcols);
 }
 
@@ -406,10 +424,18 @@ pbm_dumpfont(struct font * const fontP,
 }
 
 
+/*----------------------------------------------------------------------------
+  Routines for loading a BDF font file
+-----------------------------------------------------------------------------*/
+
+
+/* The following do not work:
+   Vertical writing systems: DWIDTH1, SWIDTH1, VVECTOR
+   global DWIDTH
+*/
 
-/* Routines for loading a BDF font file */
 
-#define  MAXBDFLINE 1024 
+#define MAXBDFLINE 1024 
 
 /* Official Adobe document says max length of string is 65535 characters.
    However the value 1024 is sufficient for practical uses.
@@ -428,7 +454,7 @@ typedef struct {
 
            It also functions as a work area for readline_read().
         */
-    const char * arg[32];
+    const char * arg[6];
         /* These are the words; each entry is a pointer into line[] (above) */
 } Readline;
 
@@ -448,15 +474,17 @@ readline_init(Readline * const readlineP,
 static void
 tokenize(char *         const s,
          const char **  const words,
-         unsigned int   const maxWordCt) {
+         unsigned int   const wordsSz) {
 /*----------------------------------------------------------------------------
-   Chop up 's' into words by changing space characters to NUL.  Return
-   as 'words' pointer to the beginning of those words in 's'.
+   Chop up 's' into words by changing space characters to NUL.  Return as
+   'words' an array of pointers to the beginnings of those words in 's'.
+   Terminate the words[] list with a null pointer.
 
-   If there are more than 'maxWordCt' words in 's', ignore the excess on
-   the right.
+   'wordsSz' is the number of elements of space in 'words'.  If there are more
+   words in 's' than will fit in that space (including the terminating null
+   pointer), ignore the excess on the right.
 -----------------------------------------------------------------------------*/
-    unsigned int n;
+    unsigned int n;  /* Number of words in words[] so far */
     char * p;
 
     p = &s[0];
@@ -467,12 +495,13 @@ tokenize(char *         const s,
             *p++ = '\0';
         else {
             words[n++] = p;
-            if (n >= maxWordCt)
+            if (n >= wordsSz - 1)
                 break;
             while (*p && !ISSPACE(*p))
                 ++p;
         }
     }
+    assert(n <= wordsSz - 1);
     words[n] = NULL;
 }
 
@@ -634,6 +663,9 @@ createBmap(unsigned int  const glyphWidth,
                  "BDF font file.");
     
     if (streq(readlineP->arg[0], "ATTRIBUTES")) {
+        /* ATTRIBUTES is defined in Glyph Bitmap Distribution Format (BDF)
+           Specification Version 2.1, but not in Version 2.2. 
+        */
         bool eof;
         readline_read(readlineP, &eof);
         if (eof)
@@ -754,7 +786,7 @@ readEncoding(Readline *     const readlineP,
 static void
 validateFontLimits(const struct font * const fontP) {
 
-    assert( pbm_maxfontheight() > 0 && pbm_maxfontwidth() > 0 );
+    assert(pbm_maxfontheight() > 0 && pbm_maxfontwidth() > 0);
 
     if (fontP->maxwidth  <= 0 ||
         fontP->maxheight <= 0 ||
@@ -765,7 +797,7 @@ validateFontLimits(const struct font * const fontP) {
         fontP->x > fontP->maxwidth  ||
         fontP->y > fontP->maxheight ||
         fontP->x + fontP->maxwidth  > pbm_maxfontwidth() || 
-         fontP->y + fontP->maxheight > pbm_maxfontheight()
+        fontP->y + fontP->maxheight > pbm_maxfontheight()
         ) {
 
         pm_error("Global font metric(s) out of bounds.\n"); 
@@ -779,8 +811,13 @@ validateGlyphLimits(const struct font  * const fontP,
                     const struct glyph * const glyphP,
                     const char *         const charName) {
 
-    if (glyphP->width  == 0 ||
-        glyphP->height == 0 ||
+    /* Some BDF files code space with zero width and height,
+       no bitmap data and just the xadd value.
+       We allow zero width and height, iff both are zero.
+    */
+
+    if (((glyphP->width == 0 || glyphP->height == 0) &&
+         !(glyphP->width == 0 && glyphP->height == 0)) ||
         glyphP->width  > fontP->maxwidth  ||
         glyphP->height > fontP->maxheight ||
         glyphP->x < fontP->x ||