load(ImlibImage * im, ImlibProgressFunction progress, char progress_granularity,
     char immediate_load)
{
   static const int    intoffset[] = { 0, 4, 2, 1 };
   static const int    intjump[] = { 8, 8, 4, 2 };
   int                 rc;
   DATA32             *ptr;
   GifFileType        *gif;
   GifRowType         *rows;
   GifRecordType       rec;
   ColorMapObject     *cmap;
   int                 i, j, done, bg, r, g, b, w = 0, h = 0;
   float               per = 0.0, per_inc;
   int                 last_per = 0, last_y = 0;
   int                 transp;
   int                 fd;

   done = 0;
   rows = NULL;
   transp = -1;

   /* if immediate_load is 1, then dont delay image laoding as below, or */
   /* already data in this image - dont load it again */
   if (im->data)
      return 0;

   fd = open(im->real_file, O_RDONLY);
   if (fd < 0)
      return 0;

#if GIFLIB_MAJOR >= 5
   gif = DGifOpenFileHandle(fd, NULL);
#else
   gif = DGifOpenFileHandle(fd);
#endif
   if (!gif)
     {
        close(fd);
        return 0;
     }

   rc = 0;                      /* Failure */

   do
     {
        if (DGifGetRecordType(gif, &rec) == GIF_ERROR)
          {
             /* PrintGifError(); */
             rec = TERMINATE_RECORD_TYPE;
          }
        if ((rec == IMAGE_DESC_RECORD_TYPE) && (!done))
          {
             if (DGifGetImageDesc(gif) == GIF_ERROR)
               {
                  /* PrintGifError(); */
                  rec = TERMINATE_RECORD_TYPE;
                  break;
               }
             w = gif->Image.Width;
             h = gif->Image.Height;
             if (!IMAGE_DIMENSIONS_OK(w, h))
                goto quit2;

             rows = calloc(h, sizeof(GifRowType *));
             if (!rows)
                goto quit2;

             for (i = 0; i < h; i++)
               {
                  rows[i] = malloc(w * sizeof(GifPixelType));
                  if (!rows[i])
                     goto quit;
               }

             if (gif->Image.Interlace)
               {
                  for (i = 0; i < 4; i++)
                    {
                       for (j = intoffset[i]; j < h; j += intjump[i])
                         {
                            if (DGifGetLine(gif, rows[i], w) == GIF_ERROR)
                               {
                                  break;
                               }
                         }
                    }
               }
             else
               {
                  for (i = 0; i < h; i++)
                    {
                       if (DGifGetLine(gif, rows[i], w) == GIF_ERROR)
                          {
                             break;
                          }
                    }
               }
             done = 1;
          }
        else if (rec == EXTENSION_RECORD_TYPE)
          {
             int                 ext_code;
             GifByteType        *ext;

             ext = NULL;
             DGifGetExtension(gif, &ext_code, &ext);
             while (ext)
               {
                  if ((ext_code == 0xf9) && (ext[1] & 1) && (transp < 0))
                    {
                       transp = (int)ext[4];
                    }
                  ext = NULL;
                  DGifGetExtensionNext(gif, &ext);
               }
          }
     }
   while (rec != TERMINATE_RECORD_TYPE);

   if (transp >= 0)
     {
        SET_FLAG(im->flags, F_HAS_ALPHA);
     }
   else
      {
         UNSET_FLAG(im->flags, F_HAS_ALPHA);
      }
   if (!rows)
     {
        goto quit2;
     }

    /* set the format string member to the lower-case full extension */
    /* name for the format - so example names would be: */
      im->format = strdup("gif");

   if (im->loader || immediate_load || progress)
     {
        bg = gif->SBackGroundColor;
        cmap = (gif->Image.ColorMap ? gif->Image.ColorMap : gif->SColorMap);
        im->data = (DATA32 *) malloc(sizeof(DATA32) * w * h);
        if (!im->data)
           goto quit;

        if (!cmap)
          {
             /* No colormap? Now what?? Let's clear the image (and not segv) */
             memset(im->data, 0, sizeof(DATA32) * w * h);
             rc = 1;
             goto finish;
          }

        ptr = im->data;
        per_inc = 100.0 / (((float)w) * h);
        for (i = 0; i < h; i++)
          {
             for (j = 0; j < w; j++)
               {
                  if (rows[i][j] == transp)
                    {
                       r = cmap->Colors[bg].Red;
                       g = cmap->Colors[bg].Green;
                       b = cmap->Colors[bg].Blue;
                       *ptr++ = 0x00ffffff & ((r << 16) | (g << 8) | b);
                    }
                  else
                    {
                       r = cmap->Colors[rows[i][j]].Red;
                       g = cmap->Colors[rows[i][j]].Green;
                       b = cmap->Colors[rows[i][j]].Blue;
                       *ptr++ = (0xff << 24) | (r << 16) | (g << 8) | b;
                    }
                  per += per_inc;
                  if (progress && (((int)per) != last_per)
                      && (((int)per) % progress_granularity == 0))
                    {
                       last_per = (int)per;
                       if (!(progress(im, (int)per, 0, last_y, w, i)))
                         {
                            rc = 2;
                            goto quit;
                         }
                       last_y = i;
                    }
               }
          }

      finish:
        if (progress)
           progress(im, 100, 0, last_y, w, h);
     }

   rc = 1;                      /* Success */

 quit:
   for (i = 0; i < h; i++)
      free(rows[i]);
   free(rows);

 quit2:
#if GIFLIB_MAJOR > 5 || (GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1)
   DGifCloseFile(gif, NULL);
#else
   DGifCloseFile(gif);
#endif

   return rc;
}


load(ImlibImage * im, ImlibProgressFunction progress,
     char progress_granularity, char immediate_load)
{
   int                 rc;
   char                p = ' ', numbers = 3, count = 0;
   int                 w = 0, h = 0, v = 255, c = 0;
   char                buf[256];
   FILE               *f = NULL;

   if (im->data)
      return 0;
   f = fopen(im->real_file, "rb");
   if (!f)
      return 0;

   /* can't use fgets(), because there might be
    * binary data after the header and there
    * needn't be a newline before the data, so
    * no chance to distinguish between end of buffer
    * and a binary 0.
    */

   /* read the header info */

   rc = 0;                      /* Error */

   c = fgetc(f);
   if (c != 'P')
      goto quit;

   p = fgetc(f);
   if (p == '1' || p == '4')
      numbers = 2;              /* bitimages don't have max value */

   if ((p < '1') || (p > '8'))
      goto quit;

   count = 0;
   while (count < numbers)
     {
        c = fgetc(f);

        if (c == EOF)
           goto quit;

        /* eat whitespace */
        while (isspace(c))
           c = fgetc(f);
        /* if comment, eat that */
        if (c == '#')
          {
             do
                c = fgetc(f);
             while (c != '\n' && c != EOF);
          }
        /* no comment -> proceed */
        else
          {
             int                 i = 0;

             /* read numbers */
             while (c != EOF && !isspace(c) && (i < 255))
               {
                  buf[i++] = c;
                  c = fgetc(f);
               }
             if (i)
               {
                  buf[i] = 0;
                  count++;
                  switch (count)
                    {
                       /* width */
                    case 1:
                       w = atoi(buf);
                       break;
                       /* height */
                    case 2:
                       h = atoi(buf);
                       break;
                       /* max value, only for color and greyscale */
                    case 3:
                       v = atoi(buf);
                       break;
                    }
               }
          }
     }
   if ((v < 0) || (v > 255))
      goto quit;

   im->w = w;
   im->h = h;
   if (!IMAGE_DIMENSIONS_OK(w, h))
      goto quit;

   if (!im->format)
     {
        if (p == '8')
           SET_FLAG(im->flags, F_HAS_ALPHA);
        else
           UNSET_FLAG(im->flags, F_HAS_ALPHA);
        im->format = strdup("pnm");
     }

   rc = 1;                      /* Ok */

   if (((!im->data) && (im->loader)) || (immediate_load) || (progress))
     {
        DATA8              *data = NULL;        /* for the binary versions */
        DATA8              *ptr = NULL;
        int                *idata = NULL;       /* for the ASCII versions */
        int                *iptr;
        char                buf2[256];
        DATA32             *ptr2;
        int                 i, j, x, y, pl = 0;
        char                pper = 0;

        /* must set the im->data member before callign progress function */
        ptr2 = im->data = malloc(w * h * sizeof(DATA32));
        if (!im->data)
           goto quit_error;

        /* start reading the data */
        switch (p)
          {
          case '1':            /* ASCII monochrome */
             buf[0] = 0;
             i = 0;
             for (y = 0; y < h; y++)
               {
                  x = 0;
                  while (x < w)
                    {
                       if (!buf[i])     /* fill buffer */
                         {
                            if (!fgets(buf, 255, f))
                               goto quit_error;
                            i = 0;
                         }
                       while (buf[i] && isspace(buf[i]))
                          i++;
                       if (buf[i])
                         {
                            if (buf[i] == '1')
                               *ptr2 = 0xff000000;
                            else if (buf[i] == '0')
                               *ptr2 = 0xffffffff;
                            else
                               goto quit_error;
                            ptr2++;
                            i++;
                         }
                    }
                  if (progress &&
                      do_progress(im, progress, progress_granularity,
                                  &pper, &pl, y))
                     goto quit_progress;
               }
             break;
          case '2':            /* ASCII greyscale */
             idata = malloc(sizeof(int) * w);
             if (!idata)
                goto quit_error;

             buf[0] = 0;
             i = 0;
             j = 0;
             for (y = 0; y < h; y++)
               {
                  iptr = idata;
                  x = 0;
                  while (x < w)
                    {
                       int                 k;

                       /* check 4 chars ahead to see if we need to
                        * fill the buffer */
                       for (k = 0; k < 4; k++)
                         {
                            if (!buf[i + k])    /* fill buffer */
                              {
                                 if (fseek(f, -k, SEEK_CUR) == -1 ||
                                     !fgets(buf, 255, f))
                                    goto quit_error;
                                 i = 0;
                                 break;
                              }
                         }
                       while (buf[i] && isspace(buf[i]))
                          i++;
                       while (buf[i] && !isspace(buf[i]))
                          buf2[j++] = buf[i++];
                       if (j)
                         {
                            buf2[j] = 0;
                            *(iptr++) = atoi(buf2);
                            j = 0;
                            x++;
                          }
                     }
                   iptr = idata;
                  if (v == 255)
                     {
                        for (x = 0; x < w; x++)
                          {
                            *ptr2 =
                               0xff000000 | (iptr[0] << 16) | (iptr[0] << 8)
                               | iptr[0];
                            ptr2++;
                            iptr++;
                         }
                    }
                  else
                    {
                       for (x = 0; x < w; x++)
                         {
                            *ptr2 =
                               0xff000000 |
                               (((iptr[0] * 255) / v) << 16) |
                               (((iptr[0] * 255) / v) << 8) |
                               ((iptr[0] * 255) / v);
                            ptr2++;
                            iptr++;
                         }
                    }
                  if (progress &&
                      do_progress(im, progress, progress_granularity,
                                  &pper, &pl, y))
                     goto quit_progress;
               }
             break;
          case '3':            /* ASCII RGB */
             idata = malloc(3 * sizeof(int) * w);
             if (!idata)
                goto quit_error;

             buf[0] = 0;
             i = 0;
             j = 0;
             for (y = 0; y < h; y++)
               {
                  int                 w3 = 3 * w;

                  iptr = idata;
                  x = 0;
                  while (x < w3)
                    {
                       int                 k;

                       /* check 4 chars ahead to see if we need to
                        * fill the buffer */
                       for (k = 0; k < 4; k++)
                         {
                            if (!buf[i + k])    /* fill buffer */
                              {
                                 if (fseek(f, -k, SEEK_CUR) == -1 ||
                                     !fgets(buf, 255, f))
                                    goto quit_error;
                                 i = 0;
                                 break;
                              }
                         }
                       while (buf[i] && isspace(buf[i]))
                          i++;
                       while (buf[i] && !isspace(buf[i]))
                          buf2[j++] = buf[i++];
                       if (j)
                         {
                            buf2[j] = 0;
                            *(iptr++) = atoi(buf2);
                            j = 0;
                            x++;
                          }
                     }
                   iptr = idata;
                  if (v == 255)
                     {
                        for (x = 0; x < w; x++)
                          {
                            *ptr2 =
                               0xff000000 | (iptr[0] << 16) | (iptr[1] << 8)
                               | iptr[2];
                            ptr2++;
                            iptr += 3;
                         }
                    }
                  else
                    {
                       for (x = 0; x < w; x++)
                         {
                            *ptr2 =
                               0xff000000 |
                               (((iptr[0] * 255) / v) << 16) |
                               (((iptr[1] * 255) / v) << 8) |
                               ((iptr[2] * 255) / v);
                            ptr2++;
                            iptr += 3;
                         }
                    }
                  if (progress &&
                      do_progress(im, progress, progress_granularity,
                                  &pper, &pl, y))
                     goto quit_progress;
               }
             break;
          case '4':            /* binary 1bit monochrome */
             data = malloc((w + 7) / 8 * sizeof(DATA8));
             if (!data)
                goto quit_error;

             ptr2 = im->data;
             for (y = 0; y < h; y++)
               {
                  if (!fread(data, (w + 7) / 8, 1, f))
                     goto quit_error;

                  ptr = data;
                  for (x = 0; x < w; x += 8)
                    {
                       j = (w - x >= 8) ? 8 : w - x;
                       for (i = 0; i < j; i++)
                         {
                            if (ptr[0] & (0x80 >> i))
                               *ptr2 = 0xff000000;
                            else
                               *ptr2 = 0xffffffff;
                            ptr2++;
                         }
                       ptr++;
                    }
                  if (progress &&
                      do_progress(im, progress, progress_granularity,
                                  &pper, &pl, y))
                     goto quit_progress;
               }
             break;
          case '5':            /* binary 8bit grayscale GGGGGGGG */
             data = malloc(1 * sizeof(DATA8) * w);
             if (!data)
                goto quit_error;

             ptr2 = im->data;
             for (y = 0; y < h; y++)
               {
                  if (!fread(data, w * 1, 1, f))
                      break;

                   ptr = data;
                  if (v == 255)
                     {
                        for (x = 0; x < w; x++)
                          {
                            *ptr2 =
                               0xff000000 | (ptr[0] << 16) | (ptr[0] << 8) |
                               ptr[0];
                            ptr2++;
                            ptr++;
                         }
                    }
                  else
                    {
                       for (x = 0; x < w; x++)
                         {
                            *ptr2 =
                               0xff000000 |
                               (((ptr[0] * 255) / v) << 16) |
                               (((ptr[0] * 255) / v) << 8) |
                               ((ptr[0] * 255) / v);
                            ptr2++;
                            ptr++;
                         }
                    }
                  if (progress &&
                      do_progress(im, progress, progress_granularity,
                                  &pper, &pl, y))
                     goto quit_progress;
               }
             break;
          case '6':            /* 24bit binary RGBRGBRGB */
             data = malloc(3 * sizeof(DATA8) * w);
             if (!data)
                goto quit_error;

             ptr2 = im->data;
             for (y = 0; y < h; y++)
               {
                  if (!fread(data, w * 3, 1, f))
                      break;

                   ptr = data;
                  if (v == 255)
                     {
                        for (x = 0; x < w; x++)
                          {
                            *ptr2 =
                               0xff000000 | (ptr[0] << 16) | (ptr[1] << 8) |
                               ptr[2];
                            ptr2++;
                            ptr += 3;
                         }
                    }
                  else
                    {
                       for (x = 0; x < w; x++)
                         {
                            *ptr2 =
                               0xff000000 |
                               (((ptr[0] * 255) / v) << 16) |
                               (((ptr[1] * 255) / v) << 8) |
                               ((ptr[2] * 255) / v);
                            ptr2++;
                            ptr += 3;
                         }
                    }
                  if (progress &&
                      do_progress(im, progress, progress_granularity,
                                  &pper, &pl, y))
                     goto quit_progress;
               }
             break;
          case '7':            /* XV's 8bit 332 format */
             data = malloc(1 * sizeof(DATA8) * w);
             if (!data)
                goto quit_error;

             ptr2 = im->data;
             for (y = 0; y < h; y++)
               {
                  if (!fread(data, w * 1, 1, f))
                     break;

                  ptr = data;
                  for (x = 0; x < w; x++)
                    {
                       int                 r, g, b;

                       r = (*ptr >> 5) & 0x7;
                       g = (*ptr >> 2) & 0x7;
                       b = (*ptr) & 0x3;
                       *ptr2 =
                          0xff000000 |
                          (((r << 21) | (r << 18) | (r << 15)) & 0xff0000) |
                          (((g << 13) | (g << 10) | (g << 7)) & 0xff00) |
                          ((b << 6) | (b << 4) | (b << 2) | (b << 0));
                       ptr2++;
                       ptr++;
                    }
                  if (progress &&
                      do_progress(im, progress, progress_granularity,
                                  &pper, &pl, y))
                     goto quit_progress;
               }
             break;
          case '8':            /* 24bit binary RGBARGBARGBA */
             data = malloc(4 * sizeof(DATA8) * w);
             if (!data)
                goto quit_error;

             ptr2 = im->data;
             for (y = 0; y < h; y++)
               {
                  if (!fread(data, w * 4, 1, f))
                      break;

                   ptr = data;
                  if (v == 255)
                     {
                        for (x = 0; x < w; x++)
                          {
                            *ptr2 =
                               (ptr[3] << 24) | (ptr[0] << 16) |
                               (ptr[1] << 8) | ptr[2];
                            ptr2++;
                            ptr += 4;
                         }
                    }
                  else
                    {
                       for (x = 0; x < w; x++)
                         {
                            *ptr2 =
                               (((ptr[3] * 255) / v) << 24) |
                               (((ptr[0] * 255) / v) << 16) |
                               (((ptr[1] * 255) / v) << 8) |
                               ((ptr[2] * 255) / v);
                            ptr2++;
                            ptr += 4;
                         }
                    }
                  if (progress &&
                      do_progress(im, progress, progress_granularity,
                                  &pper, &pl, y))
                     goto quit_progress;
               }
             break;
          default:
           quit_error:
             rc = 0;
             break;
           quit_progress:
             rc = 2;
             break;
          }
        if (idata)
           free(idata);
        if (data)
           free(data);
     }
 quit:
   fclose(f);
   return rc;
}

imlib2 before 1.4.7 allows remote attackers to cause a denial of service (divide-by-zero error and application crash) via a crafted PNM file.


load(ImlibImage * im, ImlibProgressFunction progress,
     char progress_granularity, char immediate_load)
{
   int                 rc;
   char                p = ' ', numbers = 3, count = 0;
   int                 w = 0, h = 0, v = 255, c = 0;
   char                buf[256];
   FILE               *f = NULL;

   if (im->data)
      return 0;
   f = fopen(im->real_file, "rb");
   if (!f)
      return 0;

   /* can't use fgets(), because there might be
    * binary data after the header and there
    * needn't be a newline before the data, so
    * no chance to distinguish between end of buffer
    * and a binary 0.
    */

   /* read the header info */

   rc = 0;                      /* Error */

   c = fgetc(f);
   if (c != 'P')
      goto quit;

   p = fgetc(f);
   if (p == '1' || p == '4')
      numbers = 2;              /* bitimages don't have max value */

   if ((p < '1') || (p > '8'))
      goto quit;

   count = 0;
   while (count < numbers)
     {
        c = fgetc(f);

        if (c == EOF)
           goto quit;

        /* eat whitespace */
        while (isspace(c))
           c = fgetc(f);
        /* if comment, eat that */
        if (c == '#')
          {
             do
                c = fgetc(f);
             while (c != '\n' && c != EOF);
          }
        /* no comment -> proceed */
        else
          {
             int                 i = 0;

             /* read numbers */
             while (c != EOF && !isspace(c) && (i < 255))
               {
                  buf[i++] = c;
                  c = fgetc(f);
               }
             if (i)
               {
                  buf[i] = 0;
                  count++;
                  switch (count)
                    {
                       /* width */
                    case 1:
                       w = atoi(buf);
                       break;
                       /* height */
                    case 2:
                       h = atoi(buf);
                       break;
                       /* max value, only for color and greyscale */
                    case 3:
                       v = atoi(buf);
                       break;
                    }
               }
          }
     }
   if ((v < 0) || (v > 255))
      goto quit;

   im->w = w;
   im->h = h;
   if (!IMAGE_DIMENSIONS_OK(w, h))
      goto quit;

   if (!im->format)
     {
        if (p == '8')
           SET_FLAG(im->flags, F_HAS_ALPHA);
        else
           UNSET_FLAG(im->flags, F_HAS_ALPHA);
        im->format = strdup("pnm");
     }

   rc = 1;                      /* Ok */

   if (((!im->data) && (im->loader)) || (immediate_load) || (progress))
     {
        DATA8              *data = NULL;        /* for the binary versions */
        DATA8              *ptr = NULL;
        int                *idata = NULL;       /* for the ASCII versions */
        int                *iptr;
        char                buf2[256];
        DATA32             *ptr2;
        int                 i, j, x, y, pl = 0;
        char                pper = 0;

        /* must set the im->data member before callign progress function */
        ptr2 = im->data = malloc(w * h * sizeof(DATA32));
        if (!im->data)
           goto quit_error;

        /* start reading the data */
        switch (p)
          {
          case '1':            /* ASCII monochrome */
             buf[0] = 0;
             i = 0;
             for (y = 0; y < h; y++)
               {
                  x = 0;
                  while (x < w)
                    {
                       if (!buf[i])     /* fill buffer */
                         {
                            if (!fgets(buf, 255, f))
                               goto quit_error;
                            i = 0;
                         }
                       while (buf[i] && isspace(buf[i]))
                          i++;
                       if (buf[i])
                         {
                            if (buf[i] == '1')
                               *ptr2 = 0xff000000;
                            else if (buf[i] == '0')
                               *ptr2 = 0xffffffff;
                            else
                               goto quit_error;
                            ptr2++;
                            i++;
                         }
                    }
                  if (progress &&
                      do_progress(im, progress, progress_granularity,
                                  &pper, &pl, y))
                     goto quit_progress;
               }
             break;
          case '2':            /* ASCII greyscale */
             idata = malloc(sizeof(int) * w);
             if (!idata)
                goto quit_error;

             buf[0] = 0;
             i = 0;
             j = 0;
             for (y = 0; y < h; y++)
               {
                  iptr = idata;
                  x = 0;
                  while (x < w)
                    {
                       int                 k;

                       /* check 4 chars ahead to see if we need to
                        * fill the buffer */
                       for (k = 0; k < 4; k++)
                         {
                            if (!buf[i + k])    /* fill buffer */
                              {
                                 if (fseek(f, -k, SEEK_CUR) == -1 ||
                                     !fgets(buf, 255, f))
                                    goto quit_error;
                                 i = 0;
                                 break;
                              }
                         }
                       while (buf[i] && isspace(buf[i]))
                          i++;
                       while (buf[i] && !isspace(buf[i]))
                          buf2[j++] = buf[i++];
                       if (j)
                         {
                            buf2[j] = 0;
                            *(iptr++) = atoi(buf2);
                            j = 0;
                            x++;
                          }
                     }
                   iptr = idata;
                  if (v == 0 || v == 255)
                     {
                        for (x = 0; x < w; x++)
                          {
                            *ptr2 =
                               0xff000000 | (iptr[0] << 16) | (iptr[0] << 8)
                               | iptr[0];
                            ptr2++;
                            iptr++;
                         }
                    }
                  else
                    {
                       for (x = 0; x < w; x++)
                         {
                            *ptr2 =
                               0xff000000 |
                               (((iptr[0] * 255) / v) << 16) |
                               (((iptr[0] * 255) / v) << 8) |
                               ((iptr[0] * 255) / v);
                            ptr2++;
                            iptr++;
                         }
                    }
                  if (progress &&
                      do_progress(im, progress, progress_granularity,
                                  &pper, &pl, y))
                     goto quit_progress;
               }
             break;
          case '3':            /* ASCII RGB */
             idata = malloc(3 * sizeof(int) * w);
             if (!idata)
                goto quit_error;

             buf[0] = 0;
             i = 0;
             j = 0;
             for (y = 0; y < h; y++)
               {
                  int                 w3 = 3 * w;

                  iptr = idata;
                  x = 0;
                  while (x < w3)
                    {
                       int                 k;

                       /* check 4 chars ahead to see if we need to
                        * fill the buffer */
                       for (k = 0; k < 4; k++)
                         {
                            if (!buf[i + k])    /* fill buffer */
                              {
                                 if (fseek(f, -k, SEEK_CUR) == -1 ||
                                     !fgets(buf, 255, f))
                                    goto quit_error;
                                 i = 0;
                                 break;
                              }
                         }
                       while (buf[i] && isspace(buf[i]))
                          i++;
                       while (buf[i] && !isspace(buf[i]))
                          buf2[j++] = buf[i++];
                       if (j)
                         {
                            buf2[j] = 0;
                            *(iptr++) = atoi(buf2);
                            j = 0;
                            x++;
                          }
                     }
                   iptr = idata;
                  if (v == 0 || v == 255)
                     {
                        for (x = 0; x < w; x++)
                          {
                            *ptr2 =
                               0xff000000 | (iptr[0] << 16) | (iptr[1] << 8)
                               | iptr[2];
                            ptr2++;
                            iptr += 3;
                         }
                    }
                  else
                    {
                       for (x = 0; x < w; x++)
                         {
                            *ptr2 =
                               0xff000000 |
                               (((iptr[0] * 255) / v) << 16) |
                               (((iptr[1] * 255) / v) << 8) |
                               ((iptr[2] * 255) / v);
                            ptr2++;
                            iptr += 3;
                         }
                    }
                  if (progress &&
                      do_progress(im, progress, progress_granularity,
                                  &pper, &pl, y))
                     goto quit_progress;
               }
             break;
          case '4':            /* binary 1bit monochrome */
             data = malloc((w + 7) / 8 * sizeof(DATA8));
             if (!data)
                goto quit_error;

             ptr2 = im->data;
             for (y = 0; y < h; y++)
               {
                  if (!fread(data, (w + 7) / 8, 1, f))
                     goto quit_error;

                  ptr = data;
                  for (x = 0; x < w; x += 8)
                    {
                       j = (w - x >= 8) ? 8 : w - x;
                       for (i = 0; i < j; i++)
                         {
                            if (ptr[0] & (0x80 >> i))
                               *ptr2 = 0xff000000;
                            else
                               *ptr2 = 0xffffffff;
                            ptr2++;
                         }
                       ptr++;
                    }
                  if (progress &&
                      do_progress(im, progress, progress_granularity,
                                  &pper, &pl, y))
                     goto quit_progress;
               }
             break;
          case '5':            /* binary 8bit grayscale GGGGGGGG */
             data = malloc(1 * sizeof(DATA8) * w);
             if (!data)
                goto quit_error;

             ptr2 = im->data;
             for (y = 0; y < h; y++)
               {
                  if (!fread(data, w * 1, 1, f))
                      break;

                   ptr = data;
                  if (v == 0 || v == 255)
                     {
                        for (x = 0; x < w; x++)
                          {
                            *ptr2 =
                               0xff000000 | (ptr[0] << 16) | (ptr[0] << 8) |
                               ptr[0];
                            ptr2++;
                            ptr++;
                         }
                    }
                  else
                    {
                       for (x = 0; x < w; x++)
                         {
                            *ptr2 =
                               0xff000000 |
                               (((ptr[0] * 255) / v) << 16) |
                               (((ptr[0] * 255) / v) << 8) |
                               ((ptr[0] * 255) / v);
                            ptr2++;
                            ptr++;
                         }
                    }
                  if (progress &&
                      do_progress(im, progress, progress_granularity,
                                  &pper, &pl, y))
                     goto quit_progress;
               }
             break;
          case '6':            /* 24bit binary RGBRGBRGB */
             data = malloc(3 * sizeof(DATA8) * w);
             if (!data)
                goto quit_error;

             ptr2 = im->data;
             for (y = 0; y < h; y++)
               {
                  if (!fread(data, w * 3, 1, f))
                      break;

                   ptr = data;
                  if (v == 0 || v == 255)
                     {
                        for (x = 0; x < w; x++)
                          {
                            *ptr2 =
                               0xff000000 | (ptr[0] << 16) | (ptr[1] << 8) |
                               ptr[2];
                            ptr2++;
                            ptr += 3;
                         }
                    }
                  else
                    {
                       for (x = 0; x < w; x++)
                         {
                            *ptr2 =
                               0xff000000 |
                               (((ptr[0] * 255) / v) << 16) |
                               (((ptr[1] * 255) / v) << 8) |
                               ((ptr[2] * 255) / v);
                            ptr2++;
                            ptr += 3;
                         }
                    }
                  if (progress &&
                      do_progress(im, progress, progress_granularity,
                                  &pper, &pl, y))
                     goto quit_progress;
               }
             break;
          case '7':            /* XV's 8bit 332 format */
             data = malloc(1 * sizeof(DATA8) * w);
             if (!data)
                goto quit_error;

             ptr2 = im->data;
             for (y = 0; y < h; y++)
               {
                  if (!fread(data, w * 1, 1, f))
                     break;

                  ptr = data;
                  for (x = 0; x < w; x++)
                    {
                       int                 r, g, b;

                       r = (*ptr >> 5) & 0x7;
                       g = (*ptr >> 2) & 0x7;
                       b = (*ptr) & 0x3;
                       *ptr2 =
                          0xff000000 |
                          (((r << 21) | (r << 18) | (r << 15)) & 0xff0000) |
                          (((g << 13) | (g << 10) | (g << 7)) & 0xff00) |
                          ((b << 6) | (b << 4) | (b << 2) | (b << 0));
                       ptr2++;
                       ptr++;
                    }
                  if (progress &&
                      do_progress(im, progress, progress_granularity,
                                  &pper, &pl, y))
                     goto quit_progress;
               }
             break;
          case '8':            /* 24bit binary RGBARGBARGBA */
             data = malloc(4 * sizeof(DATA8) * w);
             if (!data)
                goto quit_error;

             ptr2 = im->data;
             for (y = 0; y < h; y++)
               {
                  if (!fread(data, w * 4, 1, f))
                      break;

                   ptr = data;
                  if (v == 0 || v == 255)
                     {
                        for (x = 0; x < w; x++)
                          {
                            *ptr2 =
                               (ptr[3] << 24) | (ptr[0] << 16) |
                               (ptr[1] << 8) | ptr[2];
                            ptr2++;
                            ptr += 4;
                         }
                    }
                  else
                    {
                       for (x = 0; x < w; x++)
                         {
                            *ptr2 =
                               (((ptr[3] * 255) / v) << 24) |
                               (((ptr[0] * 255) / v) << 16) |
                               (((ptr[1] * 255) / v) << 8) |
                               ((ptr[2] * 255) / v);
                            ptr2++;
                            ptr += 4;
                         }
                    }
                  if (progress &&
                      do_progress(im, progress, progress_granularity,
                                  &pper, &pl, y))
                     goto quit_progress;
               }
             break;
          default:
           quit_error:
             rc = 0;
             break;
           quit_progress:
             rc = 2;
             break;
          }
        if (idata)
           free(idata);
        if (data)
           free(data);
     }
 quit:
   fclose(f);
   return rc;
}


