diff options
Diffstat (limited to 'libXfont/src/fc')
-rw-r--r-- | libXfont/src/fc/fsconvert.c | 68 | ||||
-rw-r--r-- | libXfont/src/fc/fserve.c | 540 | ||||
-rw-r--r-- | libXfont/src/fc/fsio.h | 3 |
3 files changed, 422 insertions, 189 deletions
diff --git a/libXfont/src/fc/fsconvert.c b/libXfont/src/fc/fsconvert.c index 15c5e4200..7a6033119 100644 --- a/libXfont/src/fc/fsconvert.c +++ b/libXfont/src/fc/fsconvert.c @@ -86,7 +86,7 @@ _fs_init_fontinfo(FSFpePtr conn, FontInfoPtr pfi) } int -_fs_convert_props(fsPropInfo *pi, fsPropOffset *po, pointer pd, +_fs_convert_props(fsPropInfo *pi, fsPropOffset *po, pointer pd, FontInfoPtr pfi) { FontPropPtr dprop; @@ -102,22 +102,26 @@ _fs_convert_props(fsPropInfo *pi, fsPropOffset *po, pointer pd, nprops = pfi->nprops = pi->num_offsets; - if (nprops < 0 - || nprops > SIZE_MAX/(sizeof(FontPropRec) + sizeof(char))) + if (nprops < 0 + || nprops > SIZE_MAX/(sizeof(FontPropRec) + sizeof(char))) return -1; - + dprop = malloc(sizeof(FontPropRec) * nprops + sizeof (char) * nprops); if (!dprop) return -1; - + is_str = (char *) (dprop + nprops); pfi->props = dprop; pfi->isStringProp = is_str; off_adr = (char *)po; - for (i = 0; i < nprops; i++, dprop++, is_str++) + for (i = 0; i < nprops; i++, dprop++, is_str++) { memcpy(&local_off, off_adr, SIZEOF(fsPropOffset)); + if ((local_off.name.position >= pi->data_len) || + (local_off.name.length > + (pi->data_len - local_off.name.position))) + goto bail; dprop->name = MakeAtom(&pdc[local_off.name.position], local_off.name.length, 1); if (local_off.type != PropTypeString) { @@ -125,10 +129,15 @@ _fs_convert_props(fsPropInfo *pi, fsPropOffset *po, pointer pd, dprop->value = local_off.value.position; } else { *is_str = TRUE; + if ((local_off.value.position >= pi->data_len) || + (local_off.value.length > + (pi->data_len - local_off.value.position))) + goto bail; dprop->value = (INT32) MakeAtom(&pdc[local_off.value.position], local_off.value.length, 1); if (dprop->value == BAD_RESOURCE) { + bail: free (pfi->props); pfi->nprops = 0; pfi->props = 0; @@ -154,8 +163,8 @@ _fs_free_props (FontInfoPtr pfi) } int -_fs_convert_lfwi_reply(FSFpePtr conn, FontInfoPtr pfi, - fsListFontsWithXInfoReply *fsrep, +_fs_convert_lfwi_reply(FSFpePtr conn, FontInfoPtr pfi, + fsListFontsWithXInfoReply *fsrep, fsPropInfo *pi, fsPropOffset *po, pointer pd) { fsUnpack_XFontInfoHeader(fsrep, pfi); @@ -188,8 +197,8 @@ _fs_convert_lfwi_reply(FSFpePtr conn, FontInfoPtr pfi, */ /* ARGSUSED */ int -fs_build_range(FontPtr pfont, Bool range_flag, unsigned int count, - int item_size, unsigned char *data, int *nranges, +fs_build_range(FontPtr pfont, Bool range_flag, unsigned int count, + int item_size, unsigned char *data, int *nranges, fsRange **ranges) { FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate); @@ -350,7 +359,7 @@ fs_build_range(FontPtr pfont, Bool range_flag, unsigned int count, requests needs to be cancelled. */ void -_fs_clean_aborted_loadglyphs(FontPtr pfont, int num_expected_ranges, +_fs_clean_aborted_loadglyphs(FontPtr pfont, int num_expected_ranges, fsRange *expected_ranges) { register FSFontPtr fsfont; @@ -396,8 +405,8 @@ _fs_clean_aborted_loadglyphs(FontPtr pfont, int num_expected_ranges, } static int -_fs_get_glyphs(FontPtr pFont, unsigned long count, unsigned char *chars, - FontEncoding charEncoding, +_fs_get_glyphs(FontPtr pFont, unsigned long count, unsigned char *chars, + FontEncoding charEncoding, unsigned long *glyphCount, /* RETURN */ CharInfoPtr *glyphs) /* RETURN */ { @@ -508,8 +517,8 @@ _fs_get_glyphs(FontPtr pFont, unsigned long count, unsigned char *chars, static int -_fs_get_metrics(FontPtr pFont, unsigned long count, unsigned char *chars, - FontEncoding charEncoding, +_fs_get_metrics(FontPtr pFont, unsigned long count, unsigned char *chars, + FontEncoding charEncoding, unsigned long *glyphCount, /* RETURN */ xCharInfo **glyphs) /* RETURN */ { @@ -620,15 +629,15 @@ _fs_unload_font(FontPtr pfont) fsdata->glyphs = glyphs->next; free (glyphs); } - + /* XXX we may get called after the resource DB has been cleaned out */ if (find_old_font(fsd->fontid)) DeleteFontClientID (fsd->fontid); - + _fs_free_props (&pfont->info); - + free(fsdata); - + DestroyFontRec(pfont); } @@ -656,11 +665,11 @@ fs_create_font (FontPathElementPtr fpe, fsd = (FSFontDataPtr) (fsfont + 1); bzero((char *) fsfont, sizeof(FSFontRec)); bzero((char *) fsd, sizeof(FSFontDataRec)); - + pfont->fpe = fpe; pfont->fontPrivate = (pointer) fsfont; pfont->fpePrivate = (pointer) fsd; - + /* These font components will be needed in packGlyphs */ CheckFSFormat(format, BitmapFormatMaskBit | BitmapFormatMaskByte | @@ -676,17 +685,17 @@ fs_create_font (FontPathElementPtr fpe, pfont->byte = byte; pfont->scan = scan; pfont->glyph = glyph; - + pfont->info.nprops = 0; pfont->info.props = 0; pfont->info.isStringProp = 0; - + /* set font function pointers */ pfont->get_glyphs = _fs_get_glyphs; pfont->get_metrics = _fs_get_metrics; pfont->unload_font = _fs_unload_font; pfont->unload_glyphs = NULL; - + /* set the FPE private information */ fsd->format = format; fsd->fmask = fmask; @@ -694,9 +703,9 @@ fs_create_font (FontPathElementPtr fpe, memcpy (fsd->name, name, namelen); fsd->name[namelen] = '\0'; fsd->fontid = GetNewFontClientID (); - + /* save the ID */ - if (!StoreFontClientFont(pfont, fsd->fontid)) + if (!StoreFontClientFont(pfont, fsd->fontid)) { free (fsfont); DestroyFontRec (pfont); @@ -712,7 +721,12 @@ fs_alloc_glyphs (FontPtr pFont, int size) FSGlyphPtr glyphs; FSFontPtr fsfont = (FSFontPtr) pFont->fontPrivate; - glyphs = malloc (sizeof (FSGlyphRec) + size); + if (size < (INT_MAX - sizeof (FSGlyphRec))) + glyphs = malloc (sizeof (FSGlyphRec) + size); + else + glyphs = NULL; + if (glyphs == NULL) + return NULL; glyphs->next = fsfont->glyphs; fsfont->glyphs = glyphs; return (pointer) (glyphs + 1); 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: diff --git a/libXfont/src/fc/fsio.h b/libXfont/src/fc/fsio.h index 2bb8e0b73..fa1e7d8f9 100644 --- a/libXfont/src/fc/fsio.h +++ b/libXfont/src/fc/fsio.h @@ -26,8 +26,9 @@ #ifndef _FSIO_H_ #define _FSIO_H_ -#undef DEBUG +#ifdef DEBUG #define REQUEST_LOG_SIZE 100 +#endif typedef struct _fs_fpe_alternate { char *name; |