Merge commit '5efadcb8cdef6fc5ca5f1f72e45ef3b23016b1c4'
authorMichael Niedermayer <michaelni@gmx.at>
Wed, 3 Jul 2013 10:16:24 +0000 (12:16 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Wed, 3 Jul 2013 10:16:24 +0000 (12:16 +0200)
* commit '5efadcb8cdef6fc5ca5f1f72e45ef3b23016b1c4':
  jpeg2000: Clean up return paths and error messages

Conflicts:
libavcodec/jpeg2000dec.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
libavcodec/jpeg2000dec.c

@@@ -160,46 -161,31 +160,46 @@@ static int tag_tree_decode(Jpeg2000Deco
  static int get_siz(Jpeg2000DecoderContext *s)
  {
      int i;
-         return AVERROR(EINVAL);
 +    int ncomponents;
 +
 +    if (bytestream2_get_bytes_left(&s->g) < 36)
++        return AVERROR_INVALIDDATA;
  
 -    if (s->buf_end - s->buf < 36)
 +    s->avctx->profile = bytestream2_get_be16u(&s->g); // Rsiz
 +    s->width          = bytestream2_get_be32u(&s->g); // Width
 +    s->height         = bytestream2_get_be32u(&s->g); // Height
 +    s->image_offset_x = bytestream2_get_be32u(&s->g); // X0Siz
 +    s->image_offset_y = bytestream2_get_be32u(&s->g); // Y0Siz
 +    s->tile_width     = bytestream2_get_be32u(&s->g); // XTSiz
 +    s->tile_height    = bytestream2_get_be32u(&s->g); // YTSiz
 +    s->tile_offset_x  = bytestream2_get_be32u(&s->g); // XT0Siz
 +    s->tile_offset_y  = bytestream2_get_be32u(&s->g); // YT0Siz
 +    ncomponents       = bytestream2_get_be16u(&s->g); // CSiz
 +
 +    if (ncomponents <= 0 || ncomponents > 4) {
 +        av_log(s->avctx, AV_LOG_ERROR, "unsupported/invalid ncomponents: %d\n", ncomponents);
-         return AVERROR(EINVAL);
++        return AVERROR_INVALIDDATA;
 +    }
 +    s->ncomponents = ncomponents;
 +
 +    if (s->tile_width<=0 || s->tile_height<=0)
-         return AVERROR(EINVAL);
+         return AVERROR_INVALIDDATA;
  
 -    s->avctx->profile = bytestream_get_be16(&s->buf); // Rsiz
 -    s->width          = bytestream_get_be32(&s->buf); // Width
 -    s->height         = bytestream_get_be32(&s->buf); // Height
 -    s->image_offset_x = bytestream_get_be32(&s->buf); // X0Siz
 -    s->image_offset_y = bytestream_get_be32(&s->buf); // Y0Siz
 -    s->tile_width     = bytestream_get_be32(&s->buf); // XTSiz
 -    s->tile_height    = bytestream_get_be32(&s->buf); // YTSiz
 -    s->tile_offset_x  = bytestream_get_be32(&s->buf); // XT0Siz
 -    s->tile_offset_y  = bytestream_get_be32(&s->buf); // YT0Siz
 -    s->ncomponents    = bytestream_get_be16(&s->buf); // CSiz
 -
 -    if (s->buf_end - s->buf < 2 * s->ncomponents)
 +    if (bytestream2_get_bytes_left(&s->g) < 3 * s->ncomponents)
-         return AVERROR(EINVAL);
+         return AVERROR_INVALIDDATA;
  
      for (i = 0; i < s->ncomponents; i++) { // Ssiz_i XRsiz_i, YRsiz_i
 -        uint8_t x = bytestream_get_byte(&s->buf);
 +        uint8_t x = bytestream2_get_byteu(&s->g);
          s->cbps[i]   = (x & 0x7f) + 1;
          s->precision = FFMAX(s->cbps[i], s->precision);
 -        s->sgnd[i]   = (x & 0x80) == 1;
 -        s->cdx[i]    = bytestream_get_byte(&s->buf);
 -        s->cdy[i]    = bytestream_get_byte(&s->buf);
 +        s->sgnd[i]   = !!(x & 0x80);
 +        s->cdx[i]    = bytestream2_get_byteu(&s->g);
 +        s->cdy[i]    = bytestream2_get_byteu(&s->g);
 +        if (s->cdx[i] != 1 || s->cdy[i] != 1) {
 +            av_log(s->avctx, AV_LOG_ERROR, "unsupported/ CDxy values %d %d for component %d\n", s->cdx[i], s->cdy[i], i);
 +            if (!s->cdx[i] || !s->cdy[i])
 +                return AVERROR_INVALIDDATA;
 +        }
      }
  
      s->numXtiles = ff_jpeg2000_ceildiv(s->width  - s->tile_offset_x, s->tile_width);
@@@ -264,15 -249,14 +264,15 @@@ static int get_cox(Jpeg2000DecoderConte
  {
      uint8_t byte;
  
 -    if (s->buf_end - s->buf < 5)
 -        return AVERROR(EINVAL);
 +    if (bytestream2_get_bytes_left(&s->g) < 5)
-         return AVERROR(EINVAL);
++        return AVERROR_INVALIDDATA;
      /*  nreslevels = number of resolution levels
                     = number of decomposition level +1 */
 -    c->nreslevels = bytestream_get_byte(&s->buf) + 1;
 -
 -    if (c->nreslevels > JPEG2000_MAX_RESLEVELS)
 +    c->nreslevels = bytestream2_get_byteu(&s->g) + 1;
 +    if (c->nreslevels >= JPEG2000_MAX_RESLEVELS) {
 +        av_log(s->avctx, AV_LOG_ERROR, "nreslevels %d is invalid\n", c->nreslevels);
          return AVERROR_INVALIDDATA;
 +    }
  
      /* compute number of resolution levels to decode */
      if (c->nreslevels < s->reduction_factor)
@@@ -317,27 -299,23 +317,27 @@@ static int get_cod(Jpeg2000DecoderConte
                     uint8_t *properties)
  {
      Jpeg2000CodingStyle tmp;
 -    int compno;
 +    int compno, ret;
  
 -    if (s->buf_end - s->buf < 5)
 +    if (bytestream2_get_bytes_left(&s->g) < 5)
-         return AVERROR(EINVAL);
+         return AVERROR_INVALIDDATA;
  
 -    tmp.log2_prec_width  =
 -    tmp.log2_prec_height = 15;
 -
 -    tmp.csty = bytestream_get_byte(&s->buf);
 +    tmp.csty = bytestream2_get_byteu(&s->g);
  
      // get progression order
 -    tmp.prog_order = bytestream_get_byte(&s->buf);
 +    tmp.prog_order = bytestream2_get_byteu(&s->g);
 +
 +    tmp.nlayers = bytestream2_get_be16u(&s->g);
 +    tmp.mct     = bytestream2_get_byteu(&s->g); // multiple component transformation
  
 -    tmp.nlayers = bytestream_get_be16(&s->buf);
 -    tmp.mct     = bytestream_get_byte(&s->buf); // multiple component transformation
 +    if (tmp.mct && s->ncomponents < 3) {
 +        av_log(s->avctx, AV_LOG_ERROR, "MCT %d with too few components (%d)\n", tmp.mct, s->ncomponents);
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    if ((ret = get_cox(s, &tmp)) < 0)
 +        return ret;
  
 -    get_cox(s, &tmp);
      for (compno = 0; compno < s->ncomponents; compno++)
          if (!(properties[compno] & HAD_COC))
              memcpy(c + compno, &tmp, sizeof(tmp));
  static int get_coc(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c,
                     uint8_t *properties)
  {
 -    int compno;
 +    int compno, ret;
  
 -    if (s->buf_end - s->buf < 2)
 +    if (bytestream2_get_bytes_left(&s->g) < 2)
-         return AVERROR(EINVAL);
+         return AVERROR_INVALIDDATA;
  
 -    compno = bytestream_get_byte(&s->buf);
 +    compno = bytestream2_get_byteu(&s->g);
 +
 +    if (compno >= s->ncomponents) {
 +        av_log(s->avctx, AV_LOG_ERROR, "Invalid compno %d\n", compno);
 +        return AVERROR_INVALIDDATA;
 +    }
  
      c      += compno;
 -    c->csty = bytestream_get_byte(&s->buf);
 -    get_cox(s, c);
 +    c->csty = bytestream2_get_byteu(&s->g);
 +
 +    if ((ret = get_cox(s, c)) < 0)
 +        return ret;
  
      properties[compno] |= HAD_COC;
      return 0;
@@@ -376,24 -347,24 +376,24 @@@ static int get_qcx(Jpeg2000DecoderConte
  {
      int i, x;
  
 -    if (s->buf_end - s->buf < 1)
 +    if (bytestream2_get_bytes_left(&s->g) < 1)
-         return AVERROR(EINVAL);
+         return AVERROR_INVALIDDATA;
  
 -    x = bytestream_get_byte(&s->buf); // Sqcd
 +    x = bytestream2_get_byteu(&s->g); // Sqcd
  
      q->nguardbits = x >> 5;
      q->quantsty   = x & 0x1f;
  
      if (q->quantsty == JPEG2000_QSTY_NONE) {
          n -= 3;
 -        if (s->buf_end - s->buf < n)
 +        if (bytestream2_get_bytes_left(&s->g) < n || 32*3 < n)
-             return AVERROR(EINVAL);
+             return AVERROR_INVALIDDATA;
          for (i = 0; i < n; i++)
 -            q->expn[i] = bytestream_get_byte(&s->buf) >> 3;
 +            q->expn[i] = bytestream2_get_byteu(&s->g) >> 3;
      } else if (q->quantsty == JPEG2000_QSTY_SI) {
 -        if (s->buf_end - s->buf < 2)
 +        if (bytestream2_get_bytes_left(&s->g) < 2)
-             return AVERROR(EINVAL);
+             return AVERROR_INVALIDDATA;
 -        x          = bytestream_get_be16(&s->buf);
 +        x          = bytestream2_get_be16u(&s->g);
          q->expn[0] = x >> 11;
          q->mant[0] = x & 0x7ff;
          for (i = 1; i < JPEG2000_MAX_DECLEVELS * 3; i++) {
          }
      } else {
          n = (n - 3) >> 1;
 -        if (s->buf_end - s->buf < n)
 +        if (bytestream2_get_bytes_left(&s->g) < 2 * n || 32*3 < n)
-             return AVERROR(EINVAL);
+             return AVERROR_INVALIDDATA;
          for (i = 0; i < n; i++) {
 -            x          = bytestream_get_be16(&s->buf);
 +            x          = bytestream2_get_be16u(&s->g);
              q->expn[i] = x >> 11;
              q->mant[i] = x & 0x7ff;
          }
@@@ -436,15 -407,10 +436,15 @@@ static int get_qcc(Jpeg2000DecoderConte
  {
      int compno;
  
 -    if (s->buf_end - s->buf < 1)
 +    if (bytestream2_get_bytes_left(&s->g) < 1)
-         return AVERROR(EINVAL);
+         return AVERROR_INVALIDDATA;
  
 -    compno              = bytestream_get_byte(&s->buf);
 +    compno              = bytestream2_get_byteu(&s->g);
 +    if (compno >= s->ncomponents) {
 +        av_log(s->avctx, AV_LOG_ERROR, "Invalid compno\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
      properties[compno] |= HAD_QCC;
      return get_qcx(s, n - 1, q + compno);
  }
@@@ -457,41 -423,41 +457,41 @@@ static int get_sot(Jpeg2000DecoderConte
      uint32_t Psot;
      uint8_t TPsot;
  
 -    if (s->buf_end - s->buf < 4)
 +    if (bytestream2_get_bytes_left(&s->g) < 8)
-         return AVERROR(EINVAL);
+         return AVERROR_INVALIDDATA;
  
 -    Isot = bytestream_get_be16(&s->buf);        // Isot
 -    if (Isot) {
 -        avpriv_request_sample(s->avctx, "Support for more than one tile");
 -        return AVERROR_PATCHWELCOME;
 +    s->curtileno = Isot = bytestream2_get_be16u(&s->g);        // Isot
 +    if ((unsigned)s->curtileno >= s->numXtiles * s->numYtiles) {
 +        s->curtileno=0;
-         return AVERROR(EINVAL);
++        return AVERROR_INVALIDDATA;
      }
 -    Psot  = bytestream_get_be32(&s->buf);       // Psot
 -    TPsot = bytestream_get_byte(&s->buf);       // TPsot
 +    Psot  = bytestream2_get_be32u(&s->g);       // Psot
 +    TPsot = bytestream2_get_byteu(&s->g);       // TPsot
  
      /* Read TNSot but not used */
 -    bytestream_get_byte(&s->buf);               // TNsot
 +    bytestream2_get_byteu(&s->g);               // TNsot
  
 -    tp             = s->tile[s->curtileno].tile_part + TPsot;
 -    tp->tile_index = Isot;
 -    tp->tp_len     = Psot;
 -    tp->tp_idx     = TPsot;
 -
 -    /* Start of bit stream. Pointer to SOD marker
 -     * Check SOD marker is present. */
 -    if (JPEG2000_SOD == bytestream_get_be16(&s->buf))
 -        tp->tp_start_bstrm = s->buf;
 -    else {
 -        av_log(s->avctx, AV_LOG_ERROR, "SOD marker not found \n");
 +    if (Psot > bytestream2_get_bytes_left(&s->g) + n + 2) {
 +        av_log(s->avctx, AV_LOG_ERROR, "Psot %d too big\n", Psot);
          return AVERROR_INVALIDDATA;
      }
 +    if (TPsot >= FF_ARRAY_ELEMS(s->tile[s->curtileno].tile_part)) {
 +        av_log(s->avctx, AV_LOG_ERROR, "TPsot %d too big\n", TPsot);
 +        return AVERROR_PATCHWELCOME;
 +    }
  
 -    /* End address of bit stream =
 -     *     start address + (Psot - size of SOT HEADER(n)
 -     *     - size of SOT MARKER(2)  - size of SOD marker(2) */
 -    tp->tp_end_bstrm = s->buf + (tp->tp_len - n - 4);
 +    s->tile[s->curtileno].tp_idx = TPsot;
 +    tp             = s->tile[s->curtileno].tile_part + TPsot;
 +    tp->tile_index = Isot;
 +    tp->tp_end     = s->g.buffer + Psot - n - 2;
  
 -    // set buffer pointer to end of tile part header
 -    s->buf = tp->tp_end_bstrm;
 +    if (!TPsot) {
 +        Jpeg2000Tile *tile = s->tile + s->curtileno;
 +
 +        /* copy defaults */
 +        memcpy(tile->codsty, s->codsty, s->ncomponents * sizeof(Jpeg2000CodingStyle));
 +        memcpy(tile->qntsty, s->qntsty, s->ncomponents * sizeof(Jpeg2000QuantStyle));
 +    }
  
      return 0;
  }
@@@ -672,12 -643,16 +672,12 @@@ static int jpeg2000_decode_packet(Jpeg2
          nb_code_blocks = prec->nb_codeblocks_height * prec->nb_codeblocks_width;
          for (cblkno = 0; cblkno < nb_code_blocks; cblkno++) {
              Jpeg2000Cblk *cblk = prec->cblk + cblkno;
 -            if (s->buf_end - s->buf < cblk->lengthinc)
 +            if (   bytestream2_get_bytes_left(&s->g) < cblk->lengthinc
 +                || sizeof(cblk->data) < cblk->length + cblk->lengthinc + 2
 +            )
-                 return AVERROR(EINVAL);
+                 return AVERROR_INVALIDDATA;
 -            /* Code-block data can be empty. In that case initialize data
 -             * with 0xFFFF. */
 -            if (cblk->lengthinc > 0) {
 -                bytestream_get_buffer(&s->buf, cblk->data, cblk->lengthinc);
 -            } else {
 -                cblk->data[0] = 0xFF;
 -                cblk->data[1] = 0xFF;
 -            }
 +
 +            bytestream2_get_bufferu(&s->g, cblk->data + cblk->length, cblk->lengthinc);
              cblk->length   += cblk->lengthinc;
              cblk->lengthinc = 0;
          }
  
  static int jpeg2000_decode_packets(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile)
  {
-     int layno, reslevelno, compno, precno, ok_reslevel;
+     int layno, reslevelno, compno, precno, ok_reslevel, ret;
 -    uint8_t prog_order = tile->codsty[0].prog_order;
 -    uint16_t x;
 -    uint16_t y;
 +    int x, y;
  
      s->bit_index = 8;
 -    switch (prog_order) {
 +    switch (tile->codsty[0].prog_order) {
      case JPEG2000_PGOD_LRCP:
 +    case JPEG2000_PGOD_RLCP:
          for (layno = 0; layno < tile->codsty[0].nlayers; layno++) {
              ok_reslevel = 1;
              for (reslevelno = 0; ok_reslevel; reslevelno++) {
                      Jpeg2000QuantStyle *qntsty  = tile->qntsty + compno;
                      if (reslevelno < codsty->nreslevels) {
                          Jpeg2000ResLevel *rlevel = tile->comp[compno].reslevel +
 -                                                   reslevelno;
 +                                                reslevelno;
                          ok_reslevel = 1;
                          for (precno = 0; precno < rlevel->num_precincts_x * rlevel->num_precincts_y; precno++)
-                             if (jpeg2000_decode_packet(s,
-                                                        codsty, rlevel,
-                                                        precno, layno,
-                                                        qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
-                                                        qntsty->nguardbits))
-                                 return -1;
+                             if ((ret = jpeg2000_decode_packet(s,
+                                                               codsty, rlevel,
+                                                               precno, layno,
+                                                               qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
+                                                               qntsty->nguardbits)) < 0)
+                                 return ret;
                      }
                  }
              }
@@@ -1251,9 -1174,9 +1251,9 @@@ static int jpeg2000_read_main_headers(J
          if (marker == JPEG2000_EOC)
              break;
  
 -        if (s->buf_end - s->buf < 2)
 +        len = bytestream2_get_be16(&s->g);
 +        if (len < 2 || bytestream2_get_bytes_left(&s->g) < len - 2)
-             return AVERROR(EINVAL);
+             return AVERROR_INVALIDDATA;
 -        len = bytestream_get_be16(&s->buf);
          switch (marker) {
          case JPEG2000_SIZ:
              ret = get_siz(s);
@@@ -1362,30 -1274,23 +1362,30 @@@ static int jpeg2000_decode_frame(AVCode
      // reduction factor, i.e number of resolution levels to skip
      s->reduction_factor = s->lowres;
  
 -    if (s->buf_end - s->buf < 2)
 -        return AVERROR_INVALIDDATA;
 +    if (bytestream2_get_bytes_left(&s->g) < 2) {
-         ret = AVERROR(EINVAL);
++        ret = AVERROR_INVALIDDATA;
 +        goto end;
 +    }
  
      // check if the image is in jp2 format
 -    if ((AV_RB32(s->buf) == 12) &&
 -        (AV_RB32(s->buf + 4) == JP2_SIG_TYPE) &&
 -        (AV_RB32(s->buf + 8) == JP2_SIG_VALUE)) {
 +    if (bytestream2_get_bytes_left(&s->g) >= 12 &&
 +       (bytestream2_get_be32u(&s->g) == 12) &&
 +       (bytestream2_get_be32u(&s->g) == JP2_SIG_TYPE) &&
 +       (bytestream2_get_be32u(&s->g) == JP2_SIG_VALUE)) {
          if (!jp2_find_codestream(s)) {
              av_log(avctx, AV_LOG_ERROR,
-                    "couldn't find jpeg2k codestream atom\n");
-             ret = -1;
+                    "Could not find Jpeg2000 codestream atom.\n");
 -            return AVERROR_INVALIDDATA;
++            ret = AVERROR_INVALIDDATA;
 +            goto end;
          }
 +    } else {
 +        bytestream2_seek(&s->g, 0, SEEK_SET);
      }
  
 -    if (bytestream_get_be16(&s->buf) != JPEG2000_SOC) {
 +    if (bytestream2_get_be16u(&s->g) != JPEG2000_SOC) {
          av_log(avctx, AV_LOG_ERROR, "SOC marker not present\n");
-         ret = -1;
 -        return AVERROR_INVALIDDATA;
++        ret = AVERROR_INVALIDDATA;
 +        goto end;
      }
      if (ret = jpeg2000_read_main_headers(s))
          goto end;