load(ImlibImage * im, ImlibProgressFunction progress, char progress_granularity,
     char immediate_load)
{
   static const int    intoffset[] = { 0, 4, 2, 1 };
   static const int    intjump[] = { 8, 8, 4, 2 };
   int                 rc;
   DATA32             *ptr;
   GifFileType        *gif;
   GifRowType         *rows;
   GifRecordType       rec;
   ColorMapObject     *cmap;
   int                 i, j, done, bg, r, g, b, w = 0, h = 0;
   float               per = 0.0, per_inc;
   int                 last_per = 0, last_y = 0;
   int                 transp;
   int                 fd;

   done = 0;
   rows = NULL;
   transp = -1;

   /* if immediate_load is 1, then dont delay image laoding as below, or */
   /* already data in this image - dont load it again */
   if (im->data)
      return 0;

   fd = open(im->real_file, O_RDONLY);
   if (fd < 0)
      return 0;

#if GIFLIB_MAJOR >= 5
   gif = DGifOpenFileHandle(fd, NULL);
#else
   gif = DGifOpenFileHandle(fd);
#endif
   if (!gif)
     {
        close(fd);
        return 0;
     }

   rc = 0;                      /* Failure */

   do
     {
        if (DGifGetRecordType(gif, &rec) == GIF_ERROR)
          {
             /* PrintGifError(); */
             rec = TERMINATE_RECORD_TYPE;
          }
        if ((rec == IMAGE_DESC_RECORD_TYPE) && (!done))
          {
             if (DGifGetImageDesc(gif) == GIF_ERROR)
               {
                  /* PrintGifError(); */
                  rec = TERMINATE_RECORD_TYPE;
               }
             w = gif->Image.Width;
             h = gif->Image.Height;
             if (!IMAGE_DIMENSIONS_OK(w, h))
                goto quit2;

             rows = calloc(h, sizeof(GifRowType *));
             if (!rows)
                goto quit2;

             for (i = 0; i < h; i++)
               {
                  rows[i] = malloc(w * sizeof(GifPixelType));
                  if (!rows[i])
                     goto quit;
               }

             if (gif->Image.Interlace)
               {
                  for (i = 0; i < 4; i++)
                    {
                       for (j = intoffset[i]; j < h; j += intjump[i])
                         {
                            DGifGetLine(gif, rows[j], w);
                         }
                    }
               }
             else
               {
                  for (i = 0; i < h; i++)
                    {
                       DGifGetLine(gif, rows[i], w);
                    }
               }
             done = 1;
          }
        else if (rec == EXTENSION_RECORD_TYPE)
          {
             int                 ext_code;
             GifByteType        *ext;

             ext = NULL;
             DGifGetExtension(gif, &ext_code, &ext);
             while (ext)
               {
                  if ((ext_code == 0xf9) && (ext[1] & 1) && (transp < 0))
                    {
                       transp = (int)ext[4];
                    }
                  ext = NULL;
                  DGifGetExtensionNext(gif, &ext);
               }
          }
     }
   while (rec != TERMINATE_RECORD_TYPE);

   if (transp >= 0)
     {
        SET_FLAG(im->flags, F_HAS_ALPHA);
     }
   else
     {
        UNSET_FLAG(im->flags, F_HAS_ALPHA);
     }

   /* set the format string member to the lower-case full extension */
   /* name for the format - so example names would be: */
   /* "png", "jpeg", "tiff", "ppm", "pgm", "pbm", "gif", "xpm" ... */
   im->w = w;
   im->h = h;
   if (!im->format)
      im->format = strdup("gif");

   if (im->loader || immediate_load || progress)
     {
        bg = gif->SBackGroundColor;
        cmap = (gif->Image.ColorMap ? gif->Image.ColorMap : gif->SColorMap);
        im->data = (DATA32 *) malloc(sizeof(DATA32) * w * h);
         if (!im->data)
            goto quit;

         ptr = im->data;
         per_inc = 100.0 / (((float)w) * h);
         for (i = 0; i < h; i++)
                       *ptr++ = 0x00ffffff & ((r << 16) | (g << 8) | b);
                    }
                  else
                    {
                       r = cmap->Colors[rows[i][j]].Red;
                       g = cmap->Colors[rows[i][j]].Green;
                       b = cmap->Colors[rows[i][j]].Blue;
                       *ptr++ = (0xff << 24) | (r << 16) | (g << 8) | b;
                    }
                  per += per_inc;
                  if (progress && (((int)per) != last_per)
                      && (((int)per) % progress_granularity == 0))
                    {
                       last_per = (int)per;
                       if (!(progress(im, (int)per, 0, last_y, w, i)))
                         {
                            rc = 2;
                            goto quit;
                         }
                       last_y = i;
                    }
               }

imlib2 before 1.4.7 allows remote attackers to cause a denial of service (segmentation fault) via a GIF image without a colormap.


