xorl %eax, %eax

CVE-2009-0196: Ghostscript JBIG2 Heap Buffer Overflow

leave a comment »

This bug was discovered and reported by Alin Rad Pop of Secunia Research on 9 April 2009. It affects Ghostscript 8.64 and probably earlier releases too. JBIG2 is an image compression used widely in PDF documents. The bug discussed here is in the JBIG2 dictionary symbols of Ghostscript which can be found at jbi2dec/jbig2_symbol_dict.c:

2     jbig2dec
3
4     Copyright (C) 2001-2005 Artifex Software, Inc.
     ...
18     symbol dictionary segment decode and support
19 */
     ...
209 /* Decoding routines */
210
211 /* 6.5 */
212 static Jbig2SymbolDict *
213 jbig2_decode_symbol_dict(Jbig2Ctx *ctx,
214                          Jbig2Segment *segment,
215                          const Jbig2SymbolDictParams *params,
216                          const byte *data, size_t size,
217                          Jbig2ArithCx *GB_stats,
218                          Jbig2ArithCx *GR_stats)
219 {
    ...
231   Jbig2ArithState *as = NULL;
    ...
234   Jbig2ArithIntCtx *IAEX = NULL;
    ...
684   /* 6.5.10 */
685   SDEXSYMS = jbig2_sd_new(ctx, params->SDNUMEXSYMS);
686   {
    ...
690     int32_t exrunlength;
    ...
697       if (params->SDHUFF)
698         /* FIXME: implement reading from huff table B.1 */
699         exrunlength = params->SDNUMEXSYMS;
700       else
701         code = jbig2_arith_int_decode(IAEX, as, &exrunlength);
702       for(k = 0; k < exrunlength; k++)
703         if (exflag) {
704           SDEXSYMS->glyphs[j++] = (i < m) ?
705             jbig2_image_clone(ctx, params->SDINSYMS->glyphs[i]) :
706             jbig2_image_clone(ctx, SDNEWSYMS->glyphs[i-m]);
707           i++;
708         }
709         exflag = !exflag;
710     }
711   }


The problem with the above code is that integer exrunlength (which represents the length of a JBIG2 symbol dictionary segment) declared at line 690 is initialized either at line 699 or at line 701. Its contents should be the same or less than params->SDNUMEXSYMS but the call to jbig2_arith_int_decode() might lead into a different result and the proceeding loop at line 702 could result in memory corruption on the heap allocated SDEXSYMS->glyphs[] buffer. To fix this the following patch was applied:

         code = jbig2_arith_int_decode(IAEX, as, &exrunlength);
+      if (exrunlength > params->SDNUMEXSYMS - j) {
+        jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+          "runlength too large in export symbol table (%d > %d - %d)\n",
+          exrunlength, params->SDNUMEXSYMS, j);
+        jbig2_sd_release(ctx, SDEXSYMS);
+        /* skip to the cleanup code and return SDEXSYMS = NULL */
+        SDEXSYMS = NULL;
+        break;
+      }
       for(k = 0; k < exrunlength; k++)

The if condition ensures that exrunlength will never be greater than params->SDNUMEXSYMS. However, if this is the case the subsequent call to jbig2_error() will terminate the application before entering the for loop.

Written by xorl

April 22, 2009 at 12:07

Posted in bugs

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s