[LOW] STR #2158: prettyprint bug

Ivar Ylvisaker ylvisaki at verizon.net
Sun Feb 18 00:20:28 PST 2007


I investigated further.

The "texttops" process crashes at line 826 in texttops.c when PrettyPrint is 2.  The relevant block of code is:

    817     for (i = 1 + PrettyPrint; i >= 0; i --)
    818       for (j = 0; j < NumFonts; j ++)
    819       {
    820         printf("/%s findfont\n", Fonts[j][i]);
    821         printf("dup length 1 add dict begin\n"
    822                "        { 1 index /FID ne { def } { pop pop } ifelse } forall\n"
    823                "        /Encoding cupsEncoding%02x def\n"
    824                "        currentdict\n"
    825                "end\n", j);
    826         printf("/%s%02x exch definefont /%s%02x exch def\n", names[i], j,
    827                names[i], j);
    828       }

names is an array of only three values:

    150   static char   *names[] =      /* Font names */
    151                 {
    152                   "cupsNormal",
    153                   "cupsBold",
    154                   "cupsItalic"
    155                 };

Hence, when PrettyPrint is 2, the index "i" is 3, which points to the 4th item in the array. This is "out of bounds" and texttops crashes.

The code looks garbled.  Possible values for PrettyPrint are these (from textcommon.h):

     60 #define PRETTY_OFF      0
     61 #define PRETTY_PLAIN    1
     62 #define PRETTY_CODE     2
     63 #define PRETTY_SHELL    3
     64 #define PRETTY_PERL     4
     65 #define PRETTY_HTML     5

There is no obvious relationship between the PrettyPrint values and the names values.

PrettyPrint is initially set to 0 in textcommon.c.  If "prettyprint" is a print option, then PrettyPrint is reset to one of the above values as follows:

    569     if ((val = getenv("CONTENT_TYPE")) == NULL)
    570     {
    571       PrettyPrint = PRETTY_PLAIN;
    572       NumKeywords = 0;
    573       Keywords    = NULL;
    574     }
    575     else if (strcasecmp(val, "application/x-cshell") == 0)
    576     {
    577       PrettyPrint = PRETTY_SHELL;
    578       NumKeywords = sizeof(csh_keywords) / sizeof(csh_keywords[0]);
    579       Keywords    = csh_keywords;
    580     }
    581     else if (strcasecmp(val, "application/x-csource") == 0)
    582     {
    583       PrettyPrint = PRETTY_CODE;
    584       NumKeywords = sizeof(code_keywords) / sizeof(code_keywords[0]);
    585       Keywords    = code_keywords;
    586     }
    587     else if (strcasecmp(val, "application/x-perl") == 0)
    588     {
    589       PrettyPrint = PRETTY_PERL;
    590       NumKeywords = sizeof(perl_keywords) / sizeof(perl_keywords[0]);
    591       Keywords    = perl_keywords;
    592     }
    593     else if (strcasecmp(val, "application/x-shell") == 0)
    594     {
    595       PrettyPrint = PRETTY_SHELL;
    596       NumKeywords = sizeof(sh_keywords) / sizeof(sh_keywords[0]);
    597       Keywords    = sh_keywords;
    598     }
    599     else
    600     {
    601       PrettyPrint = PRETTY_PLAIN;
    602       NumKeywords = 0;
    603       Keywords    = NULL;
    604     }

The rules defined in mime.types indicate that "CONTENT_TYPE" will be set to "application/x-csource" if a text file to be printed starts with "/*", which was true for the file that I had trouble printing.  PrettyPrint is then 2 and a crash occurs.  If a text file starts with " /*" (i.e., begins with a space), the "CONTENT_TYPE" can be set to "application/x-shell," and the file will be printed because this results in a valid value for "names."

Ivar




More information about the cups-devel mailing list