load(ImlibImage * im, ImlibProgressFunction progress, char progress_granularity,
     char immediate_load)
{
   static const int    intoffset[] = { 0, 4, 2, 1 };
   static const int    intjump[] = { 8, 8, 4, 2 };
   int                 rc;
   DATA32             *ptr;
   GifFileType        *gif;
   GifRowType         *rows;
   GifRecordType       rec;
   ColorMapObject     *cmap;
   int                 i, j, done, bg, r, g, b, w = 0, h = 0;
   float               per = 0.0, per_inc;
   int                 last_per = 0, last_y = 0;
   int                 transp;
   int                 fd;

   done = 0;
   rows = NULL;
   transp = -1;

   /* if immediate_load is 1, then dont delay image laoding as below, or */
   /* already data in this image - dont load it again */
   if (im->data)
      return 0;

   fd = open(im->real_file, O_RDONLY);
   if (fd < 0)
      return 0;

#if GIFLIB_MAJOR >= 5
   gif = DGifOpenFileHandle(fd, NULL);
#else
   gif = DGifOpenFileHandle(fd);
#endif
   if (!gif)
     {
        close(fd);
        return 0;
     }

   rc = 0;                      /* Failure */

   do
     {
        if (DGifGetRecordType(gif, &rec) == GIF_ERROR)
          {
             /* PrintGifError(); */
             rec = TERMINATE_RECORD_TYPE;
          }
        if ((rec == IMAGE_DESC_RECORD_TYPE) && (!done))
          {
             if (DGifGetImageDesc(gif) == GIF_ERROR)
               {
                  /* PrintGifError(); */
                  rec = TERMINATE_RECORD_TYPE;
               }
             w = gif->Image.Width;
             h = gif->Image.Height;
             if (!IMAGE_DIMENSIONS_OK(w, h))
                goto quit2;

             rows = calloc(h, sizeof(GifRowType *));
             if (!rows)
                goto quit2;

             for (i = 0; i < h; i++)
               {
                  rows[i] = malloc(w * sizeof(GifPixelType));
                  if (!rows[i])
                     goto quit;
               }

             if (gif->Image.Interlace)
               {
                  for (i = 0; i < 4; i++)
                    {
                       for (j = intoffset[i]; j < h; j += intjump[i])
                         {
                            DGifGetLine(gif, rows[j], w);
                         }
                    }
               }
             else
               {
                  for (i = 0; i < h; i++)
                    {
                       DGifGetLine(gif, rows[i], w);
                    }
               }
             done = 1;
          }
        else if (rec == EXTENSION_RECORD_TYPE)
          {
             int                 ext_code;
             GifByteType        *ext;

             ext = NULL;
             DGifGetExtension(gif, &ext_code, &ext);
             while (ext)
               {
                  if ((ext_code == 0xf9) && (ext[1] & 1) && (transp < 0))
                    {
                       transp = (int)ext[4];
                    }
                  ext = NULL;
                  DGifGetExtensionNext(gif, &ext);
               }
          }
     }
   while (rec != TERMINATE_RECORD_TYPE);

   if (transp >= 0)
     {
        SET_FLAG(im->flags, F_HAS_ALPHA);
     }
   else
     {
        UNSET_FLAG(im->flags, F_HAS_ALPHA);
     }

   /* set the format string member to the lower-case full extension */
   /* name for the format - so example names would be: */
   /* "png", "jpeg", "tiff", "ppm", "pgm", "pbm", "gif", "xpm" ... */
   im->w = w;
   im->h = h;
   if (!im->format)
      im->format = strdup("gif");

   if (im->loader || immediate_load || progress)
     {
        bg = gif->SBackGroundColor;
        cmap = (gif->Image.ColorMap ? gif->Image.ColorMap : gif->SColorMap);
        im->data = (DATA32 *) malloc(sizeof(DATA32) * w * h);
         if (!im->data)
            goto quit;

        if (!cmap)
          {
             /* No colormap? Now what?? Let's clear the image (and not segv) */
             memset(im->data, 0, sizeof(DATA32) * w * h);
             rc = 1;
             goto finish;
          }

         ptr = im->data;
         per_inc = 100.0 / (((float)w) * h);
         for (i = 0; i < h; i++)
                       *ptr++ = 0x00ffffff & ((r << 16) | (g << 8) | b);
                    }
                  else
                    {
                       r = cmap->Colors[rows[i][j]].Red;
                       g = cmap->Colors[rows[i][j]].Green;
                       b = cmap->Colors[rows[i][j]].Blue;
                       *ptr++ = (0xff << 24) | (r << 16) | (g << 8) | b;
                    }
                  per += per_inc;
                  if (progress && (((int)per) != last_per)
                      && (((int)per) % progress_granularity == 0))
                    {
                       last_per = (int)per;
                       if (!(progress(im, (int)per, 0, last_y, w, i)))
                         {
                            rc = 2;
                            goto quit;
                         }
                       last_y = i;
                    }
               }


  cid_parse_font_matrix( CID_Face     face,
                         CID_Parser*  parser )
  {
    CID_FaceDict  dict;
    FT_Face       root = (FT_Face)&face->root;
    FT_Fixed      temp[6];
    FT_Fixed      temp_scale;

    if ( parser->num_dict >= 0 && parser->num_dict < face->cid.num_dicts )
     {
       FT_Matrix*  matrix;
       FT_Vector*  offset;

       dict   = face->cid.font_dicts + parser->num_dict;
       matrix = &dict->font_matrix;
       offset = &dict->font_offset;

      (void)cid_parser_to_fixed_array( parser, 6, temp, 3 );

       temp_scale = FT_ABS( temp[3] );

       /* Set Units per EM based on FontMatrix values.  We set the value to */
       /* 1000 / temp_scale, because temp_scale was already multiplied by   */
       /* 1000 (in t1_tofixed, from psobjs.c).                              */
        temp[5] = FT_DivFix( temp[5], temp_scale );
        temp[3] = 0x10000L;
      }

      matrix->xx = temp[0];
      matrix->yx = temp[1];
      matrix->xy = temp[2];
      matrix->yy = temp[3];
         temp[2] = FT_DivFix( temp[2], temp_scale );
         temp[4] = FT_DivFix( temp[4], temp_scale );
         temp[5] = FT_DivFix( temp[5], temp_scale );
        temp[3] = 0x10000L;
       }

The (1) t1_parse_font_matrix function in type1/t1load.c, (2) cid_parse_font_matrix function in cid/cidload.c, (3) t42_parse_font_matrix function in type42/t42parse.c, and (4) ps_parser_load_field function in psaux/psobjs.c in FreeType before 2.5.4 do not check return values, which allows remote attackers to cause a denial of service (uninitialized memory access and application crash) or possibly have unspecified other impact via a crafted font.


  cid_parse_font_matrix( CID_Face     face,
                         CID_Parser*  parser )
  {
    CID_FaceDict  dict;
    FT_Face       root = (FT_Face)&face->root;
    FT_Fixed      temp[6];
    FT_Fixed      temp_scale;

    if ( parser->num_dict >= 0 && parser->num_dict < face->cid.num_dicts )
     {
       FT_Matrix*  matrix;
       FT_Vector*  offset;
      FT_Int      result;

       dict   = face->cid.font_dicts + parser->num_dict;
       matrix = &dict->font_matrix;
       offset = &dict->font_offset;

      result = cid_parser_to_fixed_array( parser, 6, temp, 3 );

      if ( result < 6 )
        return FT_THROW( Invalid_File_Format );

       temp_scale = FT_ABS( temp[3] );

      if ( temp_scale == 0 )
      {
        FT_ERROR(( "cid_parse_font_matrix: invalid font matrix\n" ));
        return FT_THROW( Invalid_File_Format );
      }

       /* Set Units per EM based on FontMatrix values.  We set the value to */
       /* 1000 / temp_scale, because temp_scale was already multiplied by   */
       /* 1000 (in t1_tofixed, from psobjs.c).                              */
        temp[5] = FT_DivFix( temp[5], temp_scale );
        temp[3] = 0x10000L;
      }

      matrix->xx = temp[0];
      matrix->yx = temp[1];
      matrix->xy = temp[2];
      matrix->yy = temp[3];
         temp[2] = FT_DivFix( temp[2], temp_scale );
         temp[4] = FT_DivFix( temp[4], temp_scale );
         temp[5] = FT_DivFix( temp[5], temp_scale );
        temp[3] = temp[3] < 0 ? -0x10000L : 0x10000L;
       }


  t1_parse_font_matrix( T1_Face    face,
                        T1_Loader  loader )
  {
    T1_Parser   parser = &loader->parser;
    FT_Matrix*  matrix = &face->type1.font_matrix;
    FT_Vector*  offset = &face->type1.font_offset;
    FT_Face     root   = (FT_Face)&face->root;
    FT_Fixed    temp[6];
    FT_Fixed    temp_scale;
    FT_Int      result;

     result = T1_ToFixedArray( parser, 6, temp, 3 );

    if ( result < 0 )
     {
       parser->root.error = FT_THROW( Invalid_File_Format );
       return;
    }

    temp_scale = FT_ABS( temp[3] );

    if ( temp_scale == 0 )
    {
      FT_ERROR(( "t1_parse_font_matrix: invalid font matrix\n" ));
      parser->root.error = FT_THROW( Invalid_File_Format );
      return;
    }

    /* Set Units per EM based on FontMatrix values.  We set the value to */
    /* 1000 / temp_scale, because temp_scale was already multiplied by   */
    /* 1000 (in t1_tofixed, from psobjs.c).                              */

    root->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale );

    /* we need to scale the values by 1.0/temp_scale */
    if ( temp_scale != 0x10000L )
    {
      temp[0] = FT_DivFix( temp[0], temp_scale );
      temp[1] = FT_DivFix( temp[1], temp_scale );
      temp[2] = FT_DivFix( temp[2], temp_scale );
      temp[4] = FT_DivFix( temp[4], temp_scale );
      temp[5] = FT_DivFix( temp[5], temp_scale );
      temp[3] = temp[3] < 0 ? -0x10000L : 0x10000L;
    }

    matrix->xx = temp[0];
    matrix->yx = temp[1];
    matrix->xy = temp[2];
    matrix->yy = temp[3];

    /* note that the offsets must be expressed in integer font units */
    offset->x = temp[4] >> 16;
    offset->y = temp[5] >> 16;
  }


  t1_parse_font_matrix( T1_Face    face,
                        T1_Loader  loader )
  {
    T1_Parser   parser = &loader->parser;
    FT_Matrix*  matrix = &face->type1.font_matrix;
    FT_Vector*  offset = &face->type1.font_offset;
    FT_Face     root   = (FT_Face)&face->root;
    FT_Fixed    temp[6];
    FT_Fixed    temp_scale;
    FT_Int      result;

     result = T1_ToFixedArray( parser, 6, temp, 3 );

    if ( result < 6 )
     {
       parser->root.error = FT_THROW( Invalid_File_Format );
       return;
    }

    temp_scale = FT_ABS( temp[3] );

    if ( temp_scale == 0 )
    {
      FT_ERROR(( "t1_parse_font_matrix: invalid font matrix\n" ));
      parser->root.error = FT_THROW( Invalid_File_Format );
      return;
    }

    /* Set Units per EM based on FontMatrix values.  We set the value to */
    /* 1000 / temp_scale, because temp_scale was already multiplied by   */
    /* 1000 (in t1_tofixed, from psobjs.c).                              */

    root->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale );

    /* we need to scale the values by 1.0/temp_scale */
    if ( temp_scale != 0x10000L )
    {
      temp[0] = FT_DivFix( temp[0], temp_scale );
      temp[1] = FT_DivFix( temp[1], temp_scale );
      temp[2] = FT_DivFix( temp[2], temp_scale );
      temp[4] = FT_DivFix( temp[4], temp_scale );
      temp[5] = FT_DivFix( temp[5], temp_scale );
      temp[3] = temp[3] < 0 ? -0x10000L : 0x10000L;
    }

    matrix->xx = temp[0];
    matrix->yx = temp[1];
    matrix->xy = temp[2];
    matrix->yy = temp[3];

    /* note that the offsets must be expressed in integer font units */
    offset->x = temp[4] >> 16;
    offset->y = temp[5] >> 16;
  }


  t42_parse_font_matrix( T42_Face    face,
                         T42_Loader  loader )
  {
    T42_Parser  parser = &loader->parser;
    FT_Matrix*  matrix = &face->type1.font_matrix;
    FT_Vector*  offset = &face->type1.font_offset;
     FT_Face     root   = (FT_Face)&face->root;
     FT_Fixed    temp[6];
     FT_Fixed    temp_scale;

    (void)T1_ToFixedArray( parser, 6, temp, 3 );

     temp_scale = FT_ABS( temp[3] );

     /* Set Units per EM based on FontMatrix values.  We set the value to */
     /* 1000 / temp_scale, because temp_scale was already multiplied by   */
     /* 1000 (in t1_tofixed, from psobjs.c).                              */
    matrix->xx = temp[0];
    matrix->yx = temp[1];
    matrix->xy = temp[2];
    matrix->yy = temp[3];

    /* note that the offsets must be expressed in integer font units */
    offset->x = temp[4] >> 16;
    offset->y = temp[5] >> 16;
       temp[2] = FT_DivFix( temp[2], temp_scale );
       temp[4] = FT_DivFix( temp[4], temp_scale );
       temp[5] = FT_DivFix( temp[5], temp_scale );
      temp[3] = 0x10000L;
     }


  t42_parse_font_matrix( T42_Face    face,
                         T42_Loader  loader )
  {
    T42_Parser  parser = &loader->parser;
    FT_Matrix*  matrix = &face->type1.font_matrix;
    FT_Vector*  offset = &face->type1.font_offset;
     FT_Face     root   = (FT_Face)&face->root;
     FT_Fixed    temp[6];
     FT_Fixed    temp_scale;
    FT_Int      result;

    result = T1_ToFixedArray( parser, 6, temp, 3 );

    if ( result < 6 )
    {
      parser->root.error = FT_THROW( Invalid_File_Format );
      return;
    }

     temp_scale = FT_ABS( temp[3] );

    if ( temp_scale == 0 )
    {
      FT_ERROR(( "t1_parse_font_matrix: invalid font matrix\n" ));
      parser->root.error = FT_THROW( Invalid_File_Format );
      return;
    }

     /* Set Units per EM based on FontMatrix values.  We set the value to */
     /* 1000 / temp_scale, because temp_scale was already multiplied by   */
     /* 1000 (in t1_tofixed, from psobjs.c).                              */
    matrix->xx = temp[0];
    matrix->yx = temp[1];
    matrix->xy = temp[2];
    matrix->yy = temp[3];

    /* note that the offsets must be expressed in integer font units */
    offset->x = temp[4] >> 16;
    offset->y = temp[5] >> 16;
       temp[2] = FT_DivFix( temp[2], temp_scale );
       temp[4] = FT_DivFix( temp[4], temp_scale );
       temp[5] = FT_DivFix( temp[5], temp_scale );
      temp[3] = temp[3] < 0 ? -0x10000L : 0x10000L;
     }


__imlib_Ellipse_DrawToData(int xc, int yc, int a, int b, DATA32 color,
                           DATA32 * dst, int dstw, int clx, int cly, int clw,
                           int clh, ImlibOp op, char dst_alpha, char blend)
{
   ImlibPointDrawFunction pfunc;
   int                 xx, yy, x, y, prev_x, prev_y, ty, by, lx, rx;
   DATA32              a2, b2, *tp, *bp;
   DATA64              dx, dy;

   if (A_VAL(&color) == 0xff)
      blend = 0;
   pfunc = __imlib_GetPointDrawFunction(op, dst_alpha, blend);
   if (!pfunc)
      return;

   xc -= clx;
   yc -= cly;
   dst += (dstw * cly) + clx;

   a2 = a * a;
   b2 = b * b;

   yy = b << 16;
   prev_y = b;

   dx = a2 * b;
   dy = 0;

   ty = yc - b - 1;
   by = yc + b;
   lx = xc - 1;
   rx = xc;

   tp = dst + (dstw * ty) + lx;
   bp = dst + (dstw * by) + lx;

   while (dy < dx)
     {
        int                 len;

        y = yy >> 16;
        y += ((yy - (y << 16)) >> 15);

        if (prev_y != y)
          {
             prev_y = y;
             dx -= a2;
             ty++;
             by--;
             tp += dstw;
             bp -= dstw;
          }

        len = rx - lx;

        if (IN_RANGE(lx, ty, clw, clh))
           pfunc(color, tp);
        if (IN_RANGE(rx, ty, clw, clh))
           pfunc(color, tp + len);
        if (IN_RANGE(lx, by, clw, clh))
           pfunc(color, bp);
         if (IN_RANGE(rx, by, clw, clh))
            pfunc(color, bp + len);

         dy += b2;
         yy -= ((dy << 16) / dx);
         lx--;

        if ((lx < 0) && (rx > clw))
           return;
        if ((ty > clh) || (by < 0))
           return;
     }

   xx = yy;
   prev_x = xx >> 16;

   dx = dy;

   ty++;
   by--;

   tp += dstw;
   bp -= dstw;

   while (ty < yc)
     {
        int                 len;

        x = xx >> 16;
        x += ((xx - (x << 16)) >> 15);

        if (prev_x != x)
          {
             prev_x = x;
             dy += b2;
             lx--;
             rx++;
             tp--;
             bp--;
          }

        len = rx - lx;

        if (IN_RANGE(lx, ty, clw, clh))
           pfunc(color, tp);
        if (IN_RANGE(rx, ty, clw, clh))
           pfunc(color, tp + len);
        if (IN_RANGE(lx, by, clw, clh))
           pfunc(color, bp);
        if (IN_RANGE(rx, by, clw, clh))
           pfunc(color, bp + len);

         if (IN_RANGE(rx, by, clw, clh))
            pfunc(color, bp + len);

         dx -= a2;
         xx += ((dx << 16) / dy);
         ty++;
        if ((ty > clh) || (by < 0))
           return;
     }
}

imlib2 before 1.4.9 allows remote attackers to cause a denial of service (divide-by-zero error and application crash) by drawing a 2x1 ellipse.


__imlib_Ellipse_DrawToData(int xc, int yc, int a, int b, DATA32 color,
                           DATA32 * dst, int dstw, int clx, int cly, int clw,
                           int clh, ImlibOp op, char dst_alpha, char blend)
{
   ImlibPointDrawFunction pfunc;
   int                 xx, yy, x, y, prev_x, prev_y, ty, by, lx, rx;
   DATA32              a2, b2, *tp, *bp;
   DATA64              dx, dy;

   if (A_VAL(&color) == 0xff)
      blend = 0;
   pfunc = __imlib_GetPointDrawFunction(op, dst_alpha, blend);
   if (!pfunc)
      return;

   xc -= clx;
   yc -= cly;
   dst += (dstw * cly) + clx;

   a2 = a * a;
   b2 = b * b;

   yy = b << 16;
   prev_y = b;

   dx = a2 * b;
   dy = 0;

   ty = yc - b - 1;
   by = yc + b;
   lx = xc - 1;
   rx = xc;

   tp = dst + (dstw * ty) + lx;
   bp = dst + (dstw * by) + lx;

   while (dy < dx)
     {
        int                 len;

        y = yy >> 16;
        y += ((yy - (y << 16)) >> 15);

        if (prev_y != y)
          {
             prev_y = y;
             dx -= a2;
             ty++;
             by--;
             tp += dstw;
             bp -= dstw;
          }

        len = rx - lx;

        if (IN_RANGE(lx, ty, clw, clh))
           pfunc(color, tp);
        if (IN_RANGE(rx, ty, clw, clh))
           pfunc(color, tp + len);
        if (IN_RANGE(lx, by, clw, clh))
           pfunc(color, bp);
         if (IN_RANGE(rx, by, clw, clh))
            pfunc(color, bp + len);

        if (dx < 1)
           dx = 1;

         dy += b2;
         yy -= ((dy << 16) / dx);
         lx--;

        if ((lx < 0) && (rx > clw))
           return;
        if ((ty > clh) || (by < 0))
           return;
     }

   xx = yy;
   prev_x = xx >> 16;

   dx = dy;

   ty++;
   by--;

   tp += dstw;
   bp -= dstw;

   while (ty < yc)
     {
        int                 len;

        x = xx >> 16;
        x += ((xx - (x << 16)) >> 15);

        if (prev_x != x)
          {
             prev_x = x;
             dy += b2;
             lx--;
             rx++;
             tp--;
             bp--;
          }

        len = rx - lx;

        if (IN_RANGE(lx, ty, clw, clh))
           pfunc(color, tp);
        if (IN_RANGE(rx, ty, clw, clh))
           pfunc(color, tp + len);
        if (IN_RANGE(lx, by, clw, clh))
           pfunc(color, bp);
        if (IN_RANGE(rx, by, clw, clh))
           pfunc(color, bp + len);

         if (IN_RANGE(rx, by, clw, clh))
            pfunc(color, bp + len);

        if (dy < 1)
           dy = 1;

         dx -= a2;
         xx += ((dx << 16) / dy);
         ty++;
        if ((ty > clh) || (by < 0))
           return;
     }
}


Bug fix for 64 bit HP-UX.

Submitted by: Karsten Spang <ks@bellesystems.com>

RSA *RSA_generate_key(int bits, unsigned long e_value,
	     void (*callback)(int,int,void *), void *cb_arg)
	{
	RSA *rsa=NULL;
	BIGNUM *r0=NULL,*r1=NULL,*r2=NULL,*r3=NULL,*tmp;
	int bitsp,bitsq,ok= -1,n=0,i;
	BN_CTX *ctx=NULL,*ctx2=NULL;

	ctx=BN_CTX_new();
	if (ctx == NULL) goto err;
	ctx2=BN_CTX_new();
	if (ctx2 == NULL) goto err;
	BN_CTX_start(ctx);
	r0 = BN_CTX_get(ctx);
	r1 = BN_CTX_get(ctx);
	r2 = BN_CTX_get(ctx);
	r3 = BN_CTX_get(ctx);
	if (r3 == NULL) goto err;

	bitsp=(bits+1)/2;
	bitsq=bits-bitsp;
	rsa=RSA_new();
	if (rsa == NULL) goto err;

	/* set e */
	rsa->e=BN_new();
	if (rsa->e == NULL) goto err;

#if 1
	/* The problem is when building with 8, 16, or 32 BN_ULONG,
         * unsigned long can be larger */
        for (i=0; i<sizeof(unsigned long)*8; i++)
                {
               if (e_value & (1<<i))
                        BN_set_bit(rsa->e,i);
                }
 #else
	if (!BN_set_word(rsa->e,e_value)) goto err;
#endif

	/* generate p and q */
	for (;;)
		{
		rsa->p=BN_generate_prime(NULL,bitsp,0,NULL,NULL,callback,cb_arg);
		if (rsa->p == NULL) goto err;
		if (!BN_sub(r2,rsa->p,BN_value_one())) goto err;
		if (!BN_gcd(r1,r2,rsa->e,ctx)) goto err;
		if (BN_is_one(r1)) break;
		if (callback != NULL) callback(2,n++,cb_arg);
		BN_free(rsa->p);
		}
	if (callback != NULL) callback(3,0,cb_arg);
	for (;;)
		{
		rsa->q=BN_generate_prime(NULL,bitsq,0,NULL,NULL,callback,cb_arg);
		if (rsa->q == NULL) goto err;
		if (!BN_sub(r2,rsa->q,BN_value_one())) goto err;
		if (!BN_gcd(r1,r2,rsa->e,ctx)) goto err;
		if (BN_is_one(r1) && (BN_cmp(rsa->p,rsa->q) != 0))
			break;
		if (callback != NULL) callback(2,n++,cb_arg);
		BN_free(rsa->q);
		}
	if (callback != NULL) callback(3,1,cb_arg);
	if (BN_cmp(rsa->p,rsa->q) < 0)
		{
		tmp=rsa->p;
		rsa->p=rsa->q;
		rsa->q=tmp;
		}

	/* calculate n */
	rsa->n=BN_new();
	if (rsa->n == NULL) goto err;
	if (!BN_mul(rsa->n,rsa->p,rsa->q,ctx)) goto err;

	/* calculate d */
	if (!BN_sub(r1,rsa->p,BN_value_one())) goto err;	/* p-1 */
	if (!BN_sub(r2,rsa->q,BN_value_one())) goto err;	/* q-1 */
	if (!BN_mul(r0,r1,r2,ctx)) goto err;	/* (p-1)(q-1) */

/* should not be needed, since gcd(p-1,e) == 1 and gcd(q-1,e) == 1 */
/*	for (;;)
		{
		if (!BN_gcd(r3,r0,rsa->e,ctx)) goto err;
		if (BN_is_one(r3)) break;

		if (1)
			{
			if (!BN_add_word(rsa->e,2L)) goto err;
			continue;
			}
		RSAerr(RSA_F_RSA_GENERATE_KEY,RSA_R_BAD_E_VALUE);
		goto err;
		}
*/
	rsa->d=BN_mod_inverse(NULL,rsa->e,r0,ctx2);	/* d */
	if (rsa->d == NULL) goto err;

	/* calculate d mod (p-1) */
	rsa->dmp1=BN_new();
	if (rsa->dmp1 == NULL) goto err;
	if (!BN_mod(rsa->dmp1,rsa->d,r1,ctx)) goto err;

	/* calculate d mod (q-1) */
	rsa->dmq1=BN_new();
	if (rsa->dmq1 == NULL) goto err;
	if (!BN_mod(rsa->dmq1,rsa->d,r2,ctx)) goto err;

	/* calculate inverse of q mod p */
	rsa->iqmp=BN_mod_inverse(NULL,rsa->q,rsa->p,ctx2);
	if (rsa->iqmp == NULL) goto err;

	ok=1;
err:
	if (ok == -1)
		{
		RSAerr(RSA_F_RSA_GENERATE_KEY,ERR_LIB_BN);
		ok=0;
		}
	BN_CTX_end(ctx);
	BN_CTX_free(ctx);
	BN_CTX_free(ctx2);

	if (!ok)
		{
		if (rsa != NULL) RSA_free(rsa);
		return(NULL);
		}
	else
		return(rsa);
	}

crypto/rsa/rsa_gen.c in OpenSSL before 0.9.6 mishandles C bitwise-shift operations that exceed the size of an expression, which makes it easier for remote attackers to defeat cryptographic protection mechanisms by leveraging improper RSA key generation on 64-bit HP-UX platforms.


