Update bundled openjpeg from 1.5.0 to 1.5.2
authorSergey Sharybin <sergey.vfx@gmail.com>
Wed, 20 Apr 2016 08:36:58 +0000 (10:36 +0200)
committerSergey Sharybin <sergey.vfx@gmail.com>
Wed, 20 Apr 2016 08:36:58 +0000 (10:36 +0200)
Solves following issues:

- Quite reasonable amount of paranoid warnings were solved by an upstream
- Upstream seems to have all fixes needed for FreeBSD and OSX already
- Brings all fixes and such from upstream

17 files changed:
extern/libopenjpeg/bio.c
extern/libopenjpeg/cidx_manager.c
extern/libopenjpeg/cio.c
extern/libopenjpeg/cio.h
extern/libopenjpeg/event.c
extern/libopenjpeg/image.c
extern/libopenjpeg/j2k.c
extern/libopenjpeg/jp2.c
extern/libopenjpeg/openjpeg.h
extern/libopenjpeg/opj_config.h
extern/libopenjpeg/opj_includes.h
extern/libopenjpeg/opj_malloc.h
extern/libopenjpeg/patches/fbsd.patch [deleted file]
extern/libopenjpeg/patches/osx.patch [deleted file]
extern/libopenjpeg/t1.c
extern/libopenjpeg/t2.c
extern/libopenjpeg/tcd.c

index 4c02f464d8da86f2b0ac743a6ce472c0006edd0e..f04f3e503fb38effb81f9d94a313837a1b0195e9 100644 (file)
@@ -42,7 +42,7 @@ Write a bit
 @param bio BIO handle
 @param b Bit to write (0 or 1)
 */
-static void bio_putbit(opj_bio_t *bio, int b);
+static void bio_putbit(opj_bio_t *bio, unsigned int b);
 /**
 Read a bit
 @param bio BIO handle
@@ -78,7 +78,7 @@ static int bio_byteout(opj_bio_t *bio) {
        if (bio->bp >= bio->end) {
                return 1;
        }
-       *bio->bp++ = bio->buf >> 8;
+       *bio->bp++ = (unsigned char)(bio->buf >> 8);
        return 0;
 }
 
@@ -92,7 +92,7 @@ static int bio_bytein(opj_bio_t *bio) {
        return 0;
 }
 
-static void bio_putbit(opj_bio_t *bio, int b) {
+static void bio_putbit(opj_bio_t *bio, unsigned int b) {
        if (bio->ct == 0) {
                bio_byteout(bio);
        }
@@ -126,7 +126,7 @@ void bio_destroy(opj_bio_t *bio) {
 }
 
 int bio_numbytes(opj_bio_t *bio) {
-       return (bio->bp - bio->start);
+       return (int)(bio->bp - bio->start);
 }
 
 void bio_init_enc(opj_bio_t *bio, unsigned char *bp, int len) {
index 6131b938ea6acc3bbc14f93b896c811ddeb01ade..f3b251ffa09bf938ce8842c8e271ff56c852e871 100644 (file)
@@ -29,8 +29,6 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <stdio.h>
-#include <stdlib.h>
 #include "opj_includes.h"
 
 
index b8a7ecf8a873a7f4cf001e59334a98d4dc6ae383..97cccea6dee55491cf96e82c9ab5cce1e95b84cc 100644 (file)
@@ -30,6 +30,7 @@
  */
 
 #include "opj_includes.h"
+#include <assert.h>
 
 /* ----------------------------------------------------------------------- */
 
