Index: work/texk/dviljk/ChangeLog =================================================================== --- work.orig/texk/dviljk/ChangeLog +++ work/texk/dviljk/ChangeLog @@ -1,3 +1,42 @@ +2007-07-02 Joachim Schrod + + * dvi2xx.c (DoSpecial): Security issue: usage of tmpnam() caused + tempfile race condition. I use mkdtemp() if it's available and + fall back to tmpnam. + + Special parsing of include files was inconsistent, unify it. The + current parsing code still allows lots of non-sensical special + commands, but at least it doesn't access unrelated variables any + more. + +2007-06-28 Joachim Schrod + + * dvi2xx.c: Fixed a whole bunch of buffer overflows: The program + did not check memory bounds for any string operation. All places + where strings are copied with strcpy are replaced by dynamically + allocated strings (with xstrdup from kpathsea) or bounded string + operations. Fixed also manual string copy operations on special + strings. Fixed array buffer overflow in defpoint and fill special + operations. + (DoSpecial): Call of ghostscript for psfile special had also a + potential buffer overflow caused by unchecked usage of sprintf. + Fix core dump: Check if all required parameters of psfile special + are passed. + + Bumped version number up to 2.6p3. + + * dvi2xx.h: Some fixed sized string arrays are pointers now, they + get dynamically allocated. + (GetBytes): Another buffer overflow: Check that the buffer size is + sufficient to store the read bytes. That relies on the invariant + that the GetBytes macro is always called with an array as argument + and not with a pointer. + + * config.h: Throw an error if kpathsea is not used. dvi2xx.c + had previously already kpathsea dependencies without protecting + them with #if KPATHSEA. We go that road further since upstream + does not exist any more. + 2006-05-29 Karl Berry * Makefile.in (install-exec): cd $(bindir) in case we are doing Index: work/texk/dviljk/c-auto.in =================================================================== --- work.orig/texk/dviljk/c-auto.in +++ work/texk/dviljk/c-auto.in @@ -1,9 +1,23 @@ -/* c-auto.in. Generated automatically from configure.in by autoheader. */ +/* c-auto.in. Generated from configure.in by autoheader. */ +/* acconfig.h -- used by autoheader when generating c-auto.in. -/* Define if type char is unsigned and you are not using gcc. */ -#ifndef __CHAR_UNSIGNED__ -#undef __CHAR_UNSIGNED__ -#endif + If you're thinking of editing acconfig.h to fix a configuration + problem, don't. Edit the c-auto.h file created by configure, + instead. Even better, fix configure to give the right answer. */ + +/* Define to 1 if you have the `mkdtemp' function. */ +#undef HAVE_MKDTEMP + +/* Define to 1 if you have the `rmdir' function. */ +#undef HAVE_RMDIR -/* The number of bytes in a long. */ +/* Define to 1 if you have the `unlink' function. */ +#undef HAVE_UNLINK + +/* The size of a `long', as computed by sizeof. */ #undef SIZEOF_LONG + +/* Define to 1 if type `char' is unsigned and you are not using gcc. */ +#ifndef __CHAR_UNSIGNED__ +# undef __CHAR_UNSIGNED__ +#endif Index: work/texk/dviljk/config.h =================================================================== --- work.orig/texk/dviljk/config.h +++ work/texk/dviljk/config.h @@ -216,12 +216,7 @@ typedef SCHAR_TYPE signed_char; #endif #ifndef KPATHSEA -extern bool findfile( -#if NeedFunctionPrototypes -char path[], char n[], long4 fontmag, char name[], - bool tfm, int level -#endif - ); +#error "Would need changed findfile, dviljk has changed allocation semantic of name member in tfontptr" #endif @@ -444,3 +439,24 @@ typedef FILE *FILEPTR; /* If we have neither, should fall back to fprintf with fixed args. */ #endif #endif + +/* If unlink and rmdir are not there, we don't delete the temporary files. */ +#ifndef HAVE_RMDIR +#define rmdir(dir) +#endif +#ifndef HAVE_UNLINK +#define unlink(file) +#endif + +/* If mkdtemp() does not exist, we have to use tmpnam(). */ +#ifndef HAVE_MKDTEMP +#define mkdtemp(dir) (tmpnam(dir) ? \ + ( mkdir(dir, 0700) == -1 ? NULL : dir ) : \ + ( errno = EINVAL, NULL ) ) +#endif + +#ifndef KPATHSEA +/* FIXME: Should provide a strdup function. But currently this tree is + only used in connection with kpathsea anyhow. */ +#error "Need xstrdup and xmalloc function, e.g. from kpathsea" +#endif Index: work/texk/dviljk/configure =================================================================== --- work.orig/texk/dviljk/configure +++ work/texk/dviljk/configure @@ -1283,6 +1283,62 @@ EOF +for ac_func in rmdir unlink mkdtemp +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1290: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1318: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + ac_config_files="$ac_config_files Makefile" trap '' 1 2 15 Index: work/texk/dviljk/configure.in =================================================================== --- work.orig/texk/dviljk/configure.in +++ work/texk/dviljk/configure.in @@ -14,5 +14,7 @@ dnl These tests prevent reliable cross-c AC_C_CHAR_UNSIGNED AC_CHECK_SIZEOF(long) +AC_CHECK_FUNCS(rmdir unlink mkdtemp) + KPSE_CONFIG_FILES([Makefile]) AC_OUTPUT Index: work/texk/dviljk/dvi2xx.c =================================================================== --- work.orig/texk/dviljk/dvi2xx.c +++ work/texk/dviljk/dvi2xx.c @@ -1,5 +1,5 @@ /* $Id: dvi2xx.c,v 2.5 1997/12/08 20:52:20 neumann Exp $ */ -#define VERSION "2.6p2 (dviljk)" +#define VERSION "dviljk (version 2.6p3)" /* #define DEBUGGS 1 */ @@ -173,7 +173,7 @@ char *argv[]; y_origin = YDEFAULTOFF; /* y-origin in dots */ setbuf(ERR_STREAM, NULL); - (void) strcpy(G_progname, argv[0]); + G_progname = argv[0]; #ifdef KPATHSEA kpse_set_progname(argv[0]); kpse_set_program_enabled (kpse_pk_format, MAKE_TEX_PK_BY_DEFAULT, kpse_src_compile); @@ -2968,8 +2968,8 @@ char *argv[]; #endif { int argind; /* argument index for flags */ - char curarea[STRSIZE]; /* current file area */ - char curname[STRSIZE]; /* current file name */ + char *curarea; /* current file area */ + char *curname; /* current file name */ char *tcp, *tcp1; /* temporary character pointers */ char *this_arg; double x_offset = 0.0, y_offset = 0.0; @@ -2988,9 +2988,9 @@ char *argv[]; #endif #endif - if (argc == 2 && (strcmp (argv[1], "--version") == 0)) { + if (argc == 2 && EQ(argv[1], "--version")) { extern KPSEDLL char *kpathsea_version_string; - puts ("dvilj(k) 2.6"); + puts (VERSION); puts (kpathsea_version_string); puts ("Copyright (C) 1997 Gustaf Neumann.\n\ There is NO warranty. You may redistribute this software\n\ @@ -3328,8 +3328,8 @@ Primary author of Dvi2xx: Gustaf Neumann } } else { - (void) strcpy(filename, tcp); - if (!strcmp(filename, "-")) { + filename = tcp; + if (EQ(filename, "-")) { EmitFileName = "-"; #ifdef RISC_USE_OSL dvifp = BINOPEN("Kbd:"); @@ -3339,57 +3339,68 @@ Primary author of Dvi2xx: Gustaf Neumann AssureBinary(fileno(dvifp)); #endif } else { + /* Since this code is used only once during startup, we don't care + about free()ing the allocated strings that represent filenames. + It will be more work to realize proper deallocation handling than + it's worth in terms of saving a few bytes. We consider these + bytes actually static memory where we don't know the size in + advance and don't add them to the allocated_storage count. + [27 Jun 07 -js] */ #ifdef KPATHSEA /* split into directory + file name */ int tcplen, argvlen; tcp = (char *)xbasename(argv[argind]);/* this knows about any kind of slashes */ tcplen = strlen(tcp); + if ( tcplen == 0 ) { + /* This happens when the DVI file name has a trailing slash; this + is not a valid name. Then we terminate the argument parsing + loop, a usage message will be output below. */ + break; + } argvlen = strlen(argv[argind]); if (tcplen == argvlen) - curarea[0] = '\0'; + curarea = ""; else { - (void) strcpy(curarea, argv[argind]); + curarea = xstrdup(argv[argind]); curarea[argvlen-tcplen] = '\0'; } #else tcp = strrchr(argv[argind], '/'); /* split into directory + file name */ if (tcp == NULL) { - curarea[0] = '\0'; + curarea[0] = ""; tcp = argv[argind]; } else { - (void) strcpy(curarea, argv[argind]); + curarea = xstrdup(argv[argind]); curarea[tcp-argv[argind]+1] = '\0'; tcp += 1; } #endif + curname = (char *) xmalloc(strlen(tcp)+5); /* + space for ".dvi" */ (void) strcpy(curname, tcp); /* split into file name + extension */ - tcp1 = strrchr(tcp, '.'); + tcp1 = strrchr(curname, '.'); if (tcp1 == NULL) { - (void) strcpy(rootname, curname); + rootname = xstrdup(curname); strcat(curname, ".dvi"); } else { *tcp1 = '\0'; - (void) strcpy(rootname, curname); + rootname = xstrdup(curname); *tcp1 = '.'; } + filename = (char *) xmalloc(strlen(curarea)+strlen(curname)+1); (void) strcpy(filename, curarea); (void) strcat(filename, curname); if ((dvifp = BINOPEN(filename)) == FPNULL) { /* do not insist on .dvi */ if (tcp1 == NULL) { - int l = strlen(curname); - if (l > 4) - curname[l - 4] = '\0'; - l = strlen(filename); - if (l > 4) - filename[l - 4] = '\0'; + filename[strlen(filename) - 4] = '\0'; + dvifp = BINOPEN(filename); } - if (tcp1 != NULL || (dvifp = BINOPEN(filename)) == FPNULL) { + if (dvifp == FPNULL) { #ifdef MSC5 Fatal("%s: can't find DVI file \"%s\"\n\n", G_progname, filename); @@ -3411,7 +3422,7 @@ Primary author of Dvi2xx: Gustaf Neumann y_goffset = (short) MM_TO_PXL(y_offset) + y_origin; if (dvifp == FPNULL) { - fprintf(ERR_STREAM,"\nThis is the DVI to %s converter version %s", + fprintf(ERR_STREAM,"\nThis is the DVI to %s converter %s", PRINTER, VERSION); #ifdef SEVENBIT fprintf(ERR_STREAM,", 7bit"); @@ -3507,13 +3518,8 @@ Primary author of Dvi2xx: Gustaf Neumann exit(1); } if (EQ(EmitFileName, "")) { - if ((EmitFileName = (char *)malloc( STRSIZE )) != NULL) - allocated_storage += STRSIZE; - else - Fatal("Can't allocate storage of %d bytes\n",STRSIZE); - (void) strcpy(EmitFileName, curname); - if ((tcp1 = strrchr(EmitFileName, '.'))) - *tcp1 = '\0'; + EmitFileName = (char *) xmalloc(strlen(rootname)+sizeof(EMITFILE_EXTENSION)); + (void) strcpy(EmitFileName, rootname); strcat(EmitFileName, EMITFILE_EXTENSION); } if (G_quiet) @@ -3698,6 +3704,8 @@ bool PFlag; #endif } CloseFiles(); + if ( tmp_dir[0] != '\0' ) + rmdir (tmp_dir); /* ignore errors */ exit(G_errenc); } @@ -3895,22 +3903,21 @@ char *str; int n; #endif { - char spbuf[STRSIZE], xs[STRSIZE], ys[STRSIZE]; - char *sf = NULL, *psfile = NULL; + char xs[STRSIZE], ys[STRSIZE]; + char *include_file = NULL; + enum { VerbFile, HPFile, PSFile } file_type; float x,y; long4 x_pos, y_pos; KeyWord k; int i, j, j1; static int GrayScale = 10, Pattern = 1; static bool GrayFill = _TRUE; - static long4 p_x[80], p_y[80]; - int llx=0, lly=0, urx=0, ury=0, rwi=0, rhi=0; -#ifdef WIN32 - char *gs_path; -#endif + static long4 p_x[MAX_SPECIAL_DEFPOINTS], p_y[MAX_SPECIAL_DEFPOINTS]; + int llx=0, lly=0, urx=0, ury=0, rwi=0; str[n] = '\0'; - spbuf[0] = '\0'; + for ( i=0 ; i0) { - x_pos = h; + if ( j < 0 || j >= MAX_SPECIAL_DEFPOINTS ) { + Warning ("defpoint %d ignored, must be between 0 and %d", + j, MAX_SPECIAL_DEFPOINTS); + break; + } + x_pos = h; y_pos = v; if (i>1) { if (sscanf(xs,"%fpt",&x)>0) { @@ -4011,19 +4008,32 @@ int n; p_x[j]=x_pos; p_y[j]=y_pos; } else -#ifdef KPATHSEA - if (!kpse_tex_hush ("special")) -#endif Warning("invalid point definition\n"); - - sf = NULL; break; case FILL: - (void) strcpy(spbuf, k.Val); - i = sscanf(spbuf,"%d/%d %s",&j,&j1,xs); + /* 254 is STRSIZE-1. cpp should be used to construct that number. */ + i = sscanf(k.Val,"%d/%d %254s",&j,&j1,xs); if (i>1) { #ifdef LJ + if ( j < 0 || j >= MAX_SPECIAL_DEFPOINTS ) { + Warning ("fill ignored, point %d must be between 0 and %d", + j, MAX_SPECIAL_DEFPOINTS); + break; + } + if ( p_x[j] == -1 ) { + Warning ("fill ignored, point %d is undefined\n", j); + break; + } + if ( j1 < 0 || j1 >= MAX_SPECIAL_DEFPOINTS ) { + Warning ("fill ignored, point %d must be between 0 and %d", + j1, MAX_SPECIAL_DEFPOINTS); + break; + } + if ( p_x[j1] == -1 ) { + Warning ("fill ignored, point %d is undefined\n", j1); + break; + } SetPosn(p_x[j], p_y[j]); x_pos = (long4)PIXROUND(p_x[j1]-p_x[j], hconv); y_pos = (long4)PIXROUND(p_y[j1]-p_y[j], vconv); @@ -4044,9 +4054,6 @@ int n; GrayScale = k.v.i; GrayFill = _TRUE; } else -#ifdef KPATHSEA - if (!kpse_tex_hush ("special")) -#endif Warning( "Invalid gray scale (%d) given; ignored.", k.v.i); break; @@ -4055,9 +4062,6 @@ int n; Pattern = k.v.i; GrayFill = _FALSE; } else -#ifdef KPATHSEA - if (!kpse_tex_hush ("special")) -#endif Warning( "Invalid pattern (%d) given; ignored.", k.v.i); break; @@ -4066,75 +4070,123 @@ int n; case URX: urx = k.v.i; break; case URY: ury = k.v.i; break; case RWI: rwi = k.v.i; break; - case RHI: rhi = k.v.i; break; + case RHI: + if (!kpse_tex_hush ("special")) + Warning("Whatever rhi was good for once, it is ignored now."); + break; default: -#ifdef KPATHSEA - if (!kpse_tex_hush ("special")) -#endif + if ( !kpse_tex_hush ("special") ) Warning("Can't handle %s=%s command; ignored.", k.Key, k.Val); break; } - - else -#ifdef KPATHSEA - if (!kpse_tex_hush ("special")) -#endif + + } else if (!kpse_tex_hush ("special")) { Warning("Invalid keyword or value in \\special - <%s> ignored", k.Key); + } + + free (k.Key); + if ( k.Val != NULL ) free(k.Val); } - if ( sf || psfile ) { + if ( include_file ) { last_rx = last_ry = UNKNOWN; #ifdef IBM3812 PMPflush; #endif - if (sf) { - if (i == HPFILE) - CopyHPFile( sf ); - else - CopyFile( sf ); - } - else + #ifdef LJ - if (psfile) { + if ( file_type == PSFile) { /* int height = rwi * (urx - llx) / (ury - lly);*/ int width = urx - llx; int height = ury - lly; char cmd[255]; - int scale_factor = 3000 * width / rwi; - int adjusted_height = height * 300/scale_factor; - int adjusted_llx = llx * 300/scale_factor; + char *cmd_format = "%s -q -dSIMPLE -dSAFER -dNOPAUSE -sDEVICE=%s -sOutputFile=%s %s %s showpage.ps -c quit"; + char *gs_cmd; + int scale_factor, adjusted_height, adjusted_llx; char *printer = "ljetplus"; /* use the most stupid one */ - - char scale_file_name[255]; - char *scale_file = tmpnam(scale_file_name); - char *pcl_file = tmpnam(NULL); + char pcl_file[STRSIZE]; + char scale_file[STRSIZE]; FILEPTR scalef; - if ( (scalef = BOUTOPEN(scale_file)) == FPNULL ) { - Warning("Unable to open file %s for writing", scale_file ); - return; - } - fprintf(scalef, "%.2f %.2f scale\n%d %d translate\n", - 300.0/scale_factor, 300.0/scale_factor, - 0, adjusted_height == height ? 0 : ury); - BCLOSE( scalef ); + if ( urx == 0 || ury == 0 || rwi == 0 ) { + /* Since dvips' psfile special has a different syntax, this might + well be one of those specials, i.e., a non-dviljk special. Then + the Warning should be suppressable. */ + if ( !kpse_tex_hush ("special") ) + Warning ("Ignoring psfile special without urx, ury and rwi attributes"); + free (include_file); + return; + } + scale_factor = 3000 * width / rwi; + adjusted_height = height * 300/scale_factor; + adjusted_llx = llx * 300/scale_factor; + + /* We cannot use mkstemp, as we cannot pass two open file descriptors + portably to Ghostscript. We don't want to use tmpnam() or tempnam() + either, as they have tempfile creation race conditions. Instead we + create a temporary directory with mkdtemp() -- if that's available. + If not, we are thrown back to tempnam(), to get our functionality + at all. We need to create the temporary directory only once per + run; it will be deleted in AllDone(). */ + if ( tmp_dir[0] == '\0' ) { + char * base_dir; + if ( (base_dir = getenv("TMPDIR")) == NULL ) { + base_dir = "/tmp"; + } else if ( strlen(base_dir) > STRSIZE - sizeof("/dviljkXXXXXX/include.pcl") ) { + Warning ("TMPDIR %s is too long, using /tmp instead", base_dir); + base_dir = "/tmp"; + } + if ( base_dir[0] == '/' && base_dir[1] == '\0' ) { + Warning ("Feeling naughty, do we? / is no temporary directory, dude"); + base_dir = "/tmp"; + } + strcpy (tmp_dir, base_dir); + strcat (tmp_dir, "/dviljkXXXXXX"); + if ( mkdtemp(tmp_dir) == NULL ) { + Warning ("Could not create temporary directory %s, errno = %d; ignoring include file special", + tmp_dir, errno); + return; + } + } + strcpy(pcl_file, tmp_dir); + strcat(pcl_file, "/include.pcl"); + strcpy(scale_file, tmp_dir); + strcat(scale_file, "/scale.ps"); + + if ( (scalef = BOUTOPEN(scale_file)) == FPNULL ) { + Warning("Unable to open file %s for writing", scale_file ); + free (include_file); + unlink(scale_file); /* ignore error */ + return; + } + fprintf(scalef, "%.2f %.2f scale\n%d %d translate\n", + 300.0/scale_factor, 300.0/scale_factor, + 0, adjusted_height == height ? 0 : ury); + BCLOSE( scalef ); #ifdef WIN32 - gs_path = getenv("GS_PATH"); - if (!gs_path) - gs_path = "gswin32c.exe"; - sprintf(cmd,"%s -q -dSIMPLE -dSAFER -dNOPAUSE -sDEVICE=%s -sOutputFile=%s %s %s showpage.ps -c quit", - gs_path, printer, pcl_file, scale_file, psfile); + if ( (gs_cmd = getenv("GS_PATH")) == NULL ) + gs_cmd = "gswin32c.exe"; #else - sprintf(cmd,"gs -q -dSIMPLE -dSAFER -dNOPAUSE -sDEVICE=%s -sOutputFile=%s %s %s showpage.ps -c quit", - printer, pcl_file, scale_file, psfile); + gs_cmd = "gs"; #endif + if ( strlen(cmd_format)-10 + strlen(gs_cmd) + strlen(printer) + + strlen(pcl_file) + strlen(scale_file) + strlen(include_file) +1 > + sizeof(cmd) ) { + Warning ("Ghostscript command for %s would be too long, skipping special", include_file); + free (include_file); + unlink(scale_file); /* ignore errors */ + unlink(pcl_file); + return; + } + sprintf(cmd, cmd_format, + gs_cmd, printer, pcl_file, scale_file, include_file); #ifdef DEBUGGS fprintf(stderr, "PS-file '%s' w=%d, h=%d, urx=%d, ury=%d, llx=%d, lly=%d, rwi=%d\n", - psfile, urx - llx, height, urx,ury,llx,lly, rwi); + include_file, urx - llx, height, urx,ury,llx,lly, rwi); fprintf(stderr,"%s\n",cmd); #endif if (system(cmd)) { @@ -4158,11 +4210,21 @@ int n; #endif CopyHPFile( pcl_file ); - /* unlink(pcl_file); */ - /* unlink(scale_file); */ - } } + unlink(scale_file); /* ignore errors */ + unlink(pcl_file); + } + else #endif /* LJ */ + + if ( file_type == HPFile ) + CopyHPFile( include_file ); + else if ( file_type == VerbFile ) + CopyFile( include_file ); + else + Warning ("This can't happen: unknown file_type value %d", file_type); + + if ( include_file != NULL ) free(include_file); } } @@ -4173,12 +4235,11 @@ int n; /**********************************************************************/ /***************************** GetKeyStr ****************************/ /**********************************************************************/ -/* extract first keyword-value pair from string (value part may be null) - * return pointer to remainder of string - * return NULL if none found +/* Extract first keyword-value pair from string (value part may be null), + * keyword and value are allocated and must be free by caller. + * Return pointer to remainder of string, + * return NULL if none found. */ -char KeyStr[STRSIZE]; -char ValStr[STRSIZE]; #if NeedFunctionPrototypes char *GetKeyStr(char *str, KeyWord *kw ) #else @@ -4187,39 +4248,46 @@ char *str; KeyWord *kw; #endif { - char *s, *k, *v, t; + char *s, *start; + char save_char, quote_char; if ( !str ) return( NULL ); for (s = str; *s == ' '; s++) ; /* skip over blanks */ if (*s == '\0') return( NULL ); - for (k = KeyStr; /* extract keyword portion */ - *s != ' ' && *s != '\0' && *s != '='; - *k++ = *s++) - ; - *k = '\0'; - kw->Key = KeyStr; - kw->Val = v = NULL; + start = s++; /* start of keyword */ + while ( *s != ' ' && *s != '\0' && *s != '=' ) /* locate end */ + s++; + save_char = *s; + *s = '\0'; + kw->Key = xstrdup(start); + kw->Val = NULL; kw->vt = None; - for ( ; *s == ' '; s++) - ; /* skip over blanks */ - if ( *s != '=' ) /* look for "=" */ + if ( save_char == '\0' ) /* shortcut when we're at the end */ + return (s); + *s = save_char; /* restore keyword end char */ + while ( *s == ' ' ) s++ ; /* skip over blanks */ + if ( *s != '=' ) /* no "=" means no value */ return( s ); - for (s++; *s == ' '; s++); /* skip over blanks */ - if ( *s == '\'' || *s == '\"' ) /* get string delimiter */ - t = *s++; + for (s++; *s == ' '; s++) + ; /* skip over blanks */ + if ( *s == '\'' || *s == '\"' ) /* get string delimiter */ + quote_char = *s++; else - t = ' '; - for (v = ValStr; /* copy value portion up to delim */ - *s != t && *s != '\0'; - *v++ = *s++) - ; - if ( t != ' ' && *s == t ) - s++; - *v = '\0'; - kw->Val = ValStr; + quote_char = ' '; + start = s; /* no increment, might be "" as value */ + while ( *s != quote_char && *s != '\0' ) + s++; /* locate end of value portion */ + save_char = *s; + *s = '\0'; + kw->Val = xstrdup(start); kw->vt = String; + if ( save_char != '\0' ) { /* save_char is now quote_char */ + *s = save_char; + if ( quote_char != ' ' ) /* we had real quote chars */ + s++; + } return( s ); } @@ -4819,13 +4887,14 @@ struct font_entry *fontptr; the resident fonts. */ if (tfm_read_info(fontptr->n, &tfm_info) && tfm_info.family[0] - && strcmp((char *)tfm_info.family, "HPAUTOTFM") == 0) { + && EQ((char *)tfm_info.family, "HPAUTOTFM")) { unsigned i; double factor = fontptr->s / (double)0x100000; resident_count++; fontptr->resident_p = _TRUE; - strcpy(fontptr->symbol_set, (char *)tfm_info.coding_scheme); + strncpy(fontptr->symbol_set, (char *)tfm_info.coding_scheme, 39); + fontptr->symbol_set[39] = '\0'; fontptr->resid = tfm_info.typeface_id; fontptr->spacing = tfm_info.spacing; fontptr->style = tfm_info.style; @@ -4878,7 +4947,7 @@ struct font_entry *fontptr; fontptr->resident_p = _FALSE; if (tfm_info.family[0] - && strcmp((char *)tfm_info.family, "UNSPECIFIED") == 0) { + && EQ((char *)tfm_info.family, "UNSPECIFIED")) { Warning("font family for %s is UNSPECIFIED; need to run dvicopy?", fontptr->n); fontptr->font_file_id = NO_FILE; @@ -5031,10 +5100,9 @@ printf("[%ld]=%lf * %lf * %lf + 0.5 = %l if (tfontptr->resident_p) return; - if (!(resident_font_located)) { + if (!(resident_font_located)) #endif -#ifdef KPATHSEA { kpse_glyph_file_type font_ret; char *name; @@ -5047,9 +5115,9 @@ printf("[%ld]=%lf * %lf * %lf + 0.5 = %l if (name) { font_found = _TRUE; - strcpy (tfontptr->name, name); - free (name); - + tfontptr->name = name; + allocated_storage += strlen(name)+1; + if (!FILESTRCASEEQ (tfontptr->n, font_ret.name)) { fprintf (stderr, "dvilj: Font %s not found, using %s at %d instead.\n", @@ -5071,29 +5139,6 @@ printf("[%ld]=%lf * %lf * %lf + 0.5 = %l tfontptr->n, dpi); } } -#else /* not KPATHSEA */ - if (!(findfile(PXLpath, - tfontptr->n, - tfontptr->font_mag, - tfontptr->name, - _FALSE, - 0))) { - Warning(tfontptr->name); /* contains error messsage */ - tfontptr->font_file_id = NO_FILE; -#ifdef __riscos - MakeMetafontFile(PXLpath, tfontptr->n, tfontptr->font_mag); -#endif - } - else { - font_found = _TRUE; - if (G_verbose) - fprintf(ERR_STREAM,"%d: using font <%s>\n", plusid, tfontptr->name); - } -#endif /* not KPATHSEA */ - -#ifdef LJ_RESIDENT_FONTS - } -#endif tfontptr->plusid = plusid; plusid++; Index: work/texk/dviljk/dvi2xx.h =================================================================== --- work.orig/texk/dviljk/dvi2xx.h +++ work/texk/dviljk/dvi2xx.h @@ -10,8 +10,8 @@ #ifdef KPATHSEA #include +#include #include -#include #include #include #include @@ -24,6 +24,7 @@ #include #include #include +#include #ifdef unix #include #endif @@ -41,9 +42,6 @@ #ifdef MSC5 #include /* only for binaryopen on device */ #endif -#if defined (unix) && !defined (KPATHSEA) -#include -#endif #include "config.h" @@ -116,6 +114,7 @@ #define HUGE_SIZE (unsigned char) 2 #define HUGE_CHAR_PATTERN 32767l #define BYTES_PER_PIXEL_LINE 500 /* max number of bytes per pixel line */ +#define MAX_SPECIAL_DEFPOINTS 80 /* max number of defpoint specials */ #define PK_POST 245 @@ -281,7 +280,14 @@ char *MFMODE = MFMODE600; #define VisChar(c) (unsigned char)(c) #endif -#define GetBytes(fp,buf,n) read_multi(buf,1,n,fp) /* used to be a function */ +/* Used to be a function. buf is always an array, never a pointer. + Without that invariant, we would have to introduce full dynamic + memory management in this driver -- probably it would be easier to + write a new one. [27 Jun 07 -js] */ +#define GetBytes(fp,buf,n) \ + ( sizeof(buf) != sizeof(void *) && sizeof(buf) > n ? \ + read_multi(buf, 1, n, fp) \ + : Fatal("Try to read %d bytes in an array of size %d", n, sizeof(buf)) ) /**********************************************************************/ @@ -307,6 +313,7 @@ int printf(); int sscanf(); int strcmp(); char *strcpy(); +char *strncpy(); # ifdef MSC5 unsigned int strlen(); # endif @@ -393,7 +400,7 @@ struct font_entry { /* font entry */ char n[STRSIZE]; /* FNT_DEF command parameters */ long4 font_mag; /* computed from FNT_DEF s and d parameters */ /*char psname[STRSIZE];*/ /* PostScript name of the font */ - char name[STRSIZE]; /* full name of PXL file */ + char *name; /* full name of PXL file */ FILEPTR font_file_id; /* file identifier (NO_FILE if none) */ #ifdef USEPXL long4 magnification; /* magnification read from PXL file */ @@ -487,8 +494,8 @@ void LoadAChar DVIPROTO((long4, regis long4 NoSignExtend DVIPROTO((FILEPTR, int)); void OpenFontFile DVIPROTO((void)); long4 PixRound DVIPROTO((long4, long4)); -void PkRaster DVIPROTO((struct char_entry *, int)); -void RasterLine DVIPROTO((struct char_entry *, unsigned int, +void PkRaster DVIPROTO((struct char_entry *, int)); +void RasterLine DVIPROTO((struct char_entry *, unsigned int, unsigned int, unsigned char *)); void RasterChar DVIPROTO((struct char_entry *)); void ReadFontDef DVIPROTO((long4)); @@ -534,11 +541,12 @@ bool LastPageSpecified = _FALSE; #ifndef KPATHSEA char *PXLpath = FONTAREA; #endif -char G_progname[STRSIZE]; /* program name */ -char filename[STRSIZE]; /* DVI file name */ -char rootname[STRSIZE]; /* DVI filename without extension */ +char *G_progname; /* program name */ +char *filename; /* DVI file name */ +char *rootname; /* DVI filename without extension */ char *HeaderFileName = ""; /* file name & path of Headerfile */ char *EmitFileName = ""; /* file name & path for output */ +char tmp_dir[STRSIZE] = ""; /* temporary directory for auxilliary files */ #ifdef IBM3812 bool FirstAlternate = _FALSE; /* first page from alternate casette ? */ #endif