RSA *RSA_generate_key(int bits, unsigned long e_value,
	     void (*callback)(int,int,void *), void *cb_arg)
	{
	RSA *rsa=NULL;
	BIGNUM *r0=NULL,*r1=NULL,*r2=NULL,*r3=NULL,*tmp;
	int bitsp,bitsq,ok= -1,n=0,i;
	BN_CTX *ctx=NULL,*ctx2=NULL;

	ctx=BN_CTX_new();
	if (ctx == NULL) goto err;
	ctx2=BN_CTX_new();
	if (ctx2 == NULL) goto err;
	BN_CTX_start(ctx);
	r0 = BN_CTX_get(ctx);
	r1 = BN_CTX_get(ctx);
	r2 = BN_CTX_get(ctx);
	r3 = BN_CTX_get(ctx);
	if (r3 == NULL) goto err;

	bitsp=(bits+1)/2;
	bitsq=bits-bitsp;
	rsa=RSA_new();
	if (rsa == NULL) goto err;

	/* set e */
	rsa->e=BN_new();
	if (rsa->e == NULL) goto err;

#if 1
	/* The problem is when building with 8, 16, or 32 BN_ULONG,
         * unsigned long can be larger */
        for (i=0; i<sizeof(unsigned long)*8; i++)
                {
               if (e_value & (1UL<<i))
                        BN_set_bit(rsa->e,i);
                }
 #else
	if (!BN_set_word(rsa->e,e_value)) goto err;
#endif

	/* generate p and q */
	for (;;)
		{
		rsa->p=BN_generate_prime(NULL,bitsp,0,NULL,NULL,callback,cb_arg);
		if (rsa->p == NULL) goto err;
		if (!BN_sub(r2,rsa->p,BN_value_one())) goto err;
		if (!BN_gcd(r1,r2,rsa->e,ctx)) goto err;
		if (BN_is_one(r1)) break;
		if (callback != NULL) callback(2,n++,cb_arg);
		BN_free(rsa->p);
		}
	if (callback != NULL) callback(3,0,cb_arg);
	for (;;)
		{
		rsa->q=BN_generate_prime(NULL,bitsq,0,NULL,NULL,callback,cb_arg);
		if (rsa->q == NULL) goto err;
		if (!BN_sub(r2,rsa->q,BN_value_one())) goto err;
		if (!BN_gcd(r1,r2,rsa->e,ctx)) goto err;
		if (BN_is_one(r1) && (BN_cmp(rsa->p,rsa->q) != 0))
			break;
		if (callback != NULL) callback(2,n++,cb_arg);
		BN_free(rsa->q);
		}
	if (callback != NULL) callback(3,1,cb_arg);
	if (BN_cmp(rsa->p,rsa->q) < 0)
		{
		tmp=rsa->p;
		rsa->p=rsa->q;
		rsa->q=tmp;
		}

	/* calculate n */
	rsa->n=BN_new();
	if (rsa->n == NULL) goto err;
	if (!BN_mul(rsa->n,rsa->p,rsa->q,ctx)) goto err;

	/* calculate d */
	if (!BN_sub(r1,rsa->p,BN_value_one())) goto err;	/* p-1 */
	if (!BN_sub(r2,rsa->q,BN_value_one())) goto err;	/* q-1 */
	if (!BN_mul(r0,r1,r2,ctx)) goto err;	/* (p-1)(q-1) */

/* should not be needed, since gcd(p-1,e) == 1 and gcd(q-1,e) == 1 */
/*	for (;;)
		{
		if (!BN_gcd(r3,r0,rsa->e,ctx)) goto err;
		if (BN_is_one(r3)) break;

		if (1)
			{
			if (!BN_add_word(rsa->e,2L)) goto err;
			continue;
			}
		RSAerr(RSA_F_RSA_GENERATE_KEY,RSA_R_BAD_E_VALUE);
		goto err;
		}
*/
	rsa->d=BN_mod_inverse(NULL,rsa->e,r0,ctx2);	/* d */
	if (rsa->d == NULL) goto err;

	/* calculate d mod (p-1) */
	rsa->dmp1=BN_new();
	if (rsa->dmp1 == NULL) goto err;
	if (!BN_mod(rsa->dmp1,rsa->d,r1,ctx)) goto err;

	/* calculate d mod (q-1) */
	rsa->dmq1=BN_new();
	if (rsa->dmq1 == NULL) goto err;
	if (!BN_mod(rsa->dmq1,rsa->d,r2,ctx)) goto err;

	/* calculate inverse of q mod p */
	rsa->iqmp=BN_mod_inverse(NULL,rsa->q,rsa->p,ctx2);
	if (rsa->iqmp == NULL) goto err;

	ok=1;
err:
	if (ok == -1)
		{
		RSAerr(RSA_F_RSA_GENERATE_KEY,ERR_LIB_BN);
		ok=0;
		}
	BN_CTX_end(ctx);
	BN_CTX_free(ctx);
	BN_CTX_free(ctx2);

	if (!ok)
		{
		if (rsa != NULL) RSA_free(rsa);
		return(NULL);
		}
	else
		return(rsa);
	}


_gcry_ecc_ecdsa_sign (gcry_mpi_t input, ECC_secret_key *skey,
                      gcry_mpi_t r, gcry_mpi_t s,
                      int flags, int hashalgo)
{
  gpg_err_code_t rc = 0;
  int extraloops = 0;
  gcry_mpi_t k, dr, sum, k_1, x;
  mpi_point_struct I;
  gcry_mpi_t hash;
   const void *abuf;
   unsigned int abits, qbits;
   mpi_ec_t ctx;

   if (DBG_CIPHER)
     log_mpidump ("ecdsa sign hash  ", input );

  /* Convert the INPUT into an MPI if needed.  */
  rc = _gcry_dsa_normalize_hash (input, &hash, qbits);
  if (rc)
    return rc;
   if (rc)
     return rc;

   k = NULL;
   dr = mpi_alloc (0);
   sum = mpi_alloc (0);
    {
      do
        {
          mpi_free (k);
          k = NULL;
          if ((flags & PUBKEY_FLAG_RFC6979) && hashalgo)
            {
              /* Use Pornin's method for deterministic DSA.  If this
                 flag is set, it is expected that HASH is an opaque
                 MPI with the to be signed hash.  That hash is also
                 used as h1 from 3.2.a.  */
              if (!mpi_is_opaque (input))
                {
                  rc = GPG_ERR_CONFLICT;
                  goto leave;
                }

              abuf = mpi_get_opaque (input, &abits);
              rc = _gcry_dsa_gen_rfc6979_k (&k, skey->E.n, skey->d,
                                            abuf, (abits+7)/8,
                                            hashalgo, extraloops);
              if (rc)
                goto leave;
              extraloops++;
            }
          else
            k = _gcry_dsa_gen_k (skey->E.n, GCRY_STRONG_RANDOM);

          _gcry_mpi_ec_mul_point (&I, k, &skey->E.G, ctx);
          if (_gcry_mpi_ec_get_affine (x, NULL, &I, ctx))
            {
              if (DBG_CIPHER)
                log_debug ("ecc sign: Failed to get affine coordinates\n");
              rc = GPG_ERR_BAD_SIGNATURE;
              goto leave;
            }
          mpi_mod (r, x, skey->E.n);  /* r = x mod n */
        }
      while (!mpi_cmp_ui (r, 0));

      mpi_mulm (dr, skey->d, r, skey->E.n); /* dr = d*r mod n  */
      mpi_addm (sum, hash, dr, skey->E.n);  /* sum = hash + (d*r) mod n  */
      mpi_invm (k_1, k, skey->E.n);         /* k_1 = k^(-1) mod n  */
      mpi_mulm (s, k_1, sum, skey->E.n);    /* s = k^(-1)*(hash+(d*r)) mod n */
    }
  while (!mpi_cmp_ui (s, 0));

  if (DBG_CIPHER)
         }

Libgcrypt before 1.7.10 and 1.8.x before 1.8.3 allows a memory-cache side-channel attack on ECDSA signatures that can be mitigated through the use of blinding during the signing process in the _gcry_ecc_ecdsa_sign function in cipher/ecc-ecdsa.c, aka the Return Of the Hidden Number Problem or ROHNP. To discover an ECDSA key, the attacker needs access to either the local machine or a different virtual machine on the same physical host.


_gcry_ecc_ecdsa_sign (gcry_mpi_t input, ECC_secret_key *skey,
                      gcry_mpi_t r, gcry_mpi_t s,
                      int flags, int hashalgo)
{
  gpg_err_code_t rc = 0;
  int extraloops = 0;
  gcry_mpi_t k, dr, sum, k_1, x;
  mpi_point_struct I;
  gcry_mpi_t hash;
   const void *abuf;
   unsigned int abits, qbits;
   mpi_ec_t ctx;
  gcry_mpi_t b;                /* Random number needed for blinding.  */
  gcry_mpi_t bi;               /* multiplicative inverse of B.        */

   if (DBG_CIPHER)
     log_mpidump ("ecdsa sign hash  ", input );

  /* Convert the INPUT into an MPI if needed.  */
  rc = _gcry_dsa_normalize_hash (input, &hash, qbits);
  if (rc)
    return rc;
   if (rc)
     return rc;

  b  = mpi_snew (qbits);
  bi = mpi_snew (qbits);
  do
    {
      _gcry_mpi_randomize (b, qbits, GCRY_WEAK_RANDOM);
      mpi_mod (b, b, skey->E.n);
    }
  while (!mpi_invm (bi, b, skey->E.n));

   k = NULL;
   dr = mpi_alloc (0);
   sum = mpi_alloc (0);
    {
      do
        {
          mpi_free (k);
          k = NULL;
          if ((flags & PUBKEY_FLAG_RFC6979) && hashalgo)
            {
              /* Use Pornin's method for deterministic DSA.  If this
                 flag is set, it is expected that HASH is an opaque
                 MPI with the to be signed hash.  That hash is also
                 used as h1 from 3.2.a.  */
              if (!mpi_is_opaque (input))
                {
                  rc = GPG_ERR_CONFLICT;
                  goto leave;
                }

              abuf = mpi_get_opaque (input, &abits);
              rc = _gcry_dsa_gen_rfc6979_k (&k, skey->E.n, skey->d,
                                            abuf, (abits+7)/8,
                                            hashalgo, extraloops);
              if (rc)
                goto leave;
              extraloops++;
            }
          else
            k = _gcry_dsa_gen_k (skey->E.n, GCRY_STRONG_RANDOM);

          _gcry_mpi_ec_mul_point (&I, k, &skey->E.G, ctx);
          if (_gcry_mpi_ec_get_affine (x, NULL, &I, ctx))
            {
              if (DBG_CIPHER)
                log_debug ("ecc sign: Failed to get affine coordinates\n");
              rc = GPG_ERR_BAD_SIGNATURE;
              goto leave;
            }
          mpi_mod (r, x, skey->E.n);  /* r = x mod n */
        }
      while (!mpi_cmp_ui (r, 0));

      mpi_mulm (dr, skey->d, r, skey->E.n); /* dr = d*r mod n  */
      mpi_addm (sum, hash, dr, skey->E.n);  /* sum = hash + (d*r) mod n  */
      mpi_invm (k_1, k, skey->E.n);         /* k_1 = k^(-1) mod n  */
      mpi_mulm (s, k_1, sum, skey->E.n);    /* s = k^(-1)*(hash+(d*r)) mod n */
    }
  while (!mpi_cmp_ui (s, 0));

  if (DBG_CIPHER)
         }


Fix heap buffer overflow in fgetwln()

In the function fgetwln() there's a 4 byte heap overflow.