@@ -106,6 +107,7 @@ int OPJ_CALLCONV cio_tell(opj_cio_t *cio) {
  * pos : position, in number of bytes, from the beginning of the stream
  */
 void OPJ_CALLCONV cio_seek(opj_cio_t *cio, int pos) {
+  assert((cio->start + pos) <= cio->end);
        cio->bp = cio->start + pos;
 }
 
@@ -113,6 +115,7 @@ void OPJ_CALLCONV cio_seek(opj_cio_t *cio, int pos) {
  * Number of bytes left before the end of the stream.
  */
 int cio_numbytesleft(opj_cio_t *cio) {
+  assert((cio->end - cio->bp) >= 0);
        return cio->end - cio->bp;
 }
 
@@ -139,6 +142,7 @@ opj_bool cio_byteout(opj_cio_t *cio, unsigned char v) {
  * Read a byte.
  */
 unsigned char cio_bytein(opj_cio_t *cio) {
+  assert(cio->bp >= cio->start);
        if (cio->bp >= cio->end) {
                opj_event_msg(cio->cinfo, EVT_ERROR, "read error: passed the end of the codestream (start = %d, current = %d, end = %d\n", cio->start, cio->bp, cio->end);
                return 0;
@@ -152,7 +156,7 @@ unsigned char cio_bytein(opj_cio_t *cio) {
  * v : value to write
  * n : number of bytes to write
  */
-unsigned int cio_write(opj_cio_t *cio, unsigned long long int v, int n) {
+unsigned int cio_write(opj_cio_t *cio, unsigned int64 v, int n) {
        int i;
        for (i = n - 1; i >= 0; i--) {
                if( !cio_byteout(cio, (unsigned char) ((v >> (i << 3)) & 0xff)) )
@@ -173,7 +177,7 @@ unsigned int cio_read(opj_cio_t *cio, int n) {
        unsigned int v;
        v = 0;
        for (i = n - 1; i >= 0; i--) {
-               v += cio_bytein(cio) << (i << 3);
+               v += (unsigned int)cio_bytein(cio) << (i << 3);
        }
        return v;
 }
@@ -184,6 +188,10 @@ unsigned int cio_read(opj_cio_t *cio, int n) {
  * n : number of bytes to skip
  */
 void cio_skip(opj_cio_t *cio, int n) {
+  assert((cio->bp + n) >= cio->bp);
+  if (((cio->bp + n) < cio->start) || ((cio->bp + n) > cio->end)) {
+    assert(0);
+  }
        cio->bp += n;
 }
 
index ce1a13ecb3a5cab9ac1b8aaaaeab30e77e0420c5..e62743141ca6684f6a08469d240d1e48cc04e44f 100644 (file)
 
 #ifndef __CIO_H
 #define __CIO_H
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+#define int64 __int64
+#else
+#define int64 long long
+#endif
+
 /**
 @file cio.h
 @brief Implementation of a byte input-output process (CIO)
@@ -63,7 +70,7 @@ Write some bytes
 @param n Number of bytes to write
 @return Returns the number of bytes written or 0 if an error occured
 */
-unsigned int cio_write(opj_cio_t *cio, unsigned long long int v, int n);
+unsigned int cio_write(opj_cio_t *cio, unsigned int64 v, int n);
 /**
 Read some bytes
 @param cio CIO handle
index 0dc22f125499182ee54e1c84728c3f5838ac2d21..38db33a94322b44c4a90f6209bcd35ec681d5fd1 100644 (file)
@@ -103,18 +103,17 @@ opj_bool opj_event_msg(opj_common_ptr cinfo, int event_type, const char *fmt, ..
                va_list arg;
                int str_length/*, i, j*/; /* UniPG */
                char message[MSG_SIZE];
-               memset(message, 0, MSG_SIZE);
                /* initialize the optional parameter list */
                va_start(arg, fmt);
-               /* check the length of the format string */
-               str_length = (strlen(fmt) > MSG_SIZE) ? MSG_SIZE : strlen(fmt);
                /* parse the format string and put the result in 'message' */
-               vsprintf(message, fmt, arg); /* UniPG */
+               str_length = vsnprintf(message, MSG_SIZE, fmt, arg); /* UniPG */
                /* deinitialize the optional parameter list */
                va_end(arg);
 
                /* output the message to the user program */
-               msg_handler(message, cinfo->client_data);
+    if( str_length > -1 && str_length < MSG_SIZE )
+      msg_handler(message, cinfo->client_data);
+    else return OPJ_FALSE;
        }
 
        return OPJ_TRUE;
index 7c1e7f7faa2639c65143e58156778524e2224c3e..579fd73d71824f0f8e6127e2ea205de5e62e294e 100644 (file)
@@ -40,7 +40,7 @@ opj_image_t* OPJ_CALLCONV opj_image_create(int numcmpts, opj_image_cmptparm_t *c
                image->color_space = clrspc;
                image->numcomps = numcmpts;
                /* allocate memory for the per-component information */
-               image->comps = (opj_image_comp_t*)opj_malloc(image->numcomps * sizeof(opj_image_comp_t));
+               image->comps = (opj_image_comp_t*)opj_calloc(1,image->numcomps * sizeof(opj_image_comp_t));
                if(!image->comps) {
                        fprintf(stderr,"Unable to allocate memory for image.\n");
                        opj_image_destroy(image);
@@ -86,3 +86,4 @@ void OPJ_CALLCONV opj_image_destroy(opj_image_t *image) {
                opj_free(image);
        }
 }
+
index d34c75faa7ba20cecbccf02986d524ba8d5484c2..93e5c9eb80a3389a9496d771590f154a7cc822a0 100644 (file)
@@ -32,6 +32,7 @@
  */
 
 #include "opj_includes.h"
+#include <assert.h>
 
 /** @defgroup J2K J2K - JPEG-2000 codestream reader/writer */
 /*@{*/
@@ -404,6 +405,7 @@ static void j2k_write_siz(opj_j2k_t *j2k) {
 
 static void j2k_read_siz(opj_j2k_t *j2k) {
        int len, i;
+  int n_comps;
        
        opj_cio_t *cio = j2k->cio;
        opj_image_t *image = j2k->image;
@@ -422,12 +424,33 @@ static void j2k_read_siz(opj_j2k_t *j2k) {
        
        if ((image->x0<0)||(image->x1<0)||(image->y0<0)||(image->y1<0)) {
                opj_event_msg(j2k->cinfo, EVT_ERROR,
-                                                                       "%s: invalid image size (x0:%d, x1:%d, y0:%d, y1:%d)\n",
+                                                                       "invalid image size (x0:%d, x1:%d, y0:%d, y1:%d)\n",
                                                                        image->x0,image->x1,image->y0,image->y1);
                return;
        }
        
+  n_comps = (len - 36 - 2 ) / 3;
+  assert( (len - 36 - 2 ) % 3 == 0 );
        image->numcomps = cio_read(cio, 2);     /* Csiz */
+  assert( n_comps == image->numcomps );
+  (void)n_comps;
+
+  /* testcase 4035.pdf.SIGSEGV.d8b.3375 */
+  if (image->x0 > image->x1 || image->y0 > image->y1) {
+    opj_event_msg(j2k->cinfo, EVT_ERROR, "Error with SIZ marker: negative image size (%d x %d)\n", image->x1 - image->x0, image->y1 - image->y0);
+    return;
+  }
+  /* testcase 2539.pdf.SIGFPE.706.1712 (also 3622.pdf.SIGFPE.706.2916 and 4008.pdf.SIGFPE.706.3345 and maybe more) */
+  if (!(cp->tdx * cp->tdy)) {
+    opj_event_msg(j2k->cinfo, EVT_ERROR, "Error with SIZ marker: invalid tile size (tdx: %d, tdy: %d)\n", cp->tdx, cp->tdy);
+    return;
+  }
+
+  /* testcase 1610.pdf.SIGSEGV.59c.681 */
+  if (((int64)image->x1) * ((int64)image->y1) != (image->x1 * image->y1)) {
+    opj_event_msg(j2k->cinfo, EVT_ERROR, "Prevent buffer overflow (x1: %d, y1: %d)\n", image->x1, image->y1);
+    return;
+  }
 
 #ifdef USE_JPWL
        if (j2k->cp->correct) {
@@ -466,11 +489,19 @@ static void j2k_read_siz(opj_j2k_t *j2k) {
                /* update components number in the jpwl_exp_comps filed */
                cp->exp_comps = image->numcomps;
        }
+#else
+  (void)len;
 #endif /* USE_JPWL */
 
+  /* prevent division by zero */
+  if (!(cp->tdx * cp->tdy)) {
+    opj_event_msg(j2k->cinfo, EVT_ERROR, "invalid tile size (tdx: %d, tdy: %d)\n", cp->tdx, cp->tdy);
+    return;
+  }
+
        image->comps = (opj_image_comp_t*) opj_calloc(image->numcomps, sizeof(opj_image_comp_t));
        for (i = 0; i < image->numcomps; i++) {
-               int tmp, w, h;
+               int tmp;
                tmp = cio_read(cio, 1);         /* Ssiz_i */
                image->comps[i].prec = (tmp & 0x7f) + 1;
                image->comps[i].sgnd = tmp >> 7;
@@ -506,9 +537,11 @@ static void j2k_read_siz(opj_j2k_t *j2k) {
                }
 #endif /* USE_JPWL */
 
-               /* TODO: unused ? */
-               w = int_ceildiv(image->x1 - image->x0, image->comps[i].dx);
-               h = int_ceildiv(image->y1 - image->y0, image->comps[i].dy);
+    /* prevent division by zero */
+    if (!(image->comps[i].dx * image->comps[i].dy)) {
+      opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: invalid component size (dx: %d, dy: %d)\n", image->comps[i].dx, image->comps[i].dy);
+      return;
+    }
 
                image->comps[i].resno_decoded = 0;      /* number of resolution decoded */
                image->comps[i].factor = cp->reduce; /* reducing factor per component */
@@ -517,6 +550,15 @@ static void j2k_read_siz(opj_j2k_t *j2k) {
        cp->tw = int_ceildiv(image->x1 - cp->tx0, cp->tdx);
        cp->th = int_ceildiv(image->y1 - cp->ty0, cp->tdy);
 
+  /* gdal_fuzzer_check_number_of_tiles.jp2 */
+  if (cp->tw == 0 || cp->th == 0 || cp->tw > 65535 / cp->th) {
+    opj_event_msg(j2k->cinfo, EVT_ERROR, 
+                            "Invalid number of tiles : %u x %u (maximum fixed by jpeg2000 norm is 65535 tiles)\n",
+                            cp->tw, cp->th);
+    return;
+  }
+
+
 #ifdef USE_JPWL
        if (j2k->cp->correct) {
                /* if JPWL is on, we check whether TX errors have damaged
@@ -558,7 +600,17 @@ static void j2k_read_siz(opj_j2k_t *j2k) {
 #endif /* USE_JPWL */
 
        cp->tcps = (opj_tcp_t*) opj_calloc(cp->tw * cp->th, sizeof(opj_tcp_t));
+    if (cp->tcps == NULL)
+    {
+        opj_event_msg(j2k->cinfo, EVT_ERROR, "Out of memory\n");
+        return;
+    }
        cp->tileno = (int*) opj_malloc(cp->tw * cp->th * sizeof(int));
+    if (cp->tileno == NULL)
+    {
+        opj_event_msg(j2k->cinfo, EVT_ERROR, "Out of memory\n");
+        return;
+    }
        cp->tileno_size = 0;
        
 #ifdef USE_JPWL
@@ -684,6 +736,12 @@ static void j2k_read_cox(opj_j2k_t *j2k, int compno) {
                                        "of resolutions of this component\nModify the cp_reduce parameter.\n\n", compno);
                j2k->state |= J2K_STATE_ERR;
        }
+  if( tccp->numresolutions > J2K_MAXRLVLS ) {
+    opj_event_msg(j2k->cinfo, EVT_ERROR, "Error decoding component %d.\nThe number of resolutions is too big: %d vs max= %d. Truncating.\n\n",
+      compno, tccp->numresolutions, J2K_MAXRLVLS);
+               j2k->state |= J2K_STATE_ERR;
+    tccp->numresolutions = J2K_MAXRLVLS;
+ }
 
        tccp->cblkw = cio_read(cio, 1) + 2;     /* SPcox (E) */
        tccp->cblkh = cio_read(cio, 1) + 2;     /* SPcox (F) */
@@ -753,6 +811,7 @@ static void j2k_read_cod(opj_j2k_t *j2k) {
        opj_image_t *image = j2k->image;
        
        len = cio_read(cio, 2);                         /* Lcod */
+  (void)len;
        tcp->csty = cio_read(cio, 1);           /* Scod */
        tcp->prg = (OPJ_PROG_ORDER)cio_read(cio, 1);            /* SGcod (A) */
        tcp->numlayers = cio_read(cio, 2);      /* SGcod (B) */
@@ -806,7 +865,14 @@ static void j2k_read_coc(opj_j2k_t *j2k) {
        opj_cio_t *cio = j2k->cio;
        
        len = cio_read(cio, 2);         /* Lcoc */
+  (void)len;
        compno = cio_read(cio, image->numcomps <= 256 ? 1 : 2); /* Ccoc */
+  if (compno >= image->numcomps) {
+    opj_event_msg(j2k->cinfo, EVT_ERROR,
+      "bad component number in COC (%d out of a maximum of %d)\n",
+      compno, image->numcomps);
+    return;
+  }
        tcp->tccps[compno].csty = cio_read(cio, 1);     /* Scoc */
        j2k_read_cox(j2k, compno);
 }
@@ -877,6 +943,8 @@ static void j2k_read_qcx(opj_j2k_t *j2k, int compno, int len) {
                opj_event_msg(j2k->cinfo, EVT_WARNING ,
                                        "bad number of subbands in Sqcx (%d) regarding to J2K_MAXBANDS (%d) \n"
                                    "- limiting number of bands to J2K_MAXBANDS and try to move to the next markers\n", numbands, J2K_MAXBANDS);
+    /* edf_c2_1013627.jp2 */
+    numbands = 1;
        }
 
 #endif /* USE_JPWL */
@@ -988,9 +1056,16 @@ static void j2k_read_qcc(opj_j2k_t *j2k) {
 
                /* keep your private count of tiles */
                backup_compno++;
-       };
+       }
 #endif /* USE_JPWL */
 
+  if ((compno < 0) || (compno >= numcomp)) {
+    opj_event_msg(j2k->cinfo, EVT_ERROR,
+      "bad component number in QCC (%d out of a maximum of %d)\n",
+      compno, j2k->image->numcomps);
+    return;
+  }
+
        j2k_read_qcx(j2k, compno, len - 2 - (numcomp <= 256 ? 1 : 2));
 }
 
@@ -1036,6 +1111,15 @@ static void j2k_read_poc(opj_j2k_t *j2k) {
        len = cio_read(cio, 2);         /* Lpoc */
        numpchgs = (len - 2) / (5 + 2 * (numcomps <= 256 ? 1 : 2));
        
+  if( numpchgs >= 32 )
+    {
+    /* edf_c2_1103421.jp2 */
+    opj_event_msg(j2k->cinfo, EVT_ERROR,
+      "bad number of POCS (%d out of a maximum of %d)\n",
+      numpchgs, 32);
+    numpchgs = 0;
+    }
+
        for (i = old_poc; i < numpchgs + old_poc; i++) {
                opj_poc_t *poc;
                poc = &tcp->pocs[i];
@@ -1058,9 +1142,12 @@ static void j2k_read_crg(opj_j2k_t *j2k) {
        int numcomps = j2k->image->numcomps;
        
        len = cio_read(cio, 2);                 /* Lcrg */
+  (void)len;
        for (i = 0; i < numcomps; i++) {
                Xcrg_i = cio_read(cio, 2);      /* Xcrg_i */
+    (void)Xcrg_i;
                Ycrg_i = cio_read(cio, 2);      /* Ycrg_i */
+    (void)Ycrg_i;
        }
 }
 
@@ -1072,13 +1159,16 @@ static void j2k_read_tlm(opj_j2k_t *j2k) {
        
        len = cio_read(cio, 2);         /* Ltlm */
        Ztlm = cio_read(cio, 1);        /* Ztlm */
+  (void)Ztlm;
        Stlm = cio_read(cio, 1);        /* Stlm */
        ST = ((Stlm >> 4) & 0x01) + ((Stlm >> 4) & 0x02);
        SP = (Stlm >> 6) & 0x01;
        tile_tlm = (len - 4) / ((SP + 1) * 2 + ST);
        for (i = 0; i < tile_tlm; i++) {
                Ttlm_i = cio_read(cio, ST);     /* Ttlm_i */
+    (void)Ttlm_i;
                Ptlm_i = cio_read(cio, SP ? 4 : 2);     /* Ptlm_i */
+    (void)Ptlm_i;
        }
 }
 
@@ -1089,6 +1179,7 @@ static void j2k_read_plm(opj_j2k_t *j2k) {
 
        len = cio_read(cio, 2);         /* Lplm */
        Zplm = cio_read(cio, 1);        /* Zplm */
+  (void)Zplm;
        len -= 3;
        while (len > 0) {
                Nplm = cio_read(cio, 4);                /* Nplm */
@@ -1114,6 +1205,7 @@ static void j2k_read_plt(opj_j2k_t *j2k) {
        
        len = cio_read(cio, 2);         /* Lplt */
        Zplt = cio_read(cio, 1);        /* Zplt */
+  (void)Zplt;
        for (i = len - 3; i > 0; i--) {
                add = cio_read(cio, 1);
                packet_len = (packet_len << 7) + add;   /* Iplt_i */
@@ -1261,6 +1353,7 @@ static void j2k_read_sot(opj_j2k_t *j2k) {
        opj_cio_t *cio = j2k->cio;
 
        len = cio_read(cio, 2);
+  (void)len;
        tileno = cio_read(cio, 2);
 
 #ifdef USE_JPWL
@@ -1269,7 +1362,7 @@ static void j2k_read_sot(opj_j2k_t *j2k) {
                static int backup_tileno = 0;
 
                /* tileno is negative or larger than the number of tiles!!! */
-               if ((tileno < 0) || (tileno > (cp->tw * cp->th))) {
+               if ((tileno < 0) || (tileno >= (cp->tw * cp->th))) {
                        opj_event_msg(j2k->cinfo, EVT_ERROR,
                                "JPWL: bad tile number (%d out of a maximum of %d)\n",
                                tileno, (cp->tw * cp->th));
@@ -1286,8 +1379,18 @@ static void j2k_read_sot(opj_j2k_t *j2k) {
 
                /* keep your private count of tiles */
                backup_tileno++;
-       };
+       }
+  else
 #endif /* USE_JPWL */
+  {
+    /* tileno is negative or larger than the number of tiles!!! */
+    if ((tileno < 0) || (tileno >= (cp->tw * cp->th))) {
+      opj_event_msg(j2k->cinfo, EVT_ERROR,
+        "JPWL: bad tile number (%d out of a maximum of %d)\n",
+        tileno, (cp->tw * cp->th));
+      return;
+    }
+  }
        
        if (cp->tileno_size == 0) {
                cp->tileno[cp->tileno_size] = tileno;
@@ -1325,8 +1428,18 @@ static void j2k_read_sot(opj_j2k_t *j2k) {
                                totlen);
                }
 
-       };
+       }
+  else
 #endif /* USE_JPWL */
+  {
+    /* totlen is negative or larger than the bytes left!!! */
+    if ((totlen < 0) || (totlen > (cio_numbytesleft(cio) + 8))) {
+      opj_event_msg(j2k->cinfo, EVT_ERROR,
+        "JPWL: bad tile byte size (%d bytes against %d bytes left)\n",
+        totlen, cio_numbytesleft(cio) + 8);
+      return;
+    }
+  }
 
        if (!totlen)
                totlen = cio_numbytesleft(cio) + 8;
@@ -1478,7 +1591,13 @@ static void j2k_read_sod(opj_j2k_t *j2k) {
        }       
 
        data = j2k->tile_data[curtileno];
+  data_ptr = data; /* store in case of failure */
        data = (unsigned char*) opj_realloc(data, (j2k->tile_len[curtileno] + len) * sizeof(unsigned char));
+  if( data == NULL ) {
+    opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not reallocated\n" );
+    opj_free( data_ptr );
+    return;
+    }
 
        data_ptr = data + j2k->tile_len[curtileno];
        for (i = 0; i < len; i++) {
@@ -1518,8 +1637,10 @@ static void j2k_read_rgn(opj_j2k_t *j2k) {
        int numcomps = j2k->image->numcomps;
 
        len = cio_read(cio, 2);                                                                         /* Lrgn */
+  (void)len;
        compno = cio_read(cio, numcomps <= 256 ? 1 : 2);                        /* Crgn */
        roisty = cio_read(cio, 1);                                                                      /* Srgn */
+  (void)roisty;
 
 #ifdef USE_JPWL
        if (j2k->cp->correct) {
@@ -1536,6 +1657,13 @@ static void j2k_read_rgn(opj_j2k_t *j2k) {
        };
 #endif /* USE_JPWL */
 
+  if (compno >= numcomps) {
+    opj_event_msg(j2k->cinfo, EVT_ERROR,
+      "bad component number in RGN (%d out of a maximum of %d)\n",
+      compno, j2k->image->numcomps);
+    return;
+  }
+
        tcp->tccps[compno].roishift = cio_read(cio, 1);                         /* SPrgn */
 }
 
@@ -1554,7 +1682,7 @@ static void j2k_write_eoc(opj_j2k_t *j2k) {
 
 static void j2k_read_eoc(opj_j2k_t *j2k) {
        int i, tileno;
-       opj_bool success;
+       opj_bool success = OPJ_FALSE;
 
        /* if packets should be decoded */
        if (j2k->cp->limit_decoding != DECODE_ALL_BUT_PACKETS) {
@@ -1562,11 +1690,17 @@ static void j2k_read_eoc(opj_j2k_t *j2k) {
                tcd_malloc_decode(tcd, j2k->image, j2k->cp);
                for (i = 0; i < j2k->cp->tileno_size; i++) {
                        tcd_malloc_decode_tile(tcd, j2k->image, j2k->cp, i, j2k->cstr_info);
-                       tileno = j2k->cp->tileno[i];
-                       success = tcd_decode_tile(tcd, j2k->tile_data[tileno], j2k->tile_len[tileno], tileno, j2k->cstr_info);
-                       opj_free(j2k->tile_data[tileno]);
-                       j2k->tile_data[tileno] = NULL;
-                       tcd_free_decode_tile(tcd, i);
+                       if (j2k->cp->tileno[i] != -1)
+                       {
+                               tileno = j2k->cp->tileno[i];
+                               success = tcd_decode_tile(tcd, j2k->tile_data[tileno], j2k->tile_len[tileno], tileno, j2k->cstr_info);
+        assert( tileno != -1 );
+                               opj_free(j2k->tile_data[tileno]);
+                               j2k->tile_data[tileno] = NULL;
+                               tcd_free_decode_tile(tcd, i);
+                       }
+                       else
+                               success = OPJ_FALSE;
                        if (success == OPJ_FALSE) {
                                j2k->state |= J2K_STATE_ERR;
                                break;
@@ -1737,6 +1871,17 @@ void j2k_destroy_decompress(opj_j2k_t *j2k) {
                opj_free(j2k->tile_len);
        }
        if(j2k->tile_data != NULL) {
+        if(j2k->cp != NULL) {
+            for (i = 0; i < j2k->cp->tileno_size; i++) {
+                int tileno = j2k->cp->tileno[i];
+                if( tileno != -1 )
+                  {
+                  opj_free(j2k->tile_data[tileno]);
+                  j2k->tile_data[tileno] = NULL;
+                  }
+            }
+        }
+
                opj_free(j2k->tile_data);
        }
        if(j2k->default_tcp != NULL) {
@@ -1856,9 +2001,15 @@ opj_image_t* j2k_decode(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestream_info_t *c
 #endif /* USE_JPWL */
 
                if (id >> 8 != 0xff) {
-                       opj_image_destroy(image);
-                       opj_event_msg(cinfo, EVT_ERROR, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id);
-                       return 0;
+               if(cio_numbytesleft(cio) != 0) /* not end of file reached and no EOC */
+          {
+               opj_event_msg(cinfo, EVT_ERROR, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id);
+               opj_image_destroy(image);
+               return 0;
+          }
+               opj_event_msg(cinfo, EVT_WARNING, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id);
+               j2k->state = J2K_STATE_NEOC;
+               break;
                }
                e = j2k_dec_mstab_lookup(id);
                /* Check if the marker is known*/
@@ -1877,7 +2028,10 @@ opj_image_t* j2k_decode(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestream_info_t *c
                        (*e->handler)(j2k);
                }
                if (j2k->state & J2K_STATE_ERR) 
+        {
+            opj_image_destroy(image);
                        return NULL;    
+        }
 
                if (j2k->state == J2K_STATE_MT) {
                        break;
@@ -1888,6 +2042,11 @@ opj_image_t* j2k_decode(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestream_info_t *c
        }
        if (j2k->state == J2K_STATE_NEOC) {
                j2k_read_eoc(j2k);
+               /* Check one last time for errors during decoding before returning */
+               if (j2k->state & J2K_STATE_ERR) {
+                       opj_image_destroy(image);
+                       return NULL;
+               }
        }
 
        if (j2k->state != J2K_STATE_MT) {
@@ -1949,9 +2108,15 @@ opj_image_t* j2k_decode_jpt_stream(opj_j2k_t *j2k, opj_cio_t *cio,  opj_codestre
                
                id = cio_read(cio, 2);
                if (id >> 8 != 0xff) {
-                       opj_image_destroy(image);
-                       opj_event_msg(cinfo, EVT_ERROR, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id);
-                       return 0;
+        if(cio_numbytesleft(cio) != 0) /* no end of file reached and no EOC */
+         {
+               opj_event_msg(cinfo, EVT_ERROR, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id);
+               opj_image_destroy(image);
+               return 0;
+         }
+               opj_event_msg(cinfo, EVT_WARNING, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id);
+               j2k->state = J2K_STATE_NEOC;
+               break;
                }
                e = j2k_dec_mstab_lookup(id);
                if (!(j2k->state & e->states)) {
index 5ae114c33b9dabc06fd79571b010e8a71b326903..d3322603c8be77de69a19a15294ce0c3a7dff002 100644 (file)
@@ -30,6 +30,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 #include "opj_includes.h"
+#include <assert.h>
 
 /** @defgroup JP2 JP2 - JPEG-2000 file format reader/writer */
 /*@{*/
@@ -172,6 +173,9 @@ static opj_bool jp2_read_boxhdr(opj_common_ptr cinfo, opj_cio_t *cio, opj_jp2_bo
        }
        else if (box->length == 0) {
                box->length = cio_numbytesleft(cio) + 8;
+       } else if (box->length < 0) {
+               opj_event_msg(cinfo, EVT_ERROR, "Integer overflow in box->length\n");
+               return OPJ_FALSE; /* TODO: actually check jp2_read_boxhdr's return value */
        }
        
        return OPJ_TRUE;
@@ -206,7 +210,10 @@ static opj_bool jp2_read_ihdr(opj_jp2_t *jp2, opj_cio_t *cio) {
 
        opj_common_ptr cinfo = jp2->cinfo;
 
-       jp2_read_boxhdr(cinfo, cio, &box);
+  if(jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) {
+    opj_event_msg(cinfo, EVT_ERROR, "Failed to read boxhdr\n");
+    return OPJ_FALSE;
+  }
        if (JP2_IHDR != box.type) {
                opj_event_msg(cinfo, EVT_ERROR, "Expected IHDR Marker\n");
                return OPJ_FALSE;
@@ -279,7 +286,10 @@ static opj_bool jp2_read_bpcc(opj_jp2_t *jp2, opj_cio_t *cio) {
 
        opj_common_ptr cinfo = jp2->cinfo;
 
-       jp2_read_boxhdr(cinfo, cio, &box);
+  if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) {
+    opj_event_msg(cinfo, EVT_ERROR, "Failed to read boxhdr\n");
+    return OPJ_FALSE;
+  }
        if (JP2_BPCC != box.type) {
                opj_event_msg(cinfo, EVT_ERROR, "Expected BPCC Marker\n");
                return OPJ_FALSE;
@@ -469,7 +479,7 @@ static opj_bool jp2_read_pclr(opj_jp2_t *jp2, opj_cio_t *cio,
        for(i = 0; i < nr_channels; ++i)
   {
 /* Cji */
-       *entries++ = cio_read(cio, channel_size[i]>>3);
+       *entries++ = cio_read(cio, (channel_size[i]+7)>>3);
   }
    }
 
@@ -512,10 +522,8 @@ static opj_bool jp2_read_cmap(opj_jp2_t *jp2, opj_cio_t *cio,
 static void jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color)
 {
        opj_jp2_cdef_info_t *info;
-       int color_space;
        unsigned short i, n, cn, typ, asoc, acn;
 
-       color_space = image->color_space;
        info = color->jp2_cdef->info;
        n = color->jp2_cdef->n;
 
@@ -525,6 +533,7 @@ static void jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color)
        if((asoc = info[i].asoc) == 0) continue;
 
        cn = info[i].cn; typ = info[i].typ; acn = asoc - 1;
+  (void)typ;
 
        if(cn != acn)
   {
@@ -639,90 +648,173 @@ opj_bool jp2_read_jp2h(opj_jp2_t *jp2, opj_cio_t *cio, opj_jp2_color_t *color)
 
        opj_common_ptr cinfo = jp2->cinfo;
 
-       jp2_read_boxhdr(cinfo, cio, &box);
-       do 
-   {
-       if (JP2_JP2H != box.type) 
-  {
-       if (box.type == JP2_JP2C) 
- {
-       opj_event_msg(cinfo, EVT_ERROR, "Expected JP2H Marker\n");
-       return OPJ_FALSE;
- }
-       cio_skip(cio, box.length - 8);
+  if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE;
+  do {
+    if (JP2_JP2H != box.type) 
+      {
+      if (box.type == JP2_JP2C) 
+        {
+        opj_event_msg(cinfo, EVT_ERROR, "Expected JP2H Marker\n");
+        return OPJ_FALSE;
+        }
+         if (box.length <= 8) return OPJ_FALSE;
+      cio_skip(cio, box.length - 8);
 
-       if(cio->bp >= cio->end) return OPJ_FALSE;
+      if(cio->bp >= cio->end) return OPJ_FALSE;
 
-       jp2_read_boxhdr(cinfo, cio, &box);
-  }
-   } while(JP2_JP2H != box.type);
+      if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE;
+      }
+  } while(JP2_JP2H != box.type);
 
        if (!jp2_read_ihdr(jp2, cio))
                return OPJ_FALSE;
        jp2h_end = box.init_pos + box.length;
 
-       if (jp2->bpc == 255) 
-   {
-       if (!jp2_read_bpcc(jp2, cio))
-               return OPJ_FALSE;
-   }
-       jp2_read_boxhdr(cinfo, cio, &box);
+  if (jp2->bpc == 255) 
+    {
+    if (!jp2_read_bpcc(jp2, cio))
+      return OPJ_FALSE;
+    }
+  if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE;
 
-       while(cio_tell(cio) < jp2h_end)
-   {
-       if(box.type == JP2_COLR)
-  {
-       if( !jp2_read_colr(jp2, cio, &box, color))
- {
-    cio_seek(cio, box.init_pos + 8);
-    cio_skip(cio, box.length - 8);
- }
-    jp2_read_boxhdr(cinfo, cio, &box);
-    continue;
-  }
+  while(cio_tell(cio) < jp2h_end)
+    {
+    if(box.type == JP2_COLR)
+      {
+      if( !jp2_read_colr(jp2, cio, &box, color))
+        {
+        if (box.length <= 8) return OPJ_FALSE;
+        cio_seek(cio, box.init_pos + 8);
+        cio_skip(cio, box.length - 8);
+        }
+      if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE;
+      continue;
+      }
     if(box.type == JP2_CDEF && !jp2->ignore_pclr_cmap_cdef)
-  {
-    if( !jp2_read_cdef(jp2, cio, &box, color))
- {
-    cio_seek(cio, box.init_pos + 8);
-    cio_skip(cio, box.length - 8);
- }
-    jp2_read_boxhdr(cinfo, cio, &box);
-    continue;
-  }
+      {
+      if( !jp2_read_cdef(jp2, cio, &box, color))
+        {
+        if (box.length <= 8) return OPJ_FALSE;
+        cio_seek(cio, box.init_pos + 8);
+        cio_skip(cio, box.length - 8);
+        }
+      if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE;
+      continue;
+      }
     if(box.type == JP2_PCLR && !jp2->ignore_pclr_cmap_cdef)
-  {
-    if( !jp2_read_pclr(jp2, cio, &box, color))
- {
-    cio_seek(cio, box.init_pos + 8);
-    cio_skip(cio, box.length - 8);
- }
-    jp2_read_boxhdr(cinfo, cio, &box);
-    continue;
-  }
+      {
+      if( !jp2_read_pclr(jp2, cio, &box, color))
+        {
+        if (box.length <= 8) return OPJ_FALSE;
+        cio_seek(cio, box.init_pos + 8);
+        cio_skip(cio, box.length - 8);
+        }
+      if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE;
+      continue;
+      }
     if(box.type == JP2_CMAP && !jp2->ignore_pclr_cmap_cdef)
-  {
-    if( !jp2_read_cmap(jp2, cio, &box, color))
- {
+      {
+      if( !jp2_read_cmap(jp2, cio, &box, color))
+        {
+        if (box.length <= 8) return OPJ_FALSE;
+        cio_seek(cio, box.init_pos + 8);
+        cio_skip(cio, box.length - 8);
+        }
+      if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE;
+      continue;
+      }
+    if (box.length <= 8) return OPJ_FALSE;
     cio_seek(cio, box.init_pos + 8);
     cio_skip(cio, box.length - 8);
- }
-    jp2_read_boxhdr(cinfo, cio, &box);
-    continue;
-  }
-       cio_seek(cio, box.init_pos + 8);
-       cio_skip(cio, box.length - 8);
-       jp2_read_boxhdr(cinfo, cio, &box);
+    if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE;
 
-   }/* while(cio_tell(cio) < box_end) */
+    }/* while(cio_tell(cio) < box_end) */
 
-       cio_seek(cio, jp2h_end);
+  cio_seek(cio, jp2h_end);
 
-/* Part 1, I.5.3.3 : 'must contain at least one' */
-       return (color->jp2_has_colr == 1);
+  /* Part 1, I.5.3.3 : 'must contain at least one' */
+  return (color->jp2_has_colr == 1);
 
 }/* jp2_read_jp2h() */
 
+static opj_bool opj_jp2_check_color(opj_image_t *image, opj_jp2_color_t *color, opj_common_ptr cinfo)
+{
+       int i;
+
+       /* testcase 4149.pdf.SIGSEGV.cf7.3501 */
+       if (color->jp2_cdef) {
+               opj_jp2_cdef_info_t *info = color->jp2_cdef->info;
+               int n = color->jp2_cdef->n;
+
+               for (i = 0; i < n; i++) {
+                       if (info[i].cn >= image->numcomps) {
+                               opj_event_msg(cinfo, EVT_ERROR, "Invalid component index %d (>= %d).\n", info[i].cn, image->numcomps);
+                               return OPJ_FALSE;
+                       }
+                       if (info[i].asoc > 0 && (info[i].asoc - 1) >= image->numcomps) {
+                               opj_event_msg(cinfo, EVT_ERROR, "Invalid component index %d (>= %d).\n", info[i].asoc - 1, image->numcomps);
+                               return OPJ_FALSE;
+                       }
+               }
+       }
+
+       /* testcases 451.pdf.SIGSEGV.f4c.3723, 451.pdf.SIGSEGV.5b5.3723 and
+          66ea31acbb0f23a2bbc91f64d69a03f5_signal_sigsegv_13937c0_7030_5725.pdf */
+       if (color->jp2_pclr && color->jp2_pclr->cmap) {
+               int nr_channels = color->jp2_pclr->nr_channels;
+               opj_jp2_cmap_comp_t *cmap = color->jp2_pclr->cmap;
+               opj_bool *pcol_usage, is_sane = OPJ_TRUE;
+
+               /* verify that all original components match an existing one */
+               for (i = 0; i < nr_channels; i++) {
+                       if (cmap[i].cmp >= image->numcomps) {
+                               opj_event_msg(cinfo, EVT_ERROR, "Invalid component index %d (>= %d).\n", cmap[i].cmp, image->numcomps);
+                               is_sane = OPJ_FALSE;
+                       }
+               }
+
+               pcol_usage = opj_calloc(nr_channels, sizeof(opj_bool));
+               if (!pcol_usage) {
+                       opj_event_msg(cinfo, EVT_ERROR, "Unexpected OOM.\n");
+                       return OPJ_FALSE;
+               }
+               /* verify that no component is targeted more than once */
+               for (i = 0; i < nr_channels; i++) {
+      int pcol = cmap[i].pcol;
+      assert(cmap[i].mtyp == 0 || cmap[i].mtyp == 1);
+                       if (pcol >= nr_channels) {
+                               opj_event_msg(cinfo, EVT_ERROR, "Invalid component/palette index for direct mapping %d.\n", pcol);
+                               is_sane = OPJ_FALSE;
+                       }
+                       else if (pcol_usage[pcol] && cmap[i].mtyp == 1) {
+                               opj_event_msg(cinfo, EVT_ERROR, "Component %d is mapped twice.\n", pcol);
+                               is_sane = OPJ_FALSE;
+                       }
+      else if (cmap[i].mtyp == 0 && cmap[i].pcol != 0) {
+        /* I.5.3.5 PCOL: If the value of the MTYP field for this channel is 0, then
+         * the value of this field shall be 0. */
+                               opj_event_msg(cinfo, EVT_ERROR, "Direct use at #%d however pcol=%d.\n", i, pcol);
+                               is_sane = OPJ_FALSE;
+      }
+                       else
+                               pcol_usage[pcol] = OPJ_TRUE;
+               }
+               /* verify that all components are targeted at least once */
+               for (i = 0; i < nr_channels; i++) {
+                       if (!pcol_usage[i] && cmap[i].mtyp != 0) {
+                               opj_event_msg(cinfo, EVT_ERROR, "Component %d doesn't have a mapping.\n", i);
+                               is_sane = OPJ_FALSE;
+                       }
+               }
+               opj_free(pcol_usage);
+               if (!is_sane) {
+                       return OPJ_FALSE;
+               }
+       }
+
+       return OPJ_TRUE;
+}
+
 opj_image_t* opj_jp2_decode(opj_jp2_t *jp2, opj_cio_t *cio, 
        opj_codestream_info_t *cstr_info) 
 {
@@ -756,6 +848,10 @@ opj_image_t* opj_jp2_decode(opj_jp2_t *jp2, opj_cio_t *cio,
    }
    
     if (!jp2->ignore_pclr_cmap_cdef){
+           if (!opj_jp2_check_color(image, &color, cinfo)) {
+        opj_event_msg(cinfo, EVT_ERROR, "Failed to decode PCRL box\n");
+                   return NULL;
+           }
 
     /* Set Image Color Space */
        if (jp2->enumcs == 16)
@@ -839,8 +935,10 @@ static opj_bool jp2_read_ftyp(opj_jp2_t *jp2, opj_cio_t *cio) {
 
        opj_common_ptr cinfo = jp2->cinfo;
 
-       jp2_read_boxhdr(cinfo, cio, &box);
-
+  if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) {
+    opj_event_msg(cinfo, EVT_ERROR, "Failed to read boxhdr\n");
+    return OPJ_FALSE;
+  }
        if (JP2_FTYP != box.type) {
                opj_event_msg(cinfo, EVT_ERROR, "Expected FTYP Marker\n");
                return OPJ_FALSE;
@@ -849,6 +947,14 @@ static opj_bool jp2_read_ftyp(opj_jp2_t *jp2, opj_cio_t *cio) {
        jp2->brand = cio_read(cio, 4);          /* BR */
        jp2->minversion = cio_read(cio, 4);     /* MinV */
        jp2->numcl = (box.length - 16) / 4;
+
+  /* edf_c2_1673169.jp2 */
+       if (cio_numbytesleft(cio) < ((int)jp2->numcl * 4)) {
+               opj_event_msg(cinfo, EVT_ERROR, "Not enough bytes in FTYP Box "
+                               "(expected %d, but only %d left)\n",
+                               ((int)jp2->numcl * 4), cio_numbytesleft(cio));
+               return OPJ_FALSE;
+       }
        jp2->cl = (unsigned int *) opj_malloc(jp2->numcl * sizeof(unsigned int));
 
        for (i = 0; i < (int)jp2->numcl; i++) {
@@ -897,15 +1003,20 @@ static opj_bool jp2_read_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, unsigned int *j2k_
 
        opj_common_ptr cinfo = jp2->cinfo;
 
-       jp2_read_boxhdr(cinfo, cio, &box);
+  if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) {
+    opj_event_msg(cinfo, EVT_ERROR, "Failed to read boxhdr\n");
+    return OPJ_FALSE;
+  }
        do {
                if(JP2_JP2C != box.type) {
+                       if (box.length <= 8) return OPJ_FALSE;
                        cio_skip(cio, box.length - 8);
-                       jp2_read_boxhdr(cinfo, cio, &box);
+                       if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE;
                }
        } while(JP2_JP2C != box.type);
 
        *j2k_codestream_offset = cio_tell(cio);
+       if (box.length <= 8) return OPJ_FALSE;
        *j2k_codestream_length = box.length - 8;
 
        return OPJ_TRUE;
@@ -930,7 +1041,10 @@ static opj_bool jp2_read_jp(opj_jp2_t *jp2, opj_cio_t *cio) {
 
        opj_common_ptr cinfo = jp2->cinfo;
 
-       jp2_read_boxhdr(cinfo, cio, &box);
+  if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) {
+    opj_event_msg(cinfo, EVT_ERROR, "Failed to read boxhdr\n");
+    return OPJ_FALSE;
+  }
        if (JP2_JP != box.type) {
                opj_event_msg(cinfo, EVT_ERROR, "Expected JP Marker\n");
                return OPJ_FALSE;
@@ -1070,6 +1184,7 @@ void jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters) {
 opj_jp2_t* jp2_create_compress(opj_common_ptr cinfo) {
        opj_jp2_t *jp2 = (opj_jp2_t*)opj_malloc(sizeof(opj_jp2_t));
        if(jp2) {
+               memset(jp2, 0, sizeof(opj_jp2_t));
                jp2->cinfo = cinfo;
                /* create the J2K codec */
                jp2->j2k = j2k_create_compress(cinfo);
index 53e9fac0438131b1a3d9220dcea1c856c3efaf32..59147c8b3d1237fb0a3a96c9a7044619355c88df 100644 (file)
@@ -135,6 +135,10 @@ typedef enum COLOR_SPACE {
        CLRSPC_SYCC = 3                 /**< YUV */
 } OPJ_COLOR_SPACE;
 
+#define ENUMCS_SRGB 16
+#define ENUMCS_GRAY 17
+#define ENUMCS_SYCC 18
+
 /**
 Supported codec
 */
index 82e12be03a9e56574c4b9d5f3d4510cd6f7afd40..5d0a877b840957e4dc642f75217454904f7878d4 100644 (file)
@@ -3,7 +3,7 @@
  * the endian check is a blender define */
 
 /* create config.h for CMake */
-#define PACKAGE_VERSION "1.5.0"
+#define PACKAGE_VERSION "1.5.2"
 
 #define HAVE_INTTYPES_H
 #define HAVE_MEMORY_H
@@ -23,6 +23,7 @@
 /* #undef HAVE_LIBLCMS2 */
 /* #undef HAVE_LCMS1_H */
 /* #undef HAVE_LCMS2_H */
+/* #undef USE_SYSTEM_GETOPT */
 
 /* Byte order.  */
 /* All compilers that support Mac OS X define either __BIG_ENDIAN__ or
index 2b5866a99902bd32a2d754d2bd442d2db9d109ce..e9194fd9886f626267bfb9587dd7ad4b7e8bd015 100644 (file)
@@ -89,18 +89,17 @@ Most compilers implement their own version of this keyword ...
 /* MSVC and Borland C do not have lrintf */
 #if defined(_MSC_VER) || defined(__BORLANDC__)
 static INLINE long lrintf(float f){
-#ifdef _M_X64
-    return (long)((f>0.0f) ? (f + 0.5f):(f -0.5f));
-#else
-    int i;
+#ifdef _M_IX86
+    long int i;
  
     _asm{
         fld f
         fistp i
     };
     return i;
-#endif
+#else
+    return (long)((f>0.0f) ? (f + 0.5f):(f -0.5f));
+#endif /* _M_IX86 */
 }
 #endif
 
index 87493f497c7a5e07e08983917ac6015b92b9e83f..aef2ee3b8c96542fe43ffcca5ed14d3a2ad6d80c 100644 (file)
@@ -83,8 +83,10 @@ Allocate memory aligned to a 16 byte boundry
 #else /* Not _WIN32 */
        #if defined(__sun)
                #define HAVE_MEMALIGN
+  #elif defined(__FreeBSD__)
+    #define HAVE_POSIX_MEMALIGN
        /* Linux x86_64 and OSX always align allocations to 16 bytes */
-       #elif !defined(__amd64__) && !defined(__APPLE__)        
+       #elif !defined(__amd64__) && !defined(__APPLE__) && !defined(_AIX)
                #define HAVE_MEMALIGN
                #include <malloc.h>                     
        #endif
diff --git a/extern/libopenjpeg/patches/fbsd.patch b/extern/libopenjpeg/patches/fbsd.patch
deleted file mode 100644 (file)
index 90e7760..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-Index: extern/libopenjpeg/opj_malloc.h
-===================================================================
---- extern/libopenjpeg/opj_malloc.h    (revision 27736)
-+++ extern/libopenjpeg/opj_malloc.h    (working copy)
-@@ -76,7 +76,7 @@
-       #if defined(__sun)
-                       #define HAVE_MEMALIGN
-               #elif defined(__GNUC__)
--                        #ifndef __APPLE__
-+                        #if !defined(__APPLE__) && !defined(__FreeBSD__)
-                           #define HAVE_MEMALIGN
-                           #include <malloc.h>
-                         #endif
diff --git a/extern/libopenjpeg/patches/osx.patch b/extern/libopenjpeg/patches/osx.patch
deleted file mode 100644 (file)
index c518978..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-Index: opj_malloc.h
-===================================================================
---- opj_malloc.h       (revision 15089)
-+++ opj_malloc.h       (working copy)
-@@ -76,8 +76,10 @@
-       #if defined(__sun)
-                       #define HAVE_MEMALIGN
-               #elif defined(__GNUC__)
--                      #define HAVE_MEMALIGN
--                      #include <malloc.h>             
-+                        #ifndef __APPLE__
-+                          #define HAVE_MEMALIGN
-+                          #include <malloc.h>
-+                        #endif
-               /* Linux x86_64 and OSX always align allocations to 16 bytes */
-               #elif !defined(__amd64__) && !defined(__APPLE__)        
-                       /* FIXME: Yes, this is a big assumption */
index 477720412aa13aafdfa4f98c7259823c929f8a35..ed9cdc3fea6b2df04d20fc1f9159175d62fa983c 100644 (file)
@@ -1577,6 +1577,7 @@ void t1_decode_cblks(
                                        opj_free(cblk->segs);
                                } /* cblkno */
                                opj_free(precinct->cblks.dec);
+                precinct->cblks.dec = NULL;
                        } /* precno */
                } /* bandno */
        } /* resno */
index 232a54373290efde0216abc1dea918d96f7f793f..2585c3d56a6891287f3d2421649b049b3df22799 100644 (file)
@@ -30,6 +30,7 @@
  */
 
 #include "opj_includes.h"
+#include <assert.h>
 
 /** @defgroup T2 T2 - Implementation of a tier-2 coding */
 /*@{*/
@@ -64,7 +65,7 @@ static int t2_encode_packet(opj_tcd_tile_t *tile, opj_tcp_t *tcp, opj_pi_iterato
 @param cblksty
 @param first
 */
-static void t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int first);
+static opj_bool t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int first);
 /**
 Decode a packet of a tile from a source buffer
 @param t2 T2 handle
@@ -296,9 +297,17 @@ static int t2_encode_packet(opj_tcd_tile_t * tile, opj_tcp_t * tcp, opj_pi_itera
        return (c - dest);
 }
 
-static void t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int first) {
+static opj_bool t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int first) {
        opj_tcd_seg_t* seg;
-       cblk->segs = (opj_tcd_seg_t*) opj_realloc(cblk->segs, (index + 1) * sizeof(opj_tcd_seg_t));
+    opj_tcd_seg_t* segs;
+    segs = (opj_tcd_seg_t*) opj_realloc(cblk->segs, (index + 1) * sizeof(opj_tcd_seg_t));
+
+    if (segs == NULL)
+    {
+        return OPJ_FALSE;
+    }
+    cblk->segs = segs;
+
        seg = &cblk->segs[index];
        seg->data = NULL;
        seg->dataindex = 0;
@@ -316,6 +325,8 @@ static void t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int fi
        } else {
                seg->maxpasses = 109;
        }
+
+    return OPJ_TRUE;
 }
 
 static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_tile_t *tile, 
@@ -330,13 +341,15 @@ static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_t
        int precno = pi->precno;        /* precinct value */
        int layno  = pi->layno;         /* quality layer value */
 
-       opj_tcd_resolution_t* res = &tile->comps[compno].resolutions[resno];
-
        unsigned char *hd = NULL;
        int present;
        
        opj_bio_t *bio = NULL;  /* BIO component */
-       
+
+       opj_tcd_resolution_t* res;
+       assert(&tile->comps[compno] != NULL);
+       res = &tile->comps[compno].resolutions[resno];
+
        if (layno == 0) {
                for (bandno = 0; bandno < res->numbands; bandno++) {
                        opj_tcd_band_t *band = &res->bands[bandno];
@@ -462,12 +475,22 @@ static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_t
                        cblk->numlenbits += increment;
                        segno = 0;
                        if (!cblk->numsegs) {
-                               t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 1);
+                if (!t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 1))
+                {
+                    opj_event_msg(t2->cinfo, EVT_ERROR, "Out of memory\n");
+                    bio_destroy(bio);
+                    return -999;
+                }
                        } else {
                                segno = cblk->numsegs - 1;
                                if (cblk->segs[segno].numpasses == cblk->segs[segno].maxpasses) {
                                        ++segno;
-                                       t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 0);
+                    if (!t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 0))
+                    {
+                        opj_event_msg(t2->cinfo, EVT_ERROR, "Out of memory\n");
+                        bio_destroy(bio);
+                        return -999;
+                    }
                                }
                        }
                        n = cblk->numnewpasses;
@@ -478,7 +501,12 @@ static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_t
                                n -= cblk->segs[segno].numnewpasses;
                                if (n > 0) {
                                        ++segno;
-                                       t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 0);
+                    if (!t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 0))
+                    {
+                        opj_event_msg(t2->cinfo, EVT_ERROR, "Out of memory\n");
+                        bio_destroy(bio);
+                        return -999;
+                    }
                                }
                        } while (n > 0);
                }
@@ -714,7 +742,11 @@ int t2_decode_packets(opj_t2_t *t2, unsigned char *src, int len, int tileno, opj
                        } else {
                                e = 0;
                        }
-                       if(e == -999) return -999;
+            if(e == -999)
+            {
+                pi_destroy(pi, cp, tileno);
+                return -999;
+            }
                        /* progression in resolution */
                        image->comps[pi[pino].compno].resno_decoded =   
                                (e > 0) ? 
index 18cdbc786bca6318246f9c556c4b77f82b6a9fff..62904eb2c655fd93eaf2dca68ffd29dd139b1d0b 100644 (file)
@@ -30,7 +30,9 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#define _ISOC99_SOURCE /* lrintf is C99 */
 #include "opj_includes.h"
+#include <assert.h>
 
 void tcd_dump(FILE *fd, opj_tcd_t *tcd, opj_tcd_image_t * img) {
        int tileno, compno, resno, bandno, precno;/*, cblkno;*/
@@ -249,7 +251,9 @@ void tcd_malloc_encode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int c
                                        cbgwidthexpn = pdx - 1;
                                        cbgheightexpn = pdy - 1;
                                }
-                               
+        (void)brcbgyend;
+        (void)brcbgxend;
+
                                cblkwidthexpn = int_min(tccp->cblkw, cbgwidthexpn);
                                cblkheightexpn = int_min(tccp->cblkh, cbgheightexpn);
                                
@@ -333,8 +337,10 @@ void tcd_malloc_encode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int c
                                                        cblk->y0 = int_max(cblkystart, prc->y0);
                                                        cblk->x1 = int_min(cblkxend, prc->x1);
                                                        cblk->y1 = int_min(cblkyend, prc->y1);
-                                                       cblk->data = (unsigned char*) opj_calloc(8192+2, sizeof(unsigned char));
+                                                       cblk->data = (unsigned char*) opj_calloc(9728+2, sizeof(unsigned char));
                                                        /* FIXME: mqc_init_enc and mqc_byteout underrun the buffer if we don't do this. Why? */
+                                                       cblk->data[0] = 0;
+                                                       cblk->data[1] = 0;
                                                        cblk->data += 2;
                                                        cblk->layers = (opj_tcd_layer_t*) opj_calloc(100, sizeof(opj_tcd_layer_t));
                                                        cblk->passes = (opj_tcd_pass_t*) opj_calloc(100, sizeof(opj_tcd_pass_t));
@@ -509,6 +515,8 @@ void tcd_init_encode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int cur
                                        cbgwidthexpn = pdx - 1;
                                        cbgheightexpn = pdy - 1;
                                }
+        (void)brcbgyend;
+        (void)brcbgxend;
                                
                                cblkwidthexpn = int_min(tccp->cblkw, cbgwidthexpn);
                                cblkheightexpn = int_min(tccp->cblkh, cbgheightexpn);
@@ -594,6 +602,8 @@ void tcd_init_encode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int cur
                                                        cblk->y1 = int_min(cblkyend, prc->y1);
                                                        cblk->data = (unsigned char*) opj_calloc(8192+2, sizeof(unsigned char));
                                                        /* FIXME: mqc_init_enc and mqc_byteout underrun the buffer if we don't do this. Why? */
+                                                       cblk->data[0] = 0;
+                                                       cblk->data[1] = 0;
                                                        cblk->data += 2;
                                                        cblk->layers = (opj_tcd_layer_t*) opj_calloc(100, sizeof(opj_tcd_layer_t));
                                                        cblk->passes = (opj_tcd_pass_t*) opj_calloc(100, sizeof(opj_tcd_pass_t));
@@ -614,7 +624,7 @@ void tcd_malloc_decode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp) {
        tcd->image = image;
        tcd->tcd_image->tw = cp->tw;
        tcd->tcd_image->th = cp->th;
-       tcd->tcd_image->tiles = (opj_tcd_tile_t *) opj_malloc(cp->tw * cp->th * sizeof(opj_tcd_tile_t));
+    tcd->tcd_image->tiles = (opj_tcd_tile_t *) opj_calloc(cp->tw * cp->th, sizeof(opj_tcd_tile_t));
 
        /* 
        Allocate place to store the decoded data = final image
@@ -690,6 +700,12 @@ void tcd_malloc_decode_tile(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp,
                opj_tccp_t *tccp = &tcp->tccps[compno];
                opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
                
+               if (tccp->numresolutions <= 0)
+               {
+                       cp->tileno[tileno] = -1;
+                       return;
+               }
+
                /* border of each tile component (global) */
                tilec->x0 = int_ceildiv(tile->x0, image->comps[compno].dx);
                tilec->y0 = int_ceildiv(tile->y0, image->comps[compno].dy);
@@ -749,6 +765,8 @@ void tcd_malloc_decode_tile(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp,
                                cbgwidthexpn = pdx - 1;
                                cbgheightexpn = pdy - 1;
                        }
+      (void)brcbgyend;
+      (void)brcbgxend;
                        
                        cblkwidthexpn = int_min(tccp->cblkw, cbgwidthexpn);
                        cblkheightexpn = int_min(tccp->cblkh, cbgheightexpn);
@@ -1370,16 +1388,31 @@ opj_bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno
        if (l == -999) {
                eof = 1;
                opj_event_msg(tcd->cinfo, EVT_ERROR, "tcd_decode: incomplete bistream\n");
+    return OPJ_FALSE;
        }
        
        /*------------------TIER1-----------------*/
        
        t1_time = opj_clock();  /* time needed to decode a tile */
        t1 = t1_create(tcd->cinfo);
+    if (t1 == NULL)
+    {
+        opj_event_msg(tcd->cinfo, EVT_ERROR, "Out of memory\n");
+        t1_destroy(t1);
+        return OPJ_FALSE;
+    }
+
        for (compno = 0; compno < tile->numcomps; ++compno) {
                opj_tcd_tilecomp_t* tilec = &tile->comps[compno];
                /* The +3 is headroom required by the vectorized DWT */
                tilec->data = (int*) opj_aligned_malloc((((tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0))+3) * sizeof(int));
+        if (tilec->data == NULL)
+        {
+            opj_event_msg(tcd->cinfo, EVT_ERROR, "Out of memory\n");
+            t1_destroy(t1);
+            return OPJ_FALSE;
+        }
+
                t1_decode_cblks(t1, tilec, &tcd->tcp->tccps[compno]);
        }
        t1_destroy(t1);
@@ -1394,13 +1427,15 @@ opj_bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno
                int numres2decode;
 
                if (tcd->cp->reduce != 0) {
-                       tcd->image->comps[compno].resno_decoded =
-                               tile->comps[compno].numresolutions - tcd->cp->reduce - 1;
-                       if (tcd->image->comps[compno].resno_decoded < 0) {                              
+                       if ( tile->comps[compno].numresolutions < ( tcd->cp->reduce - 1 ) ) {                           
                                opj_event_msg(tcd->cinfo, EVT_ERROR, "Error decoding tile. The number of resolutions to remove [%d+1] is higher than the number "
                                        " of resolutions in the original codestream [%d]\nModify the cp_reduce parameter.\n", tcd->cp->reduce, tile->comps[compno].numresolutions);
                                return OPJ_FALSE;
                        }
+      else {
+                       tcd->image->comps[compno].resno_decoded =
+                               tile->comps[compno].numresolutions - tcd->cp->reduce - 1;
+      }
                }
 
                numres2decode = tcd->image->comps[compno].resno_decoded + 1;
@@ -1421,6 +1456,13 @@ opj_bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno
                int n = (tile->comps[0].x1 - tile->comps[0].x0) * (tile->comps[0].y1 - tile->comps[0].y0);
 
                if (tile->numcomps >= 3 ){
+      /* testcase 1336.pdf.asan.47.376 */
+      if ((tile->comps[0].x1 - tile->comps[0].x0) * (tile->comps[0].y1 - tile->comps[0].y0) < n ||
+        (  tile->comps[1].x1 - tile->comps[1].x0) * (tile->comps[1].y1 - tile->comps[1].y0) < n ||
+        (  tile->comps[2].x1 - tile->comps[2].x0) * (tile->comps[2].y1 - tile->comps[2].y0) < n) {
+        opj_event_msg(tcd->cinfo, EVT_ERROR, "Tiles don't all have the same dimension. Skip the MCT step.\n");
+        return OPJ_FALSE;
+      }
                        if (tcd->tcp->tccps[0].qmfbid == 1) {
                                mct_decode(
                                                tile->comps[0].data,
@@ -1452,18 +1494,33 @@ opj_bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno
                int tw = tilec->x1 - tilec->x0;
                int w = imagec->w;
 
+               int i, j;
                int offset_x = int_ceildivpow2(imagec->x0, imagec->factor);
                int offset_y = int_ceildivpow2(imagec->y0, imagec->factor);
+    /* NR-DEC-2977.pdf.asan.67.2198.jp2-52-decode */
+    if( res->x0 - offset_x < 0 || res->x1 - offset_x < 0
+     || res->y0 - offset_y < 0 || res->y1 - offset_y < 0 )
+      {
+      opj_event_msg(tcd->cinfo, EVT_ERROR, "Impossible offsets %d / %d\n", offset_x, offset_y);
+      return OPJ_FALSE;
+      }
+    assert( 0 <= res->x0 - offset_x && 0 <= res->x1 - offset_x );
+    assert( 0 <= res->y0 - offset_y && 0 <= res->y1 - offset_y );
 
-               int i, j;
                if(!imagec->data){
                        imagec->data = (int*) opj_malloc(imagec->w * imagec->h * sizeof(int));
                }
+        if (!imagec->data)
+        {
+            opj_event_msg(tcd->cinfo, EVT_ERROR, "Out of memory\n");
+            return OPJ_FALSE;
+        }
                if(tcd->tcp->tccps[compno].qmfbid == 1) {
                        for(j = res->y0; j < res->y1; ++j) {
                                for(i = res->x0; i < res->x1; ++i) {
                                        int v = tilec->data[i - res->x0 + (j - res->y0) * tw];
                                        v += adjust;
+          /*assert( (i - offset_x) + (j - offset_y) * w >= 0 );*/
                                        imagec->data[(i - offset_x) + (j - offset_y) * w] = int_clamp(v, min, max);
                                }
                        }
@@ -1473,6 +1530,7 @@ opj_bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno
                                        float tmp = ((float*)tilec->data)[i - res->x0 + (j - res->y0) * tw];
                                        int v = lrintf(tmp);
                                        v += adjust;
+          /*assert( (i - offset_x) + (j - offset_y) * w >= 0 );*/
                                        imagec->data[(i - offset_x) + (j - offset_y) * w] = int_clamp(v, min, max);
                                }
                        }
@@ -1492,32 +1550,51 @@ opj_bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno
 
 void tcd_free_decode(opj_tcd_t *tcd) {
        opj_tcd_image_t *tcd_image = tcd->tcd_image;    
+    int i = 0;
+    for (i = 0; i < tcd_image->tw * tcd_image->th; i++)
+    {
+        tcd_free_decode_tile(tcd, i);
+    }
+
        opj_free(tcd_image->tiles);
 }
 
 void tcd_free_decode_tile(opj_tcd_t *tcd, int tileno) {
-       int compno,resno,bandno,precno;
+    int compno,resno,bandno,precno,cblkno;
 
        opj_tcd_image_t *tcd_image = tcd->tcd_image;
 
        opj_tcd_tile_t *tile = &tcd_image->tiles[tileno];
-       for (compno = 0; compno < tile->numcomps; compno++) {
-               opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
-               for (resno = 0; resno < tilec->numresolutions; resno++) {
-                       opj_tcd_resolution_t *res = &tilec->resolutions[resno];
-                       for (bandno = 0; bandno < res->numbands; bandno++) {
-                               opj_tcd_band_t *band = &res->bands[bandno];
-                               for (precno = 0; precno < res->ph * res->pw; precno++) {
-                                       opj_tcd_precinct_t *prec = &band->precincts[precno];
-                                       if (prec->imsbtree != NULL) tgt_destroy(prec->imsbtree);
-                                       if (prec->incltree != NULL) tgt_destroy(prec->incltree);
+    if (tile->comps != NULL) {
+        for (compno = 0; compno < tile->numcomps; compno++) {
+            opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
+            for (resno = 0; resno < tilec->numresolutions; resno++) {
+                opj_tcd_resolution_t *res = &tilec->resolutions[resno];
+                for (bandno = 0; bandno < res->numbands; bandno++) {
+                    opj_tcd_band_t *band = &res->bands[bandno];
+                    for (precno = 0; precno < res->ph * res->pw; precno++) {
+                        opj_tcd_precinct_t *prec = &band->precincts[precno];
+                        if (prec->cblks.dec != NULL) {
+                            for (cblkno = 0; cblkno < prec->cw * prec->ch; ++cblkno) {
+                                opj_tcd_cblk_dec_t* cblk = &prec->cblks.dec[cblkno];
+                                opj_free(cblk->data);
+                                opj_free(cblk->segs);
+                            }
+                            opj_free(prec->cblks.dec);
+                        }
+                        if (prec->imsbtree != NULL) tgt_destroy(prec->imsbtree);
+                        if (prec->incltree != NULL) tgt_destroy(prec->incltree);
+
+
+                    }
+                    opj_free(band->precincts);
                                }
-                               opj_free(band->precincts);
                        }
+            opj_free(tilec->resolutions);
                }
-               opj_free(tilec->resolutions);
+        opj_free(tile->comps);
+        tile->comps = NULL;
        }
-       opj_free(tile->comps);
 }