aboutsummaryrefslogtreecommitdiff
path: root/libXfont/src/fc/fserve.c
diff options
context:
space:
mode:
Diffstat (limited to 'libXfont/src/fc/fserve.c')
-rw-r--r--libXfont/src/fc/fserve.c540
1 files changed, 379 insertions, 161 deletions
diff --git a/libXfont/src/fc/fserve.c b/libXfont/src/fc/fserve.c
index b02b0b749..1e1093cd5 100644
--- a/libXfont/src/fc/fserve.c
+++ b/libXfont/src/fc/fserve.c
@@ -70,6 +70,7 @@ in this Software without prior written authorization from The Open Group.
#include "fservestr.h"
#include <X11/fonts/fontutil.h>
#include <errno.h>
+#include <limits.h>
#include <time.h>
#define Time_t time_t
@@ -84,28 +85,37 @@ in this Software without prior written authorization from The Open Group.
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
#define TimeCmp(a,c,b) ((int) ((a) - (b)) c 0)
-
+
#define NONZEROMETRICS(pci) ((pci)->leftSideBearing || \
(pci)->rightSideBearing || \
(pci)->ascent || \
(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)
+
+/* 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 );
static int fs_read_list ( FontPathElementPtr fpe, FSBlockDataPtr blockrec );
-static int fs_read_list_info ( FontPathElementPtr fpe,
+static int fs_read_list_info ( FontPathElementPtr fpe,
FSBlockDataPtr blockrec );
extern fd_set _fs_fd_mask;
-static void fs_block_handler ( pointer data, OSTimePtr wt,
+static void fs_block_handler ( pointer data, OSTimePtr wt,
pointer LastSelectMask );
static int fs_wakeup ( FontPathElementPtr fpe, unsigned long *mask );
/*
- * List of all FPEs
+ * List of all FPEs
*/
static FSFpePtr fs_fpes;
/*
@@ -114,7 +124,7 @@ static FSFpePtr fs_fpes;
static CARD32 fs_blockState;
static int _fs_restart_connection ( FSFpePtr conn );
-static void fs_send_query_bitmaps ( FontPathElementPtr fpe,
+static void fs_send_query_bitmaps ( FontPathElementPtr fpe,
FSBlockDataPtr blockrec );
static int fs_send_close_font ( FontPathElementPtr fpe, Font id );
static void fs_client_died ( pointer client, FontPathElementPtr fpe );
@@ -206,9 +216,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
@@ -240,7 +263,7 @@ _fs_client_resolution(FSFpePtr conn)
}
}
-/*
+/*
* close font server and remove any state associated with
* this connection - this includes any client records.
*/
@@ -251,8 +274,8 @@ fs_close_conn(FSFpePtr conn)
FSClientPtr client, nclient;
_fs_close_server (conn);
-
- for (client = conn->clients; client; client = nclient)
+
+ for (client = conn->clients; client; client = nclient)
{
nclient = client->next;
free (client);
@@ -308,7 +331,7 @@ fs_init_fpe(FontPathElementPtr fpe)
err = Successful;
}
}
-
+
if (err == Successful)
{
#ifdef NCD
@@ -348,7 +371,7 @@ static int
fs_free_fpe(FontPathElementPtr fpe)
{
FSFpePtr conn = (FSFpePtr) fpe->private, *prev;
-
+
/* unhook from chain of all font servers */
for (prev = &fs_fpes; *prev; prev = &(*prev)->next)
{
@@ -410,7 +433,7 @@ fs_new_block_rec(FontPathElementPtr fpe, pointer client, int type)
blockrec->type = type;
blockrec->depending = 0;
blockrec->next = (FSBlockDataPtr) 0;
-
+
/* stick it on the end of the list (since its expected last) */
for (prev = &conn->blockedRequests; *prev; prev = &(*prev)->next)
;
@@ -423,7 +446,7 @@ static void
_fs_set_pending_reply (FSFpePtr conn)
{
FSBlockDataPtr blockrec;
-
+
for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next)
if (blockrec->errcode == StillWorking)
break;
@@ -442,7 +465,7 @@ _fs_remove_block_rec(FSFpePtr conn, FSBlockDataPtr blockrec)
FSBlockDataPtr *prev;
for (prev = &conn->blockedRequests; *prev; prev = &(*prev)->next)
- if (*prev == blockrec)
+ if (*prev == blockrec)
{
*prev = blockrec->next;
break;
@@ -461,7 +484,7 @@ static void
_fs_signal_clients_depending(FSClientsDependingPtr *clients_depending)
{
FSClientsDependingPtr p;
-
+
while ((p = *clients_depending))
{
*clients_depending = p->next;
@@ -474,14 +497,14 @@ static int
_fs_add_clients_depending(FSClientsDependingPtr *clients_depending, pointer client)
{
FSClientsDependingPtr new, cd;
-
- for (; (cd = *clients_depending);
+
+ for (; (cd = *clients_depending);
clients_depending = &(*clients_depending)->next)
{
- if (cd->client == client)
+ if (cd->client == client)
return Suspended;
}
-
+
new = malloc (sizeof (FSClientsDependingRec));
if (!new)
return BadAlloc;
@@ -503,17 +526,17 @@ _fs_clean_aborted_blockrec(FSFpePtr conn, FSBlockDataPtr blockrec)
switch(blockrec->type) {
case FS_OPEN_FONT: {
FSBlockedFontPtr bfont = (FSBlockedFontPtr)blockrec->data;
-
+
fs_cleanup_bfont (bfont);
_fs_signal_clients_depending(&bfont->clients_depending);
break;
}
case FS_LOAD_GLYPHS: {
FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr)blockrec->data;
-
+
_fs_clean_aborted_loadglyphs(bglyph->pfont,
bglyph->num_expected_ranges,
- bglyph->expected_ranges);
+ bglyph->expected_ranges);
_fs_signal_clients_depending(&bglyph->clients_depending);
break;
}
@@ -550,12 +573,12 @@ fs_cleanup_bfont (FSBlockedFontPtr bfont)
if (bfont->pfont)
{
fsd = (FSFontDataRec *) bfont->pfont->fpePrivate;
-
+
/* make sure the FS knows we choked on it */
fs_send_close_font(bfont->pfont->fpe, bfont->fontid);
-
+
/*
- * Either unload the font if it's being opened for
+ * Either unload the font if it's being opened for
* the first time, or smash the generation field to
* mark this font as an orphan
*/
@@ -590,16 +613,31 @@ fs_get_reply (FSFpePtr conn, int *error)
*error = FSIO_BLOCK;
return 0;
}
-
+
ret = _fs_start_read (conn, sizeof (fsGenericReply), &buf);
if (ret != FSIO_READY)
{
*error = FSIO_BLOCK;
return 0;
}
-
+
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)
{
@@ -608,7 +646,7 @@ fs_get_reply (FSFpePtr conn, int *error)
}
*error = FSIO_READY;
-
+
return (fsGenericReply *) buf;
}
@@ -616,7 +654,7 @@ static Bool
fs_reply_ready (FSFpePtr conn)
{
fsGenericReply *rep;
-
+
if (conn->fs_fd == -1 || !FD_ISSET (conn->fs_fd, &_fs_fd_mask))
return FALSE;
if (fs_data_read (conn) < sizeof (fsGenericReply))
@@ -651,10 +689,10 @@ static int
fs_await_reply (FSFpePtr conn)
{
int ret;
-
+
if (conn->blockState & FS_COMPLETE_REPLY)
return FSIO_READY;
-
+
while (!fs_get_reply (conn, &ret))
{
if (ret != FSIO_BLOCK)
@@ -682,16 +720,18 @@ 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;
}
-
+
/* If we're not reopening a font and FS detected a duplicate font
open request, replace our reference to the new font with a
reference to an existing font (possibly one not finished
@@ -701,10 +741,10 @@ fs_read_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
if we we decide (in fs_read_query_info()) that we don't like what
we got. */
- if (rep->otherid && !(bfont->flags & FontReopen))
+ if (rep->otherid && !(bfont->flags & FontReopen))
{
fs_cleanup_bfont (bfont);
-
+
/* Find old font if we're completely done getting it from server. */
bfont->pfont = find_old_font(rep->otherid);
bfont->freeFont = FALSE;
@@ -715,12 +755,12 @@ fs_read_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
*/
for (blockOrig = conn->blockedRequests;
blockOrig;
- blockOrig = blockOrig->next)
+ blockOrig = blockOrig->next)
{
- if (blockOrig != blockrec && blockOrig->type == FS_OPEN_FONT)
+ if (blockOrig != blockrec && blockOrig->type == FS_OPEN_FONT)
{
origBfont = (FSBlockedFontPtr) blockOrig->data;
- if (origBfont->fontid == rep->otherid)
+ if (origBfont->fontid == rep->otherid)
{
blockrec->depending = blockOrig->depending;
blockOrig->depending = blockrec;
@@ -757,7 +797,7 @@ static Bool
fs_fonts_match (FontInfoPtr pInfo1, FontInfoPtr pInfo2)
{
int i;
-
+
if (pInfo1->firstCol != pInfo2->firstCol ||
pInfo1->lastCol != pInfo2->lastCol ||
pInfo1->firstRow != pInfo2->firstRow ||
@@ -815,6 +855,7 @@ fs_read_query_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
FSFpePtr conn = (FSFpePtr) fpe->private;
fsQueryXInfoReply *rep;
char *buf;
+ long bufleft; /* length of reply left to use */
fsPropInfo *pi;
fsPropOffset *po;
pointer pd;
@@ -824,16 +865,18 @@ 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;
}
-
+
/* If this is a reopen, accumulate the query info into a dummy
font and compare to our original data. */
if (bfont->flags & FontReopen)
@@ -843,27 +886,63 @@ fs_read_query_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
buf = (char *) rep;
buf += SIZEOF(fsQueryXInfoReply);
-
+
+ bufleft = rep->length << 2;
+ bufleft -= SIZEOF(fsQueryXInfoReply);
+
/* move the data over */
fsUnpack_XFontInfoHeader(rep, pInfo);
-
+
/* compute accelerators */
_fs_init_fontinfo(conn, pInfo);
/* Compute offsets into the reply */
+ if (bufleft < SIZEOF(fsPropInfo))
+ {
+ ret = -1;
+#ifdef DEBUG
+ fprintf(stderr, "fsQueryXInfo: bufleft (%ld) < SIZEOF(fsPropInfo)\n",
+ bufleft);
+#endif
+ goto bail;
+ }
pi = (fsPropInfo *) buf;
buf += SIZEOF (fsPropInfo);
-
+ bufleft -= SIZEOF(fsPropInfo);
+
+ if ((bufleft / SIZEOF(fsPropOffset)) < pi->num_offsets)
+ {
+ ret = -1;
+#ifdef DEBUG
+ fprintf(stderr,
+ "fsQueryXInfo: bufleft (%ld) / SIZEOF(fsPropOffset) < %d\n",
+ bufleft, pi->num_offsets);
+#endif
+ goto bail;
+ }
po = (fsPropOffset *) buf;
buf += pi->num_offsets * SIZEOF(fsPropOffset);
+ bufleft -= pi->num_offsets * SIZEOF(fsPropOffset);
+ if (bufleft < pi->data_len)
+ {
+ ret = -1;
+#ifdef DEBUG
+ fprintf(stderr,
+ "fsQueryXInfo: bufleft (%ld) < data_len (%d)\n",
+ bufleft, pi->data_len);
+#endif
+ goto bail;
+ }
pd = (pointer) buf;
buf += pi->data_len;
-
+ bufleft -= pi->data_len;
+
/* convert the properties and step over the reply */
ret = _fs_convert_props(pi, po, pd, pInfo);
+ bail:
_fs_done_read (conn, rep->length << 2);
-
+
if (ret == -1)
{
fs_cleanup_bfont (bfont);
@@ -889,7 +968,7 @@ fs_read_query_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
err = BadFontName;
}
_fs_free_props (pInfo);
-
+
return err;
}
@@ -904,14 +983,14 @@ fs_read_query_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
* Figure out if the whole font should get loaded right now.
*/
if (glyphCachingMode == CACHING_OFF ||
- (glyphCachingMode == CACHE_16_BIT_GLYPHS
+ (glyphCachingMode == CACHE_16_BIT_GLYPHS
&& !bfont->pfont->info.lastRow))
{
bfont->flags |= FontLoadAll;
}
-
+
/*
- * Ready to send the query bitmaps; the terminal font bit has
+ * Ready to send the query bitmaps; the terminal font bit has
* been computed and glyphCaching has been considered
*/
if (bfont->flags & FontLoadBitmaps)
@@ -927,7 +1006,7 @@ fs_read_query_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
*/
blockrec->sequenceNumber = bfont->queryExtentsSequence;
conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout;
-
+
return StillWorking;
}
@@ -951,16 +1030,18 @@ 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;
}
-
+
/* move the data over */
/* need separate inkMetrics for fixed font server protocol version */
numExtents = rep->num_extents;
@@ -970,9 +1051,28 @@ fs_read_extent_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
numInfos *= 2;
haveInk = TRUE;
}
- ci = pCI = malloc(sizeof(CharInfoRec) * numInfos);
+ if (numInfos >= (INT_MAX / sizeof(CharInfoRec))) {
+#ifdef DEBUG
+ fprintf(stderr,
+ "fsQueryXExtents16: numInfos (%d) >= %ld\n",
+ numInfos, (INT_MAX / sizeof(CharInfoRec)));
+#endif
+ pCI = NULL;
+ }
+ else if (numExtents > ((rep->length - LENGTHOF(fsQueryXExtents16Reply))
+ / LENGTHOF(fsXCharInfo))) {
+#ifdef DEBUG
+ fprintf(stderr,
+ "fsQueryXExtents16: numExtents (%d) > (%d - %d) / %d\n",
+ numExtents, rep->length,
+ LENGTHOF(fsQueryXExtents16Reply), LENGTHOF(fsXCharInfo));
+#endif
+ pCI = NULL;
+ }
+ else
+ pCI = malloc(sizeof(CharInfoRec) * numInfos);
- if (!pCI)
+ if (!pCI)
{
_fs_done_read (conn, rep->length << 2);
fs_cleanup_bfont(bfont);
@@ -987,10 +1087,10 @@ fs_read_extent_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
buf = (char *) rep;
buf += SIZEOF (fsQueryXExtents16Reply);
fsci = buf;
-
+
fsd->glyphs_to_get = 0;
ci = fsfont->inkMetrics;
- for (i = 0; i < numExtents; i++)
+ for (i = 0; i < numExtents; i++)
{
memcpy(&fscilocal, fsci, SIZEOF(fsXCharInfo)); /* align it */
_fs_convert_char_info(&fscilocal, &ci->metrics);
@@ -1030,7 +1130,7 @@ fs_read_extent_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
/* Done with reply */
_fs_done_read (conn, rep->length << 2);
-
+
/* build bitmap metrics, ImageRectMax style */
if (haveInk)
{
@@ -1098,7 +1198,7 @@ fs_read_extent_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
}
bfont->state = FS_GLYPHS_REPLY;
- if (bfont->flags & FontLoadBitmaps)
+ if (bfont->flags & FontLoadBitmaps)
{
/*
* Reset the blockrec for the next reply
@@ -1111,7 +1211,7 @@ fs_read_extent_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
}
#ifdef DEBUG
-static char *fs_open_states[] = {
+static const char *fs_open_states[] = {
"OPEN_REPLY ",
"INFO_REPLY ",
"EXTENT_REPLY",
@@ -1129,7 +1229,7 @@ fs_do_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
#ifdef DEBUG
fprintf (stderr, "fs_do_open_font state %s %s\n",
- fs_open_states[bfont->state],
+ fs_open_states[bfont->state],
((FSFontDataPtr) (bfont->pfont->fpePrivate))->name);
#endif
err = BadFontName;
@@ -1165,10 +1265,10 @@ fs_do_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
#ifdef DEBUG
fprintf (stderr, "fs_do_open_font err %d\n", err);
#endif
- if (err != StillWorking)
+ if (err != StillWorking)
{
bfont->state = FS_DONE_REPLY; /* for _fs_load_glyphs() */
- while ((blockrec = blockrec->depending))
+ while ((blockrec = blockrec->depending))
{
bfont = (FSBlockedFontPtr) blockrec->data;
bfont->state = FS_DONE_REPLY; /* for _fs_load_glyphs() */
@@ -1188,7 +1288,7 @@ void
_fs_unmark_block (FSFpePtr conn, CARD32 mask)
{
FSFpePtr c;
-
+
if (conn->blockState & mask)
{
conn->blockState &= ~mask;
@@ -1207,7 +1307,7 @@ fs_block_handler(pointer data, OSTimePtr wt, pointer LastSelectMask)
int soonest;
FSFpePtr conn;
- XFD_ORSET((fd_set *)LastSelectMask, (fd_set *)LastSelectMask,
+ XFD_ORSET((fd_set *)LastSelectMask, (fd_set *)LastSelectMask,
&_fs_fd_mask);
/*
* Flush all pending output
@@ -1280,7 +1380,7 @@ fs_block_handler(pointer data, OSTimePtr wt, pointer LastSelectMask)
static void
fs_handle_unexpected(FSFpePtr conn, fsGenericReply *rep)
{
- if (rep->type == FS_Event && rep->data1 == KeepAlive)
+ if (rep->type == FS_Event && rep->data1 == KeepAlive)
{
fsNoopReq req;
@@ -1302,27 +1402,27 @@ fs_read_reply (FontPathElementPtr fpe, pointer client)
int ret;
int err;
fsGenericReply *rep;
-
+
if ((rep = fs_get_reply (conn, &ret)))
{
_fs_add_rep_log (conn, rep);
- for (blockrec = conn->blockedRequests;
- blockrec;
- blockrec = blockrec->next)
+ for (blockrec = conn->blockedRequests;
+ blockrec;
+ blockrec = blockrec->next)
{
if (blockrec->sequenceNumber == rep->sequenceNumber)
break;
}
err = Successful;
- if (!blockrec)
+ if (!blockrec)
{
fs_handle_unexpected(conn, rep);
}
else
{
- /*
- * go read it, and if we're done,
- * wake up the appropriate client
+ /*
+ * go read it, and if we're done,
+ * wake up the appropriate client
*/
switch (blockrec->type) {
case FS_OPEN_FONT:
@@ -1343,7 +1443,7 @@ fs_read_reply (FontPathElementPtr fpe, pointer client)
err = blockrec->errcode;
if (err != StillWorking)
{
- while (blockrec)
+ while (blockrec)
{
blockrec->errcode = err;
if (client != blockrec->client)
@@ -1366,7 +1466,7 @@ fs_wakeup(FontPathElementPtr fpe, unsigned long *mask)
fd_set *LastSelectMask = (fd_set *) mask;
FSFpePtr conn = (FSFpePtr) fpe->private;
- /*
+ /*
* Don't continue if the fd is -1 (which will be true when the
* font server terminates
*/
@@ -1381,7 +1481,6 @@ fs_wakeup(FontPathElementPtr fpe, unsigned long *mask)
{
FSBlockDataPtr blockrec;
FSBlockedFontPtr bfont;
- FSBlockedListPtr blist;
static CARD32 lastState;
static FSBlockDataPtr lastBlock;
@@ -1400,12 +1499,11 @@ fs_wakeup(FontPathElementPtr fpe, unsigned long *mask)
blockrec->errcode,
blockrec->sequenceNumber,
fs_open_states[bfont->state],
- bfont->pfont ?
+ bfont->pfont ?
((FSFontDataPtr) (bfont->pfont->fpePrivate))->name :
"<freed>");
break;
case FS_LIST_FONTS:
- blist = (FSBlockedListPtr) blockrec->data;
fprintf (stderr, " Blocked list errcode %d sequence %d\n",
blockrec->errcode, blockrec->sequenceNumber);
break;
@@ -1418,7 +1516,7 @@ fs_wakeup(FontPathElementPtr fpe, unsigned long *mask)
}
}
}
-#endif
+#endif
return FALSE;
}
@@ -1446,7 +1544,7 @@ _fs_restart_connection(FSFpePtr conn)
FSBlockDataPtr block;
_fs_unmark_block (conn, FS_GIVE_UP);
- while ((block = (FSBlockDataPtr) conn->blockedRequests))
+ while ((block = (FSBlockDataPtr) conn->blockedRequests))
{
if (block->errcode == StillWorking)
{
@@ -1471,7 +1569,7 @@ _fs_giveup (FSFpePtr conn)
fprintf (stderr, "give up on FS \"%s\"\n", conn->servername);
#endif
_fs_mark_block (conn, FS_GIVE_UP);
- while ((block = (FSBlockDataPtr) conn->blockedRequests))
+ while ((block = (FSBlockDataPtr) conn->blockedRequests))
{
if (block->errcode == StillWorking)
{
@@ -1494,7 +1592,7 @@ _fs_do_blocked (FSFpePtr conn)
{
_fs_giveup (conn);
}
- else
+ else
{
if (conn->blockState & FS_BROKEN_CONNECTION)
{
@@ -1516,9 +1614,9 @@ _fs_do_blocked (FSFpePtr conn)
*/
/* ARGSUSED */
static int
-fs_send_open_font(pointer client, FontPathElementPtr fpe, Mask flags,
- char *name, int namelen,
- fsBitmapFormat format, fsBitmapFormatMask fmask,
+fs_send_open_font(pointer client, FontPathElementPtr fpe, Mask flags,
+ char *name, int namelen,
+ fsBitmapFormat format, fsBitmapFormatMask fmask,
XID id, FontPtr *ppfont)
{
FSFpePtr conn = (FSFpePtr) fpe->private;
@@ -1534,10 +1632,10 @@ fs_send_open_font(pointer client, FontPathElementPtr fpe, Mask flags,
if (conn->blockState & FS_GIVE_UP)
return BadFontName;
-
+
if (namelen <= 0 || namelen > sizeof (buf) - 1)
return BadFontName;
-
+
/*
* Get the font structure put together, either by reusing
* the existing one or creating a new one
@@ -1574,10 +1672,10 @@ fs_send_open_font(pointer client, FontPathElementPtr fpe, Mask flags,
font = fs_create_font (fpe, name, namelen, format, fmask);
if (!font)
return AllocError;
-
+
fsd = (FSFontDataPtr)font->fpePrivate;
}
-
+
/* make a new block record, and add it to the end of the list */
blockrec = fs_new_block_rec(font->fpe, client, FS_OPEN_FONT);
if (!blockrec)
@@ -1586,7 +1684,7 @@ fs_send_open_font(pointer client, FontPathElementPtr fpe, Mask flags,
(*font->unload_font) (font);
return AllocError;
}
-
+
/*
* Must check this before generating any protocol, otherwise we'll
* mess up a reconnect in progress
@@ -1596,7 +1694,7 @@ fs_send_open_font(pointer client, FontPathElementPtr fpe, Mask flags,
_fs_pending_reply (conn);
return Suspended;
}
-
+
fsd->generation = conn->generation;
bfont = (FSBlockedFontPtr) blockrec->data;
@@ -1626,17 +1724,17 @@ fs_send_open_font(pointer client, FontPathElementPtr fpe, Mask flags,
_fs_write_pad(conn, (char *) buf, namelen + 1);
blockrec->sequenceNumber = conn->current_seq;
-
+
inforeq.reqType = FS_QueryXInfo;
inforeq.pad = 0;
inforeq.id = fsd->fontid;
inforeq.length = SIZEOF(fsQueryXInfoReq) >> 2;
bfont->queryInfoSequence = conn->current_seq + 1;
-
+
_fs_add_req_log(conn, FS_QueryXInfo);
_fs_write(conn, (char *) &inforeq, SIZEOF(fsQueryXInfoReq));
-
+
if (!(bfont->flags & FontReopen))
{
extreq.reqType = FS_QueryXExtents16;
@@ -1644,15 +1742,15 @@ fs_send_open_font(pointer client, FontPathElementPtr fpe, Mask flags,
extreq.fid = fsd->fontid;
extreq.num_ranges = 0;
extreq.length = SIZEOF(fsQueryXExtents16Req) >> 2;
-
+
bfont->queryExtentsSequence = conn->current_seq + 1;
-
+
_fs_add_req_log(conn, FS_QueryXExtents16);
_fs_write(conn, (char *) &extreq, SIZEOF(fsQueryXExtents16Req));
}
-
+
#ifdef NCD
- if (configData.ExtendedFontDiags)
+ if (configData.ExtendedFontDiags)
{
memcpy(buf, name, MIN(256, namelen));
buf[MIN(256, namelen)] = '\0';
@@ -1661,7 +1759,7 @@ fs_send_open_font(pointer client, FontPathElementPtr fpe, Mask flags,
}
#endif
_fs_prepare_for_reply (conn);
-
+
err = blockrec->errcode;
if (bfont->flags & FontOpenSync)
{
@@ -1701,16 +1799,16 @@ fs_send_query_bitmaps(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
bitreq.num_ranges = 0;
bfont->queryBitmapsSequence = conn->current_seq + 1;
-
+
_fs_add_req_log(conn, FS_QueryXBitmaps16);
_fs_write(conn, (char *) &bitreq, SIZEOF(fsQueryXBitmaps16Req));
}
/* ARGSUSED */
static int
-fs_open_font(pointer client, FontPathElementPtr fpe, Mask flags,
- char *name, int namelen,
- fsBitmapFormat format, fsBitmapFormatMask fmask,
+fs_open_font(pointer client, FontPathElementPtr fpe, Mask flags,
+ char *name, int namelen,
+ fsBitmapFormat format, fsBitmapFormatMask fmask,
XID id, FontPtr *ppfont,
char **alias, FontPtr non_cachable_font)
{
@@ -1725,12 +1823,12 @@ fs_open_font(pointer client, FontPathElementPtr fpe, Mask flags,
*alias = (char *) 0;
for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next)
{
- if (blockrec->type == FS_OPEN_FONT && blockrec->client == client)
+ if (blockrec->type == FS_OPEN_FONT && blockrec->client == client)
{
err = blockrec->errcode;
if (err == StillWorking)
return Suspended;
-
+
bfont = (FSBlockedFontPtr) blockrec->data;
if (err == Successful)
*ppfont = bfont->pfont;
@@ -1809,6 +1907,7 @@ fs_read_glyphs(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
FontInfoPtr pfi = &pfont->info;
fsQueryXBitmaps16Reply *rep;
char *buf;
+ long bufleft; /* length of reply left to use */
fsOffset32 *ppbits;
fsOffset32 local_off;
char *off_adr;
@@ -1825,22 +1924,48 @@ 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;
}
buf = (char *) rep;
buf += SIZEOF (fsQueryXBitmaps16Reply);
+ bufleft = rep->length << 2;
+ bufleft -= SIZEOF (fsQueryXBitmaps16Reply);
+
+ if ((bufleft / SIZEOF (fsOffset32)) < rep->num_chars)
+ {
+#ifdef DEBUG
+ fprintf(stderr,
+ "fsQueryXBitmaps16: num_chars (%d) > bufleft (%ld) / %d\n",
+ rep->num_chars, bufleft, SIZEOF (fsOffset32));
+#endif
+ err = AllocError;
+ goto bail;
+ }
ppbits = (fsOffset32 *) buf;
buf += SIZEOF (fsOffset32) * (rep->num_chars);
+ bufleft -= SIZEOF (fsOffset32) * (rep->num_chars);
+ if (bufleft < rep->nbytes)
+ {
+#ifdef DEBUG
+ fprintf(stderr,
+ "fsQueryXBitmaps16: nbytes (%d) > bufleft (%ld)\n",
+ rep->nbytes, bufleft);
+#endif
+ err = AllocError;
+ goto bail;
+ }
pbitmaps = (pointer ) buf;
if (blockrec->type == FS_LOAD_GLYPHS)
@@ -1871,21 +1996,21 @@ fs_read_glyphs(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
}
off_adr = (char *)ppbits;
-
+
allbits = fs_alloc_glyphs (pfont, rep->nbytes);
-
+
if (!allbits)
{
err = AllocError;
goto bail;
}
-
+
#ifdef DEBUG
origallbits = allbits;
fprintf (stderr, "Reading %d glyphs in %d bytes for %s\n",
(int) rep->num_chars, (int) rep->nbytes, fsd->name);
#endif
-
+
for (i = 0; i < rep->num_chars; i++)
{
memcpy(&local_off, off_adr, SIZEOF(fsOffset32)); /* align it */
@@ -1898,7 +2023,9 @@ fs_read_glyphs(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
*/
if (NONZEROMETRICS(&fsdata->encoding[minchar].metrics))
{
- if (local_off.length)
+ if (local_off.length &&
+ (local_off.position < rep->nbytes) &&
+ (local_off.length <= (rep->nbytes - local_off.position)))
{
bits = allbits;
allbits += local_off.length;
@@ -1945,7 +2072,7 @@ bail:
}
static int
-fs_send_load_glyphs(pointer client, FontPtr pfont,
+fs_send_load_glyphs(pointer client, FontPtr pfont,
int nranges, fsRange *ranges)
{
FontPathElementPtr fpe = pfont->fpe;
@@ -1956,7 +2083,7 @@ fs_send_load_glyphs(pointer client, FontPtr pfont,
if (conn->blockState & FS_GIVE_UP)
return BadCharRange;
-
+
/* make a new block record, and add it to the end of the list */
blockrec = fs_new_block_rec(fpe, client, FS_LOAD_GLYPHS);
if (!blockrec)
@@ -1973,7 +2100,7 @@ fs_send_load_glyphs(pointer client, FontPtr pfont,
_fs_pending_reply (conn);
return Suspended;
}
-
+
/* send the request */
req.reqType = FS_QueryXBitmaps16;
req.fid = ((FSFontDataPtr) pfont->fpePrivate)->fontid;
@@ -1989,7 +2116,7 @@ fs_send_load_glyphs(pointer client, FontPtr pfont,
_fs_write(conn, (char *) &req, SIZEOF(fsQueryXBitmaps16Req));
blockrec->sequenceNumber = conn->current_seq;
-
+
/* Send ranges to the server... pack into a char array by hand
to avoid structure-packing portability problems and to
handle swapping for version1 protocol */
@@ -2039,7 +2166,7 @@ extern pointer serverClient; /* This could be any number that
client values. */
static int
-_fs_load_glyphs(pointer client, FontPtr pfont, Bool range_flag,
+_fs_load_glyphs(pointer client, FontPtr pfont, Bool range_flag,
unsigned int nchars, int item_size, unsigned char *data)
{
FSFpePtr conn = (FSFpePtr) pfont->fpe->private;
@@ -2095,7 +2222,7 @@ _fs_load_glyphs(pointer client, FontPtr pfont, Bool range_flag,
err = blockrec->errcode;
if (err == StillWorking)
return Suspended;
-
+
_fs_signal_clients_depending(&bfont->clients_depending);
_fs_remove_block_rec(conn, blockrec);
if (err != Successful)
@@ -2228,38 +2355,55 @@ fs_read_list(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
FSBlockedListPtr blist = (FSBlockedListPtr) blockrec->data;
fsListFontsReply *rep;
char *data;
+ long dataleft; /* length of reply left to use */
int length,
i,
ret;
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);
+ dataleft = (rep->length << 2) - SIZEOF (fsListFontsReply);
err = Successful;
/* copy data into FontPathRecord */
- for (i = 0; i < rep->nFonts; i++)
+ for (i = 0; i < rep->nFonts; i++)
{
+ if (dataleft < 1)
+ break;
length = *(unsigned char *)data++;
+ dataleft--; /* used length byte */
+ if (length > dataleft) {
+#ifdef DEBUG
+ fprintf(stderr,
+ "fsListFonts: name length (%d) > dataleft (%ld)\n",
+ length, dataleft);
+#endif
+ err = BadFontName;
+ break;
+ }
err = AddFontNamesName(blist->names, data, length);
if (err != Successful)
break;
data += length;
+ dataleft -= length;
}
_fs_done_read (conn, rep->length << 2);
return err;
}
static int
-fs_send_list_fonts(pointer client, FontPathElementPtr fpe, char *pattern,
+fs_send_list_fonts(pointer client, FontPathElementPtr fpe, char *pattern,
int patlen, int maxnames, FontNamesPtr newnames)
{
FSFpePtr conn = (FSFpePtr) fpe->private;
@@ -2269,7 +2413,7 @@ fs_send_list_fonts(pointer client, FontPathElementPtr fpe, char *pattern,
if (conn->blockState & FS_GIVE_UP)
return BadFontName;
-
+
/* make a new block record, and add it to the end of the list */
blockrec = fs_new_block_rec(fpe, client, FS_LIST_FONTS);
if (!blockrec)
@@ -2282,7 +2426,7 @@ fs_send_list_fonts(pointer client, FontPathElementPtr fpe, char *pattern,
_fs_pending_reply (conn);
return Suspended;
}
-
+
_fs_client_access (conn, client, FALSE);
_fs_client_resolution(conn);
@@ -2297,7 +2441,7 @@ fs_send_list_fonts(pointer client, FontPathElementPtr fpe, char *pattern,
_fs_write_pad(conn, (char *) pattern, patlen);
blockrec->sequenceNumber = conn->current_seq;
-
+
#ifdef NCD
if (configData.ExtendedFontDiags) {
char buf[256];
@@ -2314,7 +2458,7 @@ fs_send_list_fonts(pointer client, FontPathElementPtr fpe, char *pattern,
}
static int
-fs_list_fonts(pointer client, FontPathElementPtr fpe,
+fs_list_fonts(pointer client, FontPathElementPtr fpe,
char *pattern, int patlen, int maxnames, FontNamesPtr newnames)
{
FSFpePtr conn = (FSFpePtr) fpe->private;
@@ -2324,7 +2468,7 @@ fs_list_fonts(pointer client, FontPathElementPtr fpe,
/* see if the result is already there */
for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next)
{
- if (blockrec->type == FS_LIST_FONTS && blockrec->client == client)
+ if (blockrec->type == FS_LIST_FONTS && blockrec->client == client)
{
err = blockrec->errcode;
if (err == StillWorking)
@@ -2347,6 +2491,7 @@ fs_read_list_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
FSBlockedListInfoPtr binfo = (FSBlockedListInfoPtr) blockrec->data;
fsListFontsWithXInfoReply *rep;
char *buf;
+ long bufleft;
FSFpePtr conn = (FSFpePtr) fpe->private;
fsPropInfo *pi;
fsPropOffset *po;
@@ -2358,12 +2503,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;
}
/*
@@ -2380,7 +2528,8 @@ fs_read_list_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
}
buf = (char *) rep + SIZEOF (fsListFontsWithXInfoReply);
-
+ bufleft = (rep->length << 2) - SIZEOF (fsListFontsWithXInfoReply);
+
/*
* The original FS implementation didn't match
* the spec, version 1 was respecified to match the FS.
@@ -2388,19 +2537,71 @@ fs_read_list_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
*/
if (conn->fsMajorVersion <= 1)
{
+ if (rep->nameLength > bufleft) {
+#ifdef DEBUG
+ fprintf(stderr,
+ "fsListFontsWithXInfo: name length (%d) > bufleft (%ld)\n",
+ (int) rep->nameLength, bufleft);
+#endif
+ err = AllocError;
+ goto done;
+ }
+ /* binfo->name is a 256 char array, rep->nameLength is a CARD8 */
memcpy (binfo->name, buf, rep->nameLength);
buf += _fs_pad_length (rep->nameLength);
+ bufleft -= _fs_pad_length (rep->nameLength);
}
pi = (fsPropInfo *) buf;
+ if (SIZEOF (fsPropInfo) > bufleft) {
+#ifdef DEBUG
+ fprintf(stderr,
+ "fsListFontsWithXInfo: PropInfo length (%d) > bufleft (%ld)\n",
+ (int) SIZEOF (fsPropInfo), bufleft);
+#endif
+ err = AllocError;
+ goto done;
+ }
+ bufleft -= SIZEOF (fsPropInfo);
buf += SIZEOF (fsPropInfo);
po = (fsPropOffset *) buf;
+ if (pi->num_offsets > (bufleft / SIZEOF (fsPropOffset))) {
+#ifdef DEBUG
+ fprintf(stderr,
+ "fsListFontsWithXInfo: offset length (%d * %d) > bufleft (%ld)\n",
+ pi->num_offsets, (int) SIZEOF (fsPropOffset), bufleft);
+#endif
+ err = AllocError;
+ goto done;
+ }
+ bufleft -= pi->num_offsets * SIZEOF (fsPropOffset);
buf += pi->num_offsets * SIZEOF (fsPropOffset);
pd = (pointer) buf;
+ if (pi->data_len > bufleft) {
+#ifdef DEBUG
+ fprintf(stderr,
+ "fsListFontsWithXInfo: data length (%d) > bufleft (%ld)\n",
+ pi->data_len, bufleft);
+#endif
+ err = AllocError;
+ goto done;
+ }
+ bufleft -= pi->data_len;
buf += pi->data_len;
if (conn->fsMajorVersion > 1)
{
+ if (rep->nameLength > bufleft) {
+#ifdef DEBUG
+ fprintf(stderr,
+ "fsListFontsWithXInfo: name length (%d) > bufleft (%ld)\n",
+ (int) rep->nameLength, bufleft);
+#endif
+ err = AllocError;
+ goto done;
+ }
+ /* binfo->name is a 256 char array, rep->nameLength is a CARD8 */
memcpy (binfo->name, buf, rep->nameLength);
buf += _fs_pad_length (rep->nameLength);
+ bufleft -= _fs_pad_length (rep->nameLength);
}
#ifdef DEBUG
@@ -2417,18 +2618,18 @@ fs_read_list_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
binfo->remaining = rep->nReplies;
binfo->status = FS_LFWI_REPLY;
-
+
/* disable this font server until we've processed this response */
_fs_unmark_block (conn, FS_COMPLETE_REPLY);
FD_CLR(conn->fs_fd, &_fs_fd_mask);
-done:
+done:
_fs_done_read (conn, rep->length << 2);
return err;
}
/* ARGSUSED */
static int
-fs_start_list_with_info(pointer client, FontPathElementPtr fpe,
+fs_start_list_with_info(pointer client, FontPathElementPtr fpe,
char *pattern, int len, int maxnames, pointer *pdata)
{
FSFpePtr conn = (FSFpePtr) fpe->private;
@@ -2443,7 +2644,7 @@ fs_start_list_with_info(pointer client, FontPathElementPtr fpe,
blockrec = fs_new_block_rec(fpe, client, FS_LIST_WITH_INFO);
if (!blockrec)
return AllocError;
-
+
binfo = (FSBlockedListInfoPtr) blockrec->data;
bzero((char *) binfo, sizeof(FSBlockedListInfoRec));
binfo->status = FS_LFWI_WAITING;
@@ -2453,7 +2654,7 @@ fs_start_list_with_info(pointer client, FontPathElementPtr fpe,
_fs_pending_reply (conn);
return Suspended;
}
-
+
_fs_client_access (conn, client, FALSE);
_fs_client_resolution(conn);
@@ -2468,7 +2669,7 @@ fs_start_list_with_info(pointer client, FontPathElementPtr fpe,
(void) _fs_write_pad(conn, pattern, len);
blockrec->sequenceNumber = conn->current_seq;
-
+
#ifdef NCD
if (configData.ExtendedFontDiags) {
char buf[256];
@@ -2486,8 +2687,8 @@ fs_start_list_with_info(pointer client, FontPathElementPtr fpe,
/* ARGSUSED */
static int
-fs_next_list_with_info(pointer client, FontPathElementPtr fpe,
- char **namep, int *namelenp,
+fs_next_list_with_info(pointer client, FontPathElementPtr fpe,
+ char **namep, int *namelenp,
FontInfoPtr *pFontInfo, int *numFonts,
pointer private)
{
@@ -2498,7 +2699,7 @@ fs_next_list_with_info(pointer client, FontPathElementPtr fpe,
/* see if the result is already there */
for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next)
- if (blockrec->type == FS_LIST_WITH_INFO && blockrec->client == client)
+ if (blockrec->type == FS_LIST_WITH_INFO && blockrec->client == client)
break;
if (!blockrec)
@@ -2513,7 +2714,7 @@ fs_next_list_with_info(pointer client, FontPathElementPtr fpe,
}
binfo = (FSBlockedListInfoPtr) blockrec->data;
-
+
if (binfo->status == FS_LFWI_WAITING)
return Suspended;
@@ -2521,12 +2722,12 @@ fs_next_list_with_info(pointer client, FontPathElementPtr fpe,
*namelenp = binfo->namelen;
*pFontInfo = &binfo->info;
*numFonts = binfo->remaining;
-
+
/* Restart reply processing from this font server */
FD_SET(conn->fs_fd, &_fs_fd_mask);
if (fs_reply_ready (conn))
_fs_mark_block (conn, FS_COMPLETE_REPLY);
-
+
err = blockrec->errcode;
switch (binfo->status) {
case FS_LFWI_FINISHED:
@@ -2539,7 +2740,7 @@ fs_next_list_with_info(pointer client, FontPathElementPtr fpe,
_fs_mark_block (conn, FS_PENDING_REPLY);
break;
}
-
+
return err;
}
@@ -2574,12 +2775,12 @@ fs_client_died(pointer client, FontPathElementPtr fpe)
for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next)
if (blockrec->client == client)
break;
-
+
if (!blockrec)
return;
-
+
/* replace the client pointers in this block rec with the chained one */
- if ((depending = blockrec->depending))
+ if ((depending = blockrec->depending))
{
blockrec->client = depending->client;
blockrec->depending = depending->depending;
@@ -2681,7 +2882,7 @@ static int
_fs_check_connect (FSFpePtr conn)
{
int ret;
-
+
ret = _fs_poll_connect (conn->trans_conn, 0);
switch (ret) {
case FSIO_READY:
@@ -2715,7 +2916,7 @@ _fs_get_conn_setup (FSFpePtr conn, int *error, int *setup_len)
*error = ret;
return 0;
}
-
+
setup = (fsConnSetup *) data;
if (setup->major_version > FS_PROTOCOL)
{
@@ -2786,10 +2987,10 @@ _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;
-
+
setup = _fs_get_conn_setup (conn, &ret, &setup_len);
if (!setup)
return ret;
@@ -2813,8 +3014,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);
@@ -2823,10 +3025,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;
@@ -2845,7 +3062,7 @@ _fs_open_server (FSFpePtr conn)
{
int ret;
char *servername;
-
+
if (conn->alternate == 0)
servername = conn->servername;
else
@@ -2877,13 +3094,13 @@ _fs_send_init_packets (FSFpePtr conn)
char *cat;
char len;
char *end;
- int num_res;
+ int num_res;
FontResolutionPtr res;
#define CATALOGUE_SEP '+'
res = GetClientResolutions(&num_res);
- if (num_res)
+ if (num_res)
{
srreq.reqType = FS_SetResolution;
srreq.num_resolutions = num_res;
@@ -2902,14 +3119,14 @@ _fs_send_init_packets (FSFpePtr conn)
catalogues = _fs_catalog_name (conn->alts[conn->alternate-1].name);
if (!catalogues)
catalogues = _fs_catalog_name (conn->servername);
-
+
if (!catalogues)
{
conn->has_catalogues = FALSE;
return FSIO_READY;
}
conn->has_catalogues = TRUE;
-
+
/* turn cats into counted list */
catalogues++;
@@ -2929,11 +3146,11 @@ _fs_send_init_packets (FSFpePtr conn)
screq.reqType = FS_SetCatalogues;
screq.num_catalogues = num_cats;
screq.length = (SIZEOF(fsSetCataloguesReq) + clen + 3) >> 2;
-
+
_fs_add_req_log(conn, FS_SetCatalogues);
if (_fs_write(conn, (char *) &screq, SIZEOF(fsSetCataloguesReq)) != FSIO_READY)
return FSIO_ERROR;
-
+
while (*cat)
{
num_cats++;
@@ -2947,10 +3164,10 @@ _fs_send_init_packets (FSFpePtr conn)
return FSIO_ERROR;
cat = end;
}
-
+
if (_fs_write (conn, "....", _fs_pad_length (clen) - clen) != FSIO_READY)
return FSIO_ERROR;
-
+
return FSIO_READY;
}
@@ -2958,12 +3175,13 @@ static int
_fs_send_cat_sync (FSFpePtr conn)
{
fsListCataloguesReq lcreq;
-
+
/*
* now sync up with the font server, to see if an error was generated
* by a bogus catalogue
*/
lcreq.reqType = FS_ListCatalogues;
+ lcreq.data = 0;
lcreq.length = (SIZEOF(fsListCataloguesReq)) >> 2;
lcreq.maxNames = 0;
lcreq.nbytes = 0;
@@ -2986,7 +3204,7 @@ _fs_recv_cat_sync (FSFpePtr conn)
reply = fs_get_reply (conn, &err);
if (!reply)
return err;
-
+
ret = FSIO_READY;
if (reply->type == FS_Error)
{
@@ -3020,7 +3238,7 @@ static int
_fs_do_setup_connection (FSFpePtr conn)
{
int ret;
-
+
do
{
#ifdef DEBUG
@@ -3113,7 +3331,7 @@ static void
_fs_check_reconnect (FSFpePtr conn)
{
int ret;
-
+
ret = _fs_do_setup_connection (conn);
switch (ret) {
case FSIO_READY: