From c8855746aec2a9b732502da0ca3258b4e701c61a Mon Sep 17 00:00:00 2001
From: Peter Harris <pharris@opentext.com>
Date: Mon, 7 Apr 2014 14:25:02 -0400
Subject: [PATCH:libXfont] Fix buffer read overrun
"FreeType" is only eight bytes long. The atom "FreeType\x00\x??" is
probably not what the author intended.
Signed-off-by: Peter Harris <pharris@opentext.com>
Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com>
---
src/FreeType/ftfuncs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/FreeType/ftfuncs.c b/src/FreeType/ftfuncs.c
index 65efefc..a4969d1 100644
--- a/src/FreeType/ftfuncs.c
+++ b/src/FreeType/ftfuncs.c
@@ -1867,7 +1867,7 @@ FreeTypeAddProperties(FTFontPtr font, FontScalablePtr vals, FontInfoPtr info,
i++;
info->props[i].name = MakeAtom("RASTERIZER_NAME", 15, TRUE);
- info->props[i].value = MakeAtom("FreeType", 10, TRUE);
+ info->props[i].value = MakeAtom("FreeType", 8, TRUE);
info->isStringProp[i] = 1;
i++;
--
1.7.9.2
From 371f8582a33235afa1b61d76e4fe98bdc9d7c083 Mon Sep 17 00:00:00 2001
From: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Sun, 20 Apr 2014 17:59:14 -0700
Subject: [PATCH:libXfont 01/16] Check if pointer returned by BufFileCreate is
NULL before writing to it
Fixes clang analyzer warning:
bufio.c:165:13: warning: Access to field 'bufp' results in a dereference
of a null pointer (loaded from variable 'f')
f->bufp = f->buffer;
~ ^
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
Reviewed-by: Thomas Klausner <wiz@NetBSD.org>
(cherry picked from commit c77a0784bdfc8c178f0742689cf6ae02a2fce37f)
---
src/fontfile/bufio.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/fontfile/bufio.c b/src/fontfile/bufio.c
index 34b7f36..d8d4f29 100644
--- a/src/fontfile/bufio.c
+++ b/src/fontfile/bufio.c
@@ -162,8 +162,10 @@ BufFileOpenWrite (int fd)
setmode(fd,O_BINARY);
#endif
f = BufFileCreate ((char *)(long) fd, 0, BufFileRawFlush, 0, BufFileFlush);
- f->bufp = f->buffer;
- f->left = BUFFILESIZE;
+ if (f != NULL) {
+ f->bufp = f->buffer;
+ f->left = BUFFILESIZE;
+ }
return f;
}
--
1.7.9.2
From 0a37bf2d9977db81573f300b0dc203df8fe108b5 Mon Sep 17 00:00:00 2001
From: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Fri, 25 Apr 2014 23:01:11 -0700
Subject: [PATCH:libXfont 05/16] CVE-2014-0209: integer overflow of realloc()
size in FontFileAddEntry()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
FontFileReadDirectory() opens a fonts.dir file, and reads over every
line in an fscanf loop. For each successful entry read (font name,
file name) a call is made to FontFileAddFontFile().
FontFileAddFontFile() will add a font file entry (for the font name
and file) each time it’s called, by calling FontFileAddEntry().
FontFileAddEntry() will do the actual adding. If the table it has
to add to is full, it will do a realloc, adding 100 more entries
to the table size without checking to see if that will overflow the
int used to store the size.
Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Reviewed-by: Matthieu Herrb <matthieu@herrb.eu>
(cherry picked from commit 2f5e57317339c526e6eaee1010b0e2ab8089c42e)
---
src/fontfile/fontdir.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/fontfile/fontdir.c b/src/fontfile/fontdir.c
index ef7ffa5..7271603 100644
--- a/src/fontfile/fontdir.c
+++ b/src/fontfile/fontdir.c
@@ -177,6 +177,11 @@ FontFileAddEntry(FontTablePtr table, FontEntryPtr prototype)
if (table->sorted)
return (FontEntryPtr) 0; /* "cannot" happen */
if (table->used == table->size) {
+ if (table->size >= ((INT32_MAX / sizeof(FontEntryRec)) - 100))
+ /* If we've read so many entries we're going to ask for 2gb
+ or more of memory, something is so wrong with this font
+ directory that we should just give up before we overflow. */
+ return NULL;
newsize = table->size + 100;
entry = realloc(table->entries, newsize * sizeof(FontEntryRec));
if (!entry)
--
1.7.9.2
From 26643c0c3f4e53945516e20e00dfbb4d69a39c65 Mon Sep 17 00:00:00 2001
From: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Fri, 25 Apr 2014 23:01:48 -0700
Subject: [PATCH:libXfont 06/16] CVE-2014-0209: integer overflow of realloc()
size in lexAlias()
lexAlias() reads from a file in a loop. It does this by starting with a
64 byte buffer. If that size limit is hit, it does a realloc of the
buffer size << 1, basically doubling the needed length every time the
length limit is hit.
Eventually, this will shift out to 0 (for a length of ~4gig), and that
length will be passed on to realloc(). A length of 0 (with a valid
pointer) causes realloc to free the buffer on most POSIX platforms,
but the caller will still have a pointer to it, leading to use after
free issues.
Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Reviewed-by: Matthieu Herrb <matthieu@herrb.eu>
(cherry picked from commit 05c8020a49416dd8b7510cbba45ce4f3fc81a7dc)
---
src/fontfile/dirfile.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/fontfile/dirfile.c b/src/fontfile/dirfile.c
index 0d34db9..639310c 100644
--- a/src/fontfile/dirfile.c
+++ b/src/fontfile/dirfile.c
@@ -42,6 +42,7 @@ in this Software without prior written authorization from The Open Group.
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
+#include <limits.h>
static Bool AddFileNameAliases ( FontDirectoryPtr dir );
static int ReadFontAlias ( char *directory, Bool isFile,
@@ -374,6 +375,9 @@ lexAlias(FILE *file, char **lexToken)
int nsize;
char *nbuf;
+ if (tokenSize >= (INT_MAX >> 2))
+ /* Stop before we overflow */
+ return EALLOC;
nsize = tokenSize ? (tokenSize << 1) : 64;
nbuf = realloc(tokenBuf, nsize);
if (!nbuf)
--
1.7.9.2
From 23dcf6b1da8b5088856aef12b4a3f4581836f63a Mon Sep 17 00:00:00 2001
From: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Fri, 25 Apr 2014 23:02:00 -0700
Subject: [PATCH:libXfont 07/16] CVE-2014-0210: unvalidated length in
_fs_recv_conn_setup()
The connection setup reply from the font server can include a list
of alternate servers to contact if this font server stops working.
The reply specifies a total size of all the font server names, and
then provides a list of names. _fs_recv_conn_setup() allocated the
specified total size for copying the names to, but didn't check to
make sure it wasn't copying more data to that buffer than the size
it had allocated.
Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Reviewed-by: Matthieu Herrb <matthieu@herrb.eu>
(cherry picked from commit 891e084b26837162b12f841060086a105edde86d)
---
src/fc/fserve.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/src/fc/fserve.c b/src/fc/fserve.c
index 92f90b2..46418bd 100644
--- a/src/fc/fserve.c
+++ b/src/fc/fserve.c
@@ -2784,7 +2784,7 @@ _fs_recv_conn_setup (FSFpePtr conn)
int ret = FSIO_ERROR;
fsConnSetup *setup;
FSFpeAltPtr alts;
- int i, alt_len;
+ unsigned int i, alt_len;
int setup_len;
char *alt_save, *alt_names;
@@ -2811,8 +2811,9 @@ _fs_recv_conn_setup (FSFpePtr conn)
}
if (setup->num_alternates)
{
+ size_t alt_name_len = setup->alternate_len << 2;
alts = malloc (setup->num_alternates * sizeof (FSFpeAltRec) +
- (setup->alternate_len << 2));
+ alt_name_len);
if (alts)
{
alt_names = (char *) (setup + 1);
@@ -2821,10 +2822,25 @@ _fs_recv_conn_setup (FSFpePtr conn)
{
alts[i].subset = alt_names[0];
alt_len = alt_names[1];
+ if (alt_len >= alt_name_len) {
+ /*
+ * Length is longer than setup->alternate_len
+ * told us to allocate room for, assume entire
+ * alternate list is corrupted.
+ */
+#ifdef DEBUG
+ fprintf (stderr,
+ "invalid alt list (length %lx >= %lx)\n",
+ (long) alt_len, (long) alt_name_len);
+#endif
+ free(alts);
+ return FSIO_ERROR;
+ }
alts[i].name = alt_save;
memcpy (alt_save, alt_names + 2, alt_len);
alt_save[alt_len] = '\0';
alt_save += alt_len + 1;
+ alt_name_len -= alt_len + 1;
alt_names += _fs_pad_length (alt_len + 2);
}
conn->numAlts = setup->num_alternates;
--
1.7.9.2
From 647d9ea15e34779afa442d362997d92488778907 Mon Sep 17 00:00:00 2001
From: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Fri, 25 Apr 2014 23:02:12 -0700
Subject: [PATCH:libXfont 08/16] CVE-2014-0210: unvalidated lengths when
reading replies from font server
Functions to handle replies to font server requests were casting replies
from the generic form to reply specific structs without first checking
that the reply was at least as long as the struct being cast to.
Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Reviewed-by: Matthieu Herrb <matthieu@herrb.eu>
(cherry picked from commit cbb64aef35960b2882be721f4b8fbaa0fb649d12)
---
src/fc/fserve.c | 44 ++++++++++++++++++++++++++++++++++++++------
1 file changed, 38 insertions(+), 6 deletions(-)
diff --git a/src/fc/fserve.c b/src/fc/fserve.c
index 46418bd..97b7659 100644
--- a/src/fc/fserve.c
+++ b/src/fc/fserve.c
@@ -91,6 +91,12 @@ in this Software without prior written authorization from The Open Group.
(pci)->descent || \
(pci)->characterWidth)
+/*
+ * SIZEOF(r) is in bytes, length fields in the protocol are in 32-bit words,
+ * so this converts for doing size comparisons.
+ */
+#define LENGTHOF(r) (SIZEOF(r) >> 2)
+
extern void ErrorF(const char *f, ...);
static int fs_read_glyphs ( FontPathElementPtr fpe, FSBlockDataPtr blockrec );
@@ -206,9 +212,22 @@ _fs_add_rep_log (FSFpePtr conn, fsGenericReply *rep)
rep->sequenceNumber,
conn->reqbuffer[i].opcode);
}
+
+#define _fs_reply_failed(rep, name, op) do { \
+ if (rep) { \
+ if (rep->type == FS_Error) \
+ fprintf (stderr, "Error: %d Request: %s\n", \
+ ((fsError *)rep)->request, #name); \
+ else \
+ fprintf (stderr, "Bad Length for %s Reply: %d %s %d\n", \
+ #name, rep->length, op, LENGTHOF(name)); \
+ } \
+} while (0)
+
#else
#define _fs_add_req_log(conn,op) ((conn)->current_seq++)
#define _fs_add_rep_log(conn,rep)
+#define _fs_reply_failed(rep,name,op)
#endif
static Bool
@@ -682,13 +701,15 @@ fs_read_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
int ret;
rep = (fsOpenBitmapFontReply *) fs_get_reply (conn, &ret);
- if (!rep || rep->type == FS_Error)
+ if (!rep || rep->type == FS_Error ||
+ (rep->length != LENGTHOF(fsOpenBitmapFontReply)))
{
if (ret == FSIO_BLOCK)
return StillWorking;
if (rep)
_fs_done_read (conn, rep->length << 2);
fs_cleanup_bfont (bfont);
+ _fs_reply_failed (rep, fsOpenBitmapFontReply, "!=");
return BadFontName;
}
@@ -824,13 +845,15 @@ fs_read_query_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
int ret;
rep = (fsQueryXInfoReply *) fs_get_reply (conn, &ret);
- if (!rep || rep->type == FS_Error)
+ if (!rep || rep->type == FS_Error ||
+ (rep->length < LENGTHOF(fsQueryXInfoReply)))
{
if (ret == FSIO_BLOCK)
return StillWorking;
if (rep)
_fs_done_read (conn, rep->length << 2);
fs_cleanup_bfont (bfont);
+ _fs_reply_failed (rep, fsQueryXInfoReply, "<");
return BadFontName;
}
@@ -951,13 +974,15 @@ fs_read_extent_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
FontInfoRec *fi = &bfont->pfont->info;
rep = (fsQueryXExtents16Reply *) fs_get_reply (conn, &ret);
- if (!rep || rep->type == FS_Error)
+ if (!rep || rep->type == FS_Error ||
+ (rep->length < LENGTHOF(fsQueryXExtents16Reply)))
{
if (ret == FSIO_BLOCK)
return StillWorking;
if (rep)
_fs_done_read (conn, rep->length << 2);
fs_cleanup_bfont (bfont);
+ _fs_reply_failed (rep, fsQueryXExtents16Reply, "<");
return BadFontName;
}
@@ -1823,13 +1848,15 @@ fs_read_glyphs(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
unsigned long minchar, maxchar;
rep = (fsQueryXBitmaps16Reply *) fs_get_reply (conn, &ret);
- if (!rep || rep->type == FS_Error)
+ if (!rep || rep->type == FS_Error ||
+ (rep->length < LENGTHOF(fsQueryXBitmaps16Reply)))
{
if (ret == FSIO_BLOCK)
return StillWorking;
if (rep)
_fs_done_read (conn, rep->length << 2);
err = AllocError;
+ _fs_reply_failed (rep, fsQueryXBitmaps16Reply, "<");
goto bail;
}
@@ -2232,12 +2259,14 @@ fs_read_list(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
int err;
rep = (fsListFontsReply *) fs_get_reply (conn, &ret);
- if (!rep || rep->type == FS_Error)
+ if (!rep || rep->type == FS_Error ||
+ (rep->length < LENGTHOF(fsListFontsReply)))
{
if (ret == FSIO_BLOCK)
return StillWorking;
if (rep)
_fs_done_read (conn, rep->length << 2);
+ _fs_reply_failed (rep, fsListFontsReply, "<");
return AllocError;
}
data = (char *) rep + SIZEOF (fsListFontsReply);
@@ -2356,12 +2385,15 @@ fs_read_list_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
_fs_free_props (&binfo->info);
rep = (fsListFontsWithXInfoReply *) fs_get_reply (conn, &ret);
- if (!rep || rep->type == FS_Error)
+ if (!rep || rep->type == FS_Error ||
+ ((rep->nameLength != 0) &&
+ (rep->length < LENGTHOF(fsListFontsWithXInfoReply))))
{
if (ret == FSIO_BLOCK)
return StillWorking;
binfo->status = FS_LFWI_FINISHED;
err = AllocError;
+ _fs_reply_failed (rep, fsListFontsWithXInfoReply, "<");
goto done;
}
/*
--
1.7.9.2
From 633005ac24a44dacaf6beb3ed240ae0ea7e022d7 Mon Sep 17 00:00:00 2001
From: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Fri, 25 Apr 2014 23:02:25 -0700
Subject: [PATCH:libXfont 09/16] CVE-2014-0211: Integer overflow in
fs_get_reply/_fs_start_read
fs_get_reply() would take any reply size, multiply it by 4 and pass to
_fs_start_read. If that size was bigger than the current reply buffer
size, _fs_start_read would add it to the existing buffer size plus the
buffer size increment constant and realloc the buffer to that result.
This math could overflow, causing the code to allocate a smaller
buffer than the amount it was about to read into that buffer from
the network. It could also succeed, allowing the remote font server
to cause massive allocations in the X server, possibly using up all
the address space in a 32-bit X server, allowing the triggering of
other bugs in code that fails to handle malloc failure properly.
This patch protects against both problems, by disconnecting any
font server trying to feed us more than (the somewhat arbitrary)
64 mb in a single reply.
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Reviewed-by: Matthieu Herrb <matthieu@herrb.eu>
(cherry picked from commit 0f1a5d372c143f91a602bdf10c917d7eabaee09b)
---
src/fc/fserve.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/src/fc/fserve.c b/src/fc/fserve.c
index 97b7659..bfd7dbe 100644
--- a/src/fc/fserve.c
+++ b/src/fc/fserve.c
@@ -97,6 +97,9 @@ in this Software without prior written authorization from The Open Group.
*/
#define LENGTHOF(r) (SIZEOF(r) >> 2)
+/* Somewhat arbitrary limit on maximum reply size we'll try to read. */
+#define MAX_REPLY_LENGTH ((64 * 1024 * 1024) >> 2)
+
extern void ErrorF(const char *f, ...);
static int fs_read_glyphs ( FontPathElementPtr fpe, FSBlockDataPtr blockrec );
@@ -619,6 +622,21 @@ fs_get_reply (FSFpePtr conn, int *error)
rep = (fsGenericReply *) buf;
+ /*
+ * Refuse to accept replies longer than a maximum reasonable length,
+ * before we pass to _fs_start_read, since it will try to resize the
+ * incoming connection buffer to this size. Also avoids integer overflow
+ * on 32-bit systems.
+ */
+ if (rep->length > MAX_REPLY_LENGTH)
+ {
+ ErrorF("fserve: reply length %d > MAX_REPLY_LENGTH, disconnecting"
+ " from font server\n", rep->length);
+ _fs_connection_died (conn);
+ *error = FSIO_ERROR;
+ return 0;
+ }
+
ret = _fs_start_read (conn, rep->length << 2, &buf);
if (ret != FSIO_READY)
{
--
1.7.9.2
From 8ca608bdb5a5af7ee705ae4c3725ac774a69018b Mon Sep 17 00:00:00 2001
From: Christos Zoulas <christos@NetBSD.org>
Date: Wed, 25 Feb 2015 21:39:30 +0100
Subject: [PATCH:libXfont 1/4] Set close-on-exec for font file I/O.
Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com>
Signed-off-by: Thomas Klausner <wiz@NetBSD.org>
(cherry picked from commit d9fda3d247942292a5f24694c22337c547006e11)
---
src/fontfile/fileio.c | 5 ++++-
src/fontfile/filewr.c | 12 +++++++-----
2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/src/fontfile/fileio.c b/src/fontfile/fileio.c
index 80af511..d44cecd 100644
--- a/src/fontfile/fileio.c
+++ b/src/fontfile/fileio.c
@@ -36,6 +36,9 @@ in this Software without prior written authorization from The Open Group.
#ifndef O_BINARY
#define O_BINARY O_RDONLY
#endif
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
FontFilePtr
FontFileOpen (const char *name)
@@ -44,7 +47,7 @@ FontFileOpen (const char *name)
int len;
BufFilePtr raw, cooked;
- fd = open (name, O_BINARY);
+ fd = open (name, O_BINARY|O_CLOEXEC);
if (fd < 0)
return 0;
raw = BufFileOpenRead (fd);
diff --git a/src/fontfile/filewr.c b/src/fontfile/filewr.c
index bcc7b1e..859a0be 100644
--- a/src/fontfile/filewr.c
+++ b/src/fontfile/filewr.c
@@ -33,17 +33,19 @@ in this Software without prior written authorization from The Open Group.
#endif
#include <X11/fonts/fntfilio.h>
#include <X11/Xos.h>
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
FontFilePtr
FontFileOpenWrite (const char *name)
{
int fd;
-#if defined(WIN32) || defined(__CYGWIN__)
- fd = open (name, O_CREAT|O_TRUNC|O_RDWR|O_BINARY, 0666);
-#else
- fd = creat (name, 0666);
-#endif
+ fd = open (name, O_CREAT|O_TRUNC|O_RDWR|O_BINARY|O_CLOEXEC, 0666);
if (fd < 0)
return 0;
return (FontFilePtr) BufFileOpenWrite (fd);
--
1.7.9.2
From 1cf5752474dd3959cdd992d8f4f40fffe10291d5 Mon Sep 17 00:00:00 2001
From: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Fri, 6 Feb 2015 15:50:45 -0800
Subject: [PATCH:libXfont 2/4] bdfReadProperties: property count needs range
check [CVE-2015-1802]
Avoid integer overflow or underflow when allocating memory arrays
by multiplying the number of properties reported for a BDF font.
Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
Reviewed-by: Julien Cristau <jcristau@debian.org>
(cherry picked from commit 2deda9906480f9c8ae07b8c2a5510cc7e4c59a8e)
---
src/bitmap/bdfread.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/bitmap/bdfread.c b/src/bitmap/bdfread.c
index 914a024..6387908 100644
--- a/src/bitmap/bdfread.c
+++ b/src/bitmap/bdfread.c
@@ -604,7 +604,9 @@ bdfReadProperties(FontFilePtr file, FontPtr pFont, bdfFileState *pState)
bdfError("missing 'STARTPROPERTIES'\n");
return (FALSE);
}
- if (sscanf((char *) line, "STARTPROPERTIES %d", &nProps) != 1) {
+ if ((sscanf((char *) line, "STARTPROPERTIES %d", &nProps) != 1) ||
+ (nProps <= 0) ||
+ (nProps > ((INT32_MAX / sizeof(FontPropRec)) - BDF_GENPROPS))) {
bdfError("bad 'STARTPROPERTIES'\n");
return (FALSE);
}
--
1.7.9.2
From 3b8dba7b48863d860a040cb6516f6f53028a9426 Mon Sep 17 00:00:00 2001
From: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Fri, 6 Feb 2015 15:54:00 -0800
Subject: [PATCH:libXfont 3/4] bdfReadCharacters: bailout if a char's bitmap
cannot be read [CVE-2015-1803]
Previously would charge on ahead with a NULL pointer in ci->bits, and
then crash later in FontCharInkMetrics() trying to access the bits.
Found with afl-1.23b.
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
Reviewed-by: Julien Cristau <jcristau@debian.org>
(cherry picked from commit 78c2e3d70d29698244f70164428bd2868c0ab34c)
---
src/bitmap/bdfread.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/bitmap/bdfread.c b/src/bitmap/bdfread.c
index 6387908..1b29b81 100644
--- a/src/bitmap/bdfread.c
+++ b/src/bitmap/bdfread.c
@@ -458,7 +458,10 @@ bdfReadCharacters(FontFilePtr file, FontPtr pFont, bdfFileState *pState,
ci->metrics.descent = -bb;
ci->metrics.characterWidth = wx;
ci->bits = NULL;
- bdfReadBitmap(ci, file, bit, byte, glyph, scan, bitmapsSizes);
+ if (!bdfReadBitmap(ci, file, bit, byte, glyph, scan, bitmapsSizes)) {
+ bdfError("could not read bitmap for character '%s'\n", charName);
+ goto BAILOUT;
+ }
ci++;
ndx++;
} else
--
1.7.9.2
From 6c60e85998252b641a50048a555de88bdaacd3c7 Mon Sep 17 00:00:00 2001
From: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Fri, 6 Mar 2015 22:54:58 -0800
Subject: [PATCH:libXfont 4/4] bdfReadCharacters: ensure metrics fit into
xCharInfo struct [CVE-2015-1804]
We use 32-bit ints to read from the bdf file, but then try to stick
into a 16-bit int in the xCharInfo struct, so make sure they won't
overflow that range.
Found by afl-1.24b.
v2: Verify that additions won't overflow 32-bit int range either.
v3: As Julien correctly observes, the previous check for bh & bw not
being < 0 reduces the number of cases we need to check for overflow.
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
Reviewed-by: Julien Cristau <jcristau@debian.org>
(cherry picked from commit 2351c83a77a478b49cba6beb2ad386835e264744)
---
src/bitmap/bdfread.c | 26 ++++++++++++++++++++++++--
1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/src/bitmap/bdfread.c b/src/bitmap/bdfread.c
index 1b29b81..a0ace8f 100644
--- a/src/bitmap/bdfread.c
+++ b/src/bitmap/bdfread.c
@@ -62,8 +62,16 @@ from The Open Group.
#if HAVE_STDINT_H
#include <stdint.h>
-#elif !defined(INT32_MAX)
-#define INT32_MAX 0x7fffffff
+#else
+# ifndef INT32_MAX
+# define INT32_MAX 0x7fffffff
+# endif
+# ifndef INT16_MAX
+# define INT16_MAX 0x7fff
+# endif
+# ifndef INT16_MIN
+# define INT16_MIN (0 - 0x8000)
+# endif
#endif
#define INDICES 256
@@ -417,6 +425,12 @@ bdfReadCharacters(FontFilePtr file, FontPtr pFont, bdfFileState *pState,
bdfError("DWIDTH y value must be zero\n");
goto BAILOUT;
}
+ /* xCharInfo metrics are stored as INT16 */
+ if ((wx < 0) || (wx > INT16_MAX)) {
+ bdfError("character '%s' has out of range width, %d\n",
+ charName, wx);
+ goto BAILOUT;
+ }
line = bdfGetLine(file, lineBuf, BDFLINELEN);
if ((!line) || (sscanf((char *) line, "BBX %d %d %d %d", &bw, &bh, &bl, &bb) != 4)) {
bdfError("bad 'BBX'\n");
@@ -427,6 +441,14 @@ bdfReadCharacters(FontFilePtr file, FontPtr pFont, bdfFileState *pState,
charName, bw, bh);
goto BAILOUT;
}
+ /* xCharInfo metrics are read as int, but stored as INT16 */
+ if ((bl > INT16_MAX) || (bl < INT16_MIN) ||
+ (bb > INT16_MAX) || (bb < INT16_MIN) ||
+ (bw > (INT16_MAX - bl)) || (bh > (INT16_MAX - bb))) {
+ bdfError("character '%s' has out of range metrics, %d %d %d %d\n",
+ charName, bl, (bl+bw), (bh+bb), -bb);
+ goto BAILOUT;
+ }
line = bdfGetLine(file, lineBuf, BDFLINELEN);
if ((line) && (bdfIsPrefix(line, "ATTRIBUTES"))) {
for (p = line + strlen("ATTRIBUTES ");
--
1.7.9.2