There is a while loop that has this check to see whether there's still
enough space in the buffer:

		if (!fb->len || wused > fb->len) {

If this is true more memory gets allocated. However this test won't be
true if wused == fb->len, but at that point wused already points out
of the buffer. Some lines later there's a write to the buffer:

		fb->wbuf[wused++] = wc;

This bug was found with the help of address sanitizer.

Warned-by: ASAN
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=93881
Signed-off-by: Guillem Jover <guillem@hadrons.org>

fgetwln(FILE *stream, size_t *lenp)
{
	struct filewbuf *fb;
	wint_t wc;
	size_t wused = 0;

	/* Try to diminish the possibility of several fgetwln() calls being
	 * used on different streams, by using a pool of buffers per file. */
	fb = &fb_pool[fb_pool_cur];
	if (fb->fp != stream && fb->fp != NULL) {
		fb_pool_cur++;
		fb_pool_cur %= FILEWBUF_POOL_ITEMS;
		fb = &fb_pool[fb_pool_cur];
	}
 	fb->fp = stream;

 	while ((wc = fgetwc(stream)) != WEOF) {
		if (!fb->len || wused > fb->len) {
 			wchar_t *wp;

 			if (fb->len)
				fb->len *= 2;
			else
				fb->len = FILEWBUF_INIT_LEN;

			wp = reallocarray(fb->wbuf, fb->len, sizeof(wchar_t));
			if (wp == NULL) {
				wused = 0;
				break;
			}
			fb->wbuf = wp;
		}

		fb->wbuf[wused++] = wc;

		if (wc == L'\n')
			break;
	}

	*lenp = wused;
	return wused ? fb->wbuf : NULL;
}

Off-by-one vulnerability in the fgetwln function in libbsd before 0.8.2 allows attackers to have unspecified impact via unknown vectors, which trigger a heap-based buffer overflow.


fgetwln(FILE *stream, size_t *lenp)
{
	struct filewbuf *fb;
	wint_t wc;
	size_t wused = 0;

	/* Try to diminish the possibility of several fgetwln() calls being
	 * used on different streams, by using a pool of buffers per file. */
	fb = &fb_pool[fb_pool_cur];
	if (fb->fp != stream && fb->fp != NULL) {
		fb_pool_cur++;
		fb_pool_cur %= FILEWBUF_POOL_ITEMS;
		fb = &fb_pool[fb_pool_cur];
	}
 	fb->fp = stream;

 	while ((wc = fgetwc(stream)) != WEOF) {
		if (!fb->len || wused >= fb->len) {
 			wchar_t *wp;

 			if (fb->len)
				fb->len *= 2;
			else
				fb->len = FILEWBUF_INIT_LEN;

			wp = reallocarray(fb->wbuf, fb->len, sizeof(wchar_t));
			if (wp == NULL) {
				wused = 0;
				break;
			}
			fb->wbuf = wp;
		}

		fb->wbuf[wused++] = wc;

		if (wc == L'\n')
			break;
	}

	*lenp = wused;
	return wused ? fb->wbuf : NULL;
}


Fix for TLS record tampering bug CVE-2013-4353

static void ssl3_take_mac(SSL *s)
        {
        const char *sender;
        int slen;
        if (s->state & SSL_ST_CONNECT)
                {
                sender=s->method->ssl3_enc->server_finished_label;
		sender=s->method->ssl3_enc->client_finished_label;
		slen=s->method->ssl3_enc->client_finished_label_len;
		}

	s->s3->tmp.peer_finish_md_len = s->method->ssl3_enc->final_finish_mac(s,
		sender,slen,s->s3->tmp.peer_finish_md);
	}

The ssl3_take_mac function in ssl/s3_both.c in OpenSSL 1.0.1 before 1.0.1f allows remote TLS servers to cause a denial of service (NULL pointer dereference and application crash) via a crafted Next Protocol Negotiation record in a TLS handshake.


static void ssl3_take_mac(SSL *s)
        {
        const char *sender;
        int slen;
       /* If no new cipher setup return immediately: other functions will
        * set the appropriate error.
        */
       if (s->s3->tmp.new_cipher == NULL)
               return;
        if (s->state & SSL_ST_CONNECT)
                {
                sender=s->method->ssl3_enc->server_finished_label;
		sender=s->method->ssl3_enc->client_finished_label;
		slen=s->method->ssl3_enc->client_finished_label_len;
		}

	s->s3->tmp.peer_finish_md_len = s->method->ssl3_enc->final_finish_mac(s,
		sender,slen,s->s3->tmp.peer_finish_md);
	}


static int ctdb_tcp_listen_automatic(struct ctdb_context *ctdb)
{
	struct ctdb_tcp *ctcp = talloc_get_type(ctdb->private_data,
                                                struct ctdb_tcp);
         ctdb_sock_addr sock;
        int lock_fd, i;
       const char *lock_path = "/tmp/.ctdb_socket_lock";
        struct flock lock;
        int one = 1;
        int sock_size;
	struct tevent_fd *fde;

	/* If there are no nodes, then it won't be possible to find
	 * the first one.  Log a failure and short circuit the whole
	 * process.
	 */
	if (ctdb->num_nodes == 0) {
		DEBUG(DEBUG_CRIT,("No nodes available to attempt bind to - is the nodes file empty?\n"));
		return -1;
	}

	/* in order to ensure that we don't get two nodes with the
	   same adddress, we must make the bind() and listen() calls
	   atomic. The SO_REUSEADDR setsockopt only prevents double
	   binds if the first socket is in LISTEN state  */
	lock_fd = open(lock_path, O_RDWR|O_CREAT, 0666);
	if (lock_fd == -1) {
		DEBUG(DEBUG_CRIT,("Unable to open %s\n", lock_path));
		return -1;
	}

	lock.l_type = F_WRLCK;
	lock.l_whence = SEEK_SET;
	lock.l_start = 0;
	lock.l_len = 1;
	lock.l_pid = 0;

	if (fcntl(lock_fd, F_SETLKW, &lock) != 0) {
		DEBUG(DEBUG_CRIT,("Unable to lock %s\n", lock_path));
		close(lock_fd);
		return -1;
	}

	for (i=0; i < ctdb->num_nodes; i++) {
		if (ctdb->nodes[i]->flags & NODE_FLAGS_DELETED) {
			continue;
		}
		ZERO_STRUCT(sock);
		if (ctdb_tcp_get_address(ctdb,
				ctdb->nodes[i]->address.address,
				&sock) != 0) {
			continue;
		}

		switch (sock.sa.sa_family) {
		case AF_INET:
			sock.ip.sin_port = htons(ctdb->nodes[i]->address.port);
			sock_size = sizeof(sock.ip);
			break;
		case AF_INET6:
			sock.ip6.sin6_port = htons(ctdb->nodes[i]->address.port);
			sock_size = sizeof(sock.ip6);
			break;
		default:
			DEBUG(DEBUG_ERR, (__location__ " unknown family %u\n",
				sock.sa.sa_family));
			continue;
		}
#ifdef HAVE_SOCK_SIN_LEN
		sock.ip.sin_len = sock_size;
#endif

		ctcp->listen_fd = socket(sock.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
		if (ctcp->listen_fd == -1) {
			ctdb_set_error(ctdb, "socket failed\n");
			continue;
		}

		set_close_on_exec(ctcp->listen_fd);

	        setsockopt(ctcp->listen_fd,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));

		if (bind(ctcp->listen_fd, (struct sockaddr * )&sock, sock_size) == 0) {
			break;
		}

		if (errno == EADDRNOTAVAIL) {
			DEBUG(DEBUG_DEBUG,(__location__ " Failed to bind() to socket. %s(%d)\n",
					strerror(errno), errno));
		} else {
			DEBUG(DEBUG_ERR,(__location__ " Failed to bind() to socket. %s(%d)\n",
					strerror(errno), errno));
		}
	}

	if (i == ctdb->num_nodes) {
		DEBUG(DEBUG_CRIT,("Unable to bind to any of the node addresses - giving up\n"));
		goto failed;
	}
	ctdb->address.address = talloc_strdup(ctdb, ctdb->nodes[i]->address.address);
	ctdb->address.port    = ctdb->nodes[i]->address.port;
	ctdb->name = talloc_asprintf(ctdb, "%s:%u",
				     ctdb->address.address,
				     ctdb->address.port);
	ctdb->pnn = ctdb->nodes[i]->pnn;
	DEBUG(DEBUG_INFO,("ctdb chose network address %s:%u pnn %u\n",
		 ctdb->address.address,
		 ctdb->address.port,
		 ctdb->pnn));

	if (listen(ctcp->listen_fd, 10) == -1) {
		goto failed;
	}

	fde = event_add_fd(ctdb->ev, ctcp, ctcp->listen_fd, EVENT_FD_READ,
			   ctdb_listen_event, ctdb);
	tevent_fd_set_auto_close(fde);

	close(lock_fd);

	return 0;

failed:
	close(lock_fd);
	close(ctcp->listen_fd);
	ctcp->listen_fd = -1;
	return -1;
}

ctdb before 2.3 in OpenSUSE 12.3 and 13.1 does not create temporary files securely, which has unspecified impact related to "several temp file vulnerabilities" in (1) tcp/tcp_connect.c, (2) server/eventscript.c, (3) tools/ctdb_diagnostics, (4) config/gdb_backtrace, and (5) include/ctdb_private.h.


static int ctdb_tcp_listen_automatic(struct ctdb_context *ctdb)
{
	struct ctdb_tcp *ctcp = talloc_get_type(ctdb->private_data,
                                                struct ctdb_tcp);
         ctdb_sock_addr sock;
        int lock_fd, i;
       const char *lock_path = VARDIR "/run/ctdb/.socket_lock";
        struct flock lock;
        int one = 1;
        int sock_size;
	struct tevent_fd *fde;

	/* If there are no nodes, then it won't be possible to find
	 * the first one.  Log a failure and short circuit the whole
	 * process.
	 */
	if (ctdb->num_nodes == 0) {
		DEBUG(DEBUG_CRIT,("No nodes available to attempt bind to - is the nodes file empty?\n"));
		return -1;
	}

	/* in order to ensure that we don't get two nodes with the
	   same adddress, we must make the bind() and listen() calls
	   atomic. The SO_REUSEADDR setsockopt only prevents double
	   binds if the first socket is in LISTEN state  */
	lock_fd = open(lock_path, O_RDWR|O_CREAT, 0666);
	if (lock_fd == -1) {
		DEBUG(DEBUG_CRIT,("Unable to open %s\n", lock_path));
		return -1;
	}

	lock.l_type = F_WRLCK;
	lock.l_whence = SEEK_SET;
	lock.l_start = 0;
	lock.l_len = 1;
	lock.l_pid = 0;

	if (fcntl(lock_fd, F_SETLKW, &lock) != 0) {
		DEBUG(DEBUG_CRIT,("Unable to lock %s\n", lock_path));
		close(lock_fd);
		return -1;
	}

	for (i=0; i < ctdb->num_nodes; i++) {
		if (ctdb->nodes[i]->flags & NODE_FLAGS_DELETED) {
			continue;
		}
		ZERO_STRUCT(sock);
		if (ctdb_tcp_get_address(ctdb,
				ctdb->nodes[i]->address.address,
				&sock) != 0) {
			continue;
		}

		switch (sock.sa.sa_family) {
		case AF_INET:
			sock.ip.sin_port = htons(ctdb->nodes[i]->address.port);
			sock_size = sizeof(sock.ip);
			break;
		case AF_INET6:
			sock.ip6.sin6_port = htons(ctdb->nodes[i]->address.port);
			sock_size = sizeof(sock.ip6);
			break;
		default:
			DEBUG(DEBUG_ERR, (__location__ " unknown family %u\n",
				sock.sa.sa_family));
			continue;
		}
#ifdef HAVE_SOCK_SIN_LEN
		sock.ip.sin_len = sock_size;
#endif

		ctcp->listen_fd = socket(sock.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
		if (ctcp->listen_fd == -1) {
			ctdb_set_error(ctdb, "socket failed\n");
			continue;
		}

		set_close_on_exec(ctcp->listen_fd);

	        setsockopt(ctcp->listen_fd,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));

		if (bind(ctcp->listen_fd, (struct sockaddr * )&sock, sock_size) == 0) {
			break;
		}

		if (errno == EADDRNOTAVAIL) {
			DEBUG(DEBUG_DEBUG,(__location__ " Failed to bind() to socket. %s(%d)\n",
					strerror(errno), errno));
		} else {
			DEBUG(DEBUG_ERR,(__location__ " Failed to bind() to socket. %s(%d)\n",
					strerror(errno), errno));
		}
	}

	if (i == ctdb->num_nodes) {
		DEBUG(DEBUG_CRIT,("Unable to bind to any of the node addresses - giving up\n"));
		goto failed;
	}
	ctdb->address.address = talloc_strdup(ctdb, ctdb->nodes[i]->address.address);
	ctdb->address.port    = ctdb->nodes[i]->address.port;
	ctdb->name = talloc_asprintf(ctdb, "%s:%u",
				     ctdb->address.address,
				     ctdb->address.port);
	ctdb->pnn = ctdb->nodes[i]->pnn;
	DEBUG(DEBUG_INFO,("ctdb chose network address %s:%u pnn %u\n",
		 ctdb->address.address,
		 ctdb->address.port,
		 ctdb->pnn));

	if (listen(ctcp->listen_fd, 10) == -1) {
		goto failed;
	}

	fde = event_add_fd(ctdb->ev, ctcp, ctcp->listen_fd, EVENT_FD_READ,
			   ctdb_listen_event, ctdb);
	tevent_fd_set_auto_close(fde);

	close(lock_fd);

	return 0;

failed:
	close(lock_fd);
	close(ctcp->listen_fd);
	ctcp->listen_fd = -1;
	return -1;
}


get_cdtext_generic (void *p_user_data)
{
  generic_img_private_t *p_env = p_user_data;
  uint8_t *p_cdtext_data = NULL;
  size_t  len;

  if (!p_env) return NULL;

  if (p_env->b_cdtext_error) return NULL;

  if (NULL == p_env->cdtext) {
    p_cdtext_data = read_cdtext_generic (p_env);

    if (NULL != p_cdtext_data) {
      len = CDIO_MMC_GET_LEN16(p_cdtext_data)-2;
      p_env->cdtext = cdtext_init();

       if(len <= 0 || 0 != cdtext_data_init (p_env->cdtext, &p_cdtext_data[4], len)) {
         p_env->b_cdtext_error = true;
        cdtext_destroy (p_env->cdtext);
         free(p_env->cdtext);
         p_env->cdtext = NULL;
       }
      }

      free(p_cdtext_data);
    }
  }

An issue was discovered in GNU libcdio before 2.0.0. There is a double free in get_cdtext_generic() in lib/driver/_cdio_generic.c.


get_cdtext_generic (void *p_user_data)
{
  generic_img_private_t *p_env = p_user_data;
  uint8_t *p_cdtext_data = NULL;
  size_t  len;

  if (!p_env) return NULL;

  if (p_env->b_cdtext_error) return NULL;

  if (NULL == p_env->cdtext) {
    p_cdtext_data = read_cdtext_generic (p_env);

    if (NULL != p_cdtext_data) {
      len = CDIO_MMC_GET_LEN16(p_cdtext_data)-2;
      p_env->cdtext = cdtext_init();

       if(len <= 0 || 0 != cdtext_data_init (p_env->cdtext, &p_cdtext_data[4], len)) {
         p_env->b_cdtext_error = true;
         free(p_env->cdtext);
         p_env->cdtext = NULL;
       }
      }

      free(p_cdtext_data);
    }
  }


modprobe,rmmod: reject module names with slashes

function                                             old     new   delta
add_probe                                             86     113     +27

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>

static void add_probe(const char *name)
 {
 	struct module_entry *m;

 	m = get_or_add_modentry(name);
 	if (!(option_mask32 & (OPT_REMOVE | OPT_SHOW_DEPS))
 	 && (m->flags & MODULE_FLAG_LOADED)
	 && strncmp(m->modname, "symbol:", 7) == 0
	) {
		G.need_symbols = 1;
	}
}

The add_probe function in modutils/modprobe.c in BusyBox before 1.23.0 allows local users to bypass intended restrictions on loading kernel modules via a / (slash) character in a module name, as demonstrated by an "ifconfig /usbserial up" command or a "mount -t /snd_pcm none /" command.


static void add_probe(const char *name)
 {
 	struct module_entry *m;

	/*
	 * get_or_add_modentry() strips path from name and works
	 * on remaining basename.
	 * This would make "rmmod dir/name" and "modprobe dir/name"
	 * to work like "rmmod name" and "modprobe name",
	 * which is wrong, and can be abused via implicit modprobing:
	 * "ifconfig /usbserial up" tries to modprobe netdev-/usbserial.
	 */
	if (strchr(name, '/'))
		bb_error_msg_and_die("malformed module name '%s'", name);

 	m = get_or_add_modentry(name);
 	if (!(option_mask32 & (OPT_REMOVE | OPT_SHOW_DEPS))
 	 && (m->flags & MODULE_FLAG_LOADED)
	 && strncmp(m->modname, "symbol:", 7) == 0
	) {
		G.need_symbols = 1;
	}
}


CatalogueRescan (FontPathElementPtr fpe)
{
    CataloguePtr	cat = fpe->private;
    char		link[MAXFONTFILENAMELEN];
    char		dest[MAXFONTFILENAMELEN];
    char		*attrib;
    FontPathElementPtr	subfpe;
    struct stat		statbuf;
    const char		*path;
    DIR			*dir;
    struct dirent	*entry;
    int			len;
    int			pathlen;

    path = fpe->name + strlen(CataloguePrefix);
    if (stat(path, &statbuf) < 0 || !S_ISDIR(statbuf.st_mode))
	return BadFontPath;

    if (statbuf.st_mtime <= cat->mtime)
	return Successful;

    dir = opendir(path);
    if (dir == NULL)
    {
	xfree(cat);
	return BadFontPath;
    }

    CatalogueUnrefFPEs (fpe);
     while (entry = readdir(dir), entry != NULL)
     {
 	snprintf(link, sizeof link, "%s/%s", path, entry->d_name);
	len = readlink(link, dest, sizeof dest);
 	if (len < 0)
 	    continue;
	dest[len] = '\0';

	if (dest[0] != '/')
	{
	   pathlen = strlen(path);
	   memmove(dest + pathlen + 1, dest, sizeof dest - pathlen - 1);
	   memcpy(dest, path, pathlen);
	   memcpy(dest + pathlen, "/", 1);
	   len += pathlen + 1;
	}

	attrib = strchr(link, ':');
	if (attrib && len + strlen(attrib) < sizeof dest)
	{
	    memcpy(dest + len, attrib, strlen(attrib));
	    len += strlen(attrib);
	}

	subfpe = xalloc(sizeof *subfpe);
	if (subfpe == NULL)
	    continue;

	/* The fonts returned by OpenFont will point back to the
	 * subfpe they come from.  So set the type of the subfpe to
	 * what the catalogue fpe was assigned, so calls to CloseFont
	 * (which uses font->fpe->type) goes to CatalogueCloseFont. */
	subfpe->type = fpe->type;
	subfpe->name_length = len;
	subfpe->name = xalloc (len + 1);
	if (subfpe == NULL)
	{
	    xfree(subfpe);
	    continue;
	}

	memcpy(subfpe->name, dest, len);
	subfpe->name[len] = '\0';

	/* The X server will manipulate the subfpe ref counts
	 * associated with the font in OpenFont and CloseFont, so we
	 * have to make sure it's valid. */
	subfpe->refcount = 1;

	if (FontFileInitFPE (subfpe) != Successful)
	{
	    xfree(subfpe->name);
	    xfree(subfpe);
	    continue;
	}

	if (CatalogueAddFPE(cat, subfpe) != Successful)
	{
	    FontFileFreeFPE (subfpe);
	    xfree(subfpe);
	    continue;
	}
    }

    closedir(dir);

    qsort(cat->fpeList,
	  cat->fpeCount, sizeof cat->fpeList[0], ComparePriority);

    cat->mtime = statbuf.st_mtime;

    return Successful;
}

A single byte overflow in catalogue.c in X.Org libXfont 1.3.1 allows remote attackers to have unspecified impact.


CatalogueRescan (FontPathElementPtr fpe)
{
    CataloguePtr	cat = fpe->private;
    char		link[MAXFONTFILENAMELEN];
    char		dest[MAXFONTFILENAMELEN];
    char		*attrib;
    FontPathElementPtr	subfpe;
    struct stat		statbuf;
    const char		*path;
    DIR			*dir;
    struct dirent	*entry;
    int			len;
    int			pathlen;

    path = fpe->name + strlen(CataloguePrefix);
    if (stat(path, &statbuf) < 0 || !S_ISDIR(statbuf.st_mode))
	return BadFontPath;

    if (statbuf.st_mtime <= cat->mtime)
	return Successful;

    dir = opendir(path);
    if (dir == NULL)
    {
	xfree(cat);
	return BadFontPath;
    }

    CatalogueUnrefFPEs (fpe);
     while (entry = readdir(dir), entry != NULL)
     {
 	snprintf(link, sizeof link, "%s/%s", path, entry->d_name);
	len = readlink(link, dest, sizeof dest - 1);
 	if (len < 0)
 	    continue;
	dest[len] = '\0';

	if (dest[0] != '/')
	{
	   pathlen = strlen(path);
	   memmove(dest + pathlen + 1, dest, sizeof dest - pathlen - 1);
	   memcpy(dest, path, pathlen);
	   memcpy(dest + pathlen, "/", 1);
	   len += pathlen + 1;
	}

	attrib = strchr(link, ':');
	if (attrib && len + strlen(attrib) < sizeof dest)
	{
	    memcpy(dest + len, attrib, strlen(attrib));
	    len += strlen(attrib);
	}

	subfpe = xalloc(sizeof *subfpe);
	if (subfpe == NULL)
	    continue;

	/* The fonts returned by OpenFont will point back to the
	 * subfpe they come from.  So set the type of the subfpe to
	 * what the catalogue fpe was assigned, so calls to CloseFont
	 * (which uses font->fpe->type) goes to CatalogueCloseFont. */
	subfpe->type = fpe->type;
	subfpe->name_length = len;
	subfpe->name = xalloc (len + 1);
	if (subfpe == NULL)
	{
	    xfree(subfpe);
	    continue;
	}

	memcpy(subfpe->name, dest, len);
	subfpe->name[len] = '\0';

	/* The X server will manipulate the subfpe ref counts
	 * associated with the font in OpenFont and CloseFont, so we
	 * have to make sure it's valid. */
	subfpe->refcount = 1;

	if (FontFileInitFPE (subfpe) != Successful)
	{
	    xfree(subfpe->name);
	    xfree(subfpe);
	    continue;
	}

	if (CatalogueAddFPE(cat, subfpe) != Successful)
	{
	    FontFileFreeFPE (subfpe);
	    xfree(subfpe);
	    continue;
	}
    }

    closedir(dir);

    qsort(cat->fpeList,
	  cat->fpeCount, sizeof cat->fpeList[0], ComparePriority);

    cat->mtime = statbuf.st_mtime;

    return Successful;
}


  tt_cmap14_validate( FT_Byte*      table,
                      FT_Validator  valid )
  {
    FT_Byte*  p;
    FT_ULong  length;
    FT_ULong  num_selectors;

    if ( table + 2 + 4 + 4 > valid->limit )
      FT_INVALID_TOO_SHORT;

    p             = table + 2;
    length        = TT_NEXT_ULONG( p );
    num_selectors = TT_NEXT_ULONG( p );

    if ( length > (FT_ULong)( valid->limit - table ) ||
         /* length < 10 + 11 * num_selectors ? */
         length < 10                                 ||
         ( length - 10 ) / 11 < num_selectors        )
      FT_INVALID_TOO_SHORT;

    /* check selectors, they must be in increasing order */
    {
      /* we start lastVarSel at 1 because a variant selector value of 0
       * isn't valid.
       */
      FT_ULong  n, lastVarSel = 1;

      for ( n = 0; n < num_selectors; n++ )
      {
        FT_ULong  varSel    = TT_NEXT_UINT24( p );
        FT_ULong  defOff    = TT_NEXT_ULONG( p );
        FT_ULong  nondefOff = TT_NEXT_ULONG( p );

        if ( defOff >= length || nondefOff >= length )
          FT_INVALID_TOO_SHORT;

        if ( varSel < lastVarSel )
          FT_INVALID_DATA;

        lastVarSel = varSel + 1;

        /* check the default table (these glyphs should be reached     */
         /* through the normal Unicode cmap, no GIDs, just check order) */
         if ( defOff != 0 )
         {
          FT_Byte*  defp      = table + defOff;
          FT_ULong  numRanges = TT_NEXT_ULONG( defp );
           FT_ULong  i;
          FT_ULong  lastBase  = 0;

           /* defp + numRanges * 4 > valid->limit ? */
           if ( numRanges > (FT_ULong)( valid->limit - defp ) / 4 )
             FT_INVALID_TOO_SHORT;

            if ( base + cnt >= 0x110000UL )              /* end of Unicode */
              FT_INVALID_DATA;

            if ( base < lastBase )
              FT_INVALID_DATA;

            lastBase = base + cnt + 1U;
          }
        }

        /* and the non-default table (these glyphs are specified here) */
        if ( nondefOff != 0 )
        {
          FT_Byte*  ndp         = table + nondefOff;
          FT_ULong  numMappings = TT_NEXT_ULONG( ndp );
         /* and the non-default table (these glyphs are specified here) */
         if ( nondefOff != 0 )
         {
          FT_Byte*  ndp         = table + nondefOff;
          FT_ULong  numMappings = TT_NEXT_ULONG( ndp );
          FT_ULong  i, lastUni  = 0;

          /* numMappings * 4 > (FT_ULong)( valid->limit - ndp ) ? */
          if ( numMappings > ( (FT_ULong)( valid->limit - ndp ) ) / 4 )
             FT_INVALID_TOO_SHORT;

           for ( i = 0; i < numMappings; ++i )

            lastUni = uni + 1U;

            if ( valid->level >= FT_VALIDATE_TIGHT    &&
                 gid >= TT_VALID_GLYPH_COUNT( valid ) )
              FT_INVALID_GLYPH_ID;
          }
        }
      }
    }

FreeType before 2.6.2 has a heap-based buffer over-read in tt_cmap14_validate in sfnt/ttcmap.c.