Merge commit '999ccd2d0a43640921088578f138c874f6cc0f8a'
authorMichael Niedermayer <michaelni@gmx.at>
Sat, 8 Jun 2013 09:41:58 +0000 (11:41 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Sat, 8 Jun 2013 09:41:58 +0000 (11:41 +0200)
* commit '999ccd2d0a43640921088578f138c874f6cc0f8a':
  tiff: cleanup the error paths

Conflicts:
libavcodec/tiff.c

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

@@@ -931,142 -545,14 +929,146 @@@ static int tiff_decode_tag(TiffContext 
          if (s->compr == TIFF_G4)
              s->fax_opts = value;
          break;
 +#define ADD_METADATA(count, name, sep)\
 +    if ((ret = add_metadata(count, type, name, sep, s, frame)) < 0) {\
 +        av_log(s->avctx, AV_LOG_ERROR, "Error allocating temporary buffer\n");\
 +        return ret;\
 +    }
 +    case TIFF_MODEL_PIXEL_SCALE:
 +        ADD_METADATA(count, "ModelPixelScaleTag", NULL);
 +        break;
 +    case TIFF_MODEL_TRANSFORMATION:
 +        ADD_METADATA(count, "ModelTransformationTag", NULL);
 +        break;
 +    case TIFF_MODEL_TIEPOINT:
 +        ADD_METADATA(count, "ModelTiepointTag", NULL);
 +        break;
 +    case TIFF_GEO_KEY_DIRECTORY:
 +        ADD_METADATA(1, "GeoTIFF_Version", NULL);
 +        ADD_METADATA(2, "GeoTIFF_Key_Revision", ".");
 +        s->geotag_count   = tget_short(&s->gb, s->le);
 +        if (s->geotag_count > count / 4 - 1) {
 +            s->geotag_count = count / 4 - 1;
 +            av_log(s->avctx, AV_LOG_WARNING, "GeoTIFF key directory buffer shorter than specified\n");
 +        }
 +        if (bytestream2_get_bytes_left(&s->gb) < s->geotag_count * sizeof(int16_t) * 4) {
 +            s->geotag_count = 0;
 +            return -1;
 +        }
 +        s->geotags = av_mallocz(sizeof(TiffGeoTag) * s->geotag_count);
 +        if (!s->geotags) {
 +            av_log(s->avctx, AV_LOG_ERROR, "Error allocating temporary buffer\n");
 +            s->geotag_count = 0;
 +            return AVERROR(ENOMEM);
 +        }
 +        for (i = 0; i < s->geotag_count; i++) {
 +            s->geotags[i].key    = tget_short(&s->gb, s->le);
 +            s->geotags[i].type   = tget_short(&s->gb, s->le);
 +            s->geotags[i].count  = tget_short(&s->gb, s->le);
 +
 +            if (!s->geotags[i].type)
 +                s->geotags[i].val  = get_geokey_val(s->geotags[i].key, tget_short(&s->gb, s->le));
 +            else
 +                s->geotags[i].offset = tget_short(&s->gb, s->le);
 +        }
 +        break;
 +    case TIFF_GEO_DOUBLE_PARAMS:
 +        if (count >= INT_MAX / sizeof(int64_t))
 +            return AVERROR_INVALIDDATA;
 +        if (bytestream2_get_bytes_left(&s->gb) < count * sizeof(int64_t))
 +            return AVERROR_INVALIDDATA;
 +        dp = av_malloc(count * sizeof(double));
 +        if (!dp) {
 +            av_log(s->avctx, AV_LOG_ERROR, "Error allocating temporary buffer\n");
 +            return AVERROR(ENOMEM);
 +        }
 +        for (i = 0; i < count; i++)
 +            dp[i] = tget_double(&s->gb, s->le);
 +        for (i = 0; i < s->geotag_count; i++) {
 +            if (s->geotags[i].type == TIFF_GEO_DOUBLE_PARAMS) {
 +                if (s->geotags[i].count == 0
 +                    || s->geotags[i].offset + s->geotags[i].count > count) {
 +                    av_log(s->avctx, AV_LOG_WARNING, "Invalid GeoTIFF key %d\n", s->geotags[i].key);
 +                } else {
 +                    char *ap = doubles2str(&dp[s->geotags[i].offset], s->geotags[i].count, ", ");
 +                    if (!ap) {
 +                        av_log(s->avctx, AV_LOG_ERROR, "Error allocating temporary buffer\n");
 +                        av_freep(&dp);
 +                        return AVERROR(ENOMEM);
 +                    }
 +                    s->geotags[i].val = ap;
 +                }
 +            }
 +        }
 +        av_freep(&dp);
 +        break;
 +    case TIFF_GEO_ASCII_PARAMS:
 +        pos = bytestream2_tell(&s->gb);
 +        for (i = 0; i < s->geotag_count; i++) {
 +            if (s->geotags[i].type == TIFF_GEO_ASCII_PARAMS) {
 +                if (s->geotags[i].count == 0
 +                    || s->geotags[i].offset +  s->geotags[i].count > count) {
 +                    av_log(s->avctx, AV_LOG_WARNING, "Invalid GeoTIFF key %d\n", s->geotags[i].key);
 +                } else {
 +                    char *ap;
 +
 +                    bytestream2_seek(&s->gb, pos + s->geotags[i].offset, SEEK_SET);
 +                    if (bytestream2_get_bytes_left(&s->gb) < s->geotags[i].count)
 +                        return AVERROR_INVALIDDATA;
 +                    ap = av_malloc(s->geotags[i].count);
 +                    if (!ap) {
 +                        av_log(s->avctx, AV_LOG_ERROR, "Error allocating temporary buffer\n");
 +                        return AVERROR(ENOMEM);
 +                    }
 +                    bytestream2_get_bufferu(&s->gb, ap, s->geotags[i].count);
 +                    ap[s->geotags[i].count - 1] = '\0'; //replace the "|" delimiter with a 0 byte
 +                    s->geotags[i].val = ap;
 +                }
 +            }
 +        }
 +        break;
 +    case TIFF_ARTIST:
 +        ADD_METADATA(count, "artist", NULL);
 +        break;
 +    case TIFF_COPYRIGHT:
 +        ADD_METADATA(count, "copyright", NULL);
 +        break;
 +    case TIFF_DATE:
 +        ADD_METADATA(count, "date", NULL);
 +        break;
 +    case TIFF_DOCUMENT_NAME:
 +        ADD_METADATA(count, "document_name", NULL);
 +        break;
 +    case TIFF_HOST_COMPUTER:
 +        ADD_METADATA(count, "computer", NULL);
 +        break;
 +    case TIFF_IMAGE_DESCRIPTION:
 +        ADD_METADATA(count, "description", NULL);
 +        break;
 +    case TIFF_MAKE:
 +        ADD_METADATA(count, "make", NULL);
 +        break;
 +    case TIFF_MODEL:
 +        ADD_METADATA(count, "model", NULL);
 +        break;
 +    case TIFF_PAGE_NAME:
 +        ADD_METADATA(count, "page_name", NULL);
 +        break;
 +    case TIFF_PAGE_NUMBER:
 +        ADD_METADATA(count, "page_number", " / ");
 +        break;
 +    case TIFF_SOFTWARE_NAME:
 +        ADD_METADATA(count, "software", NULL);
 +        break;
      default:
-         av_log(s->avctx, AV_LOG_DEBUG, "Unknown or unsupported tag %d/0X%0X\n",
-                tag, tag);
+         if (s->avctx->err_recognition & AV_EF_EXPLODE) {
+             av_log(s->avctx, AV_LOG_ERROR,
+                    "Unknown or unsupported tag %d/0X%0X\n",
+                    tag, tag);
+             return AVERROR_INVALIDDATA;
+         }
      }
 +    bytestream2_seek(&s->gb, start, SEEK_SET);
      return 0;
  }
  
@@@ -1194,9 -642,12 +1196,12 @@@ static int decode_frame(AVCodecContext 
              av_log(avctx, AV_LOG_ERROR, "Invalid strip size/offset\n");
              return AVERROR_INVALIDDATA;
          }
-         if (tiff_unpack_strip(s, dst, stride, avpkt->data + soff, ssize,
-                               FFMIN(s->rps, s->height - i)) < 0)
 -        if ((ret = tiff_unpack_strip(s, dst, stride, orig_buf + soff, ssize,
++        if ((ret = tiff_unpack_strip(s, dst, stride, avpkt->data + soff, ssize,
+                                      FFMIN(s->rps, s->height - i))) < 0) {
+             if (avctx->err_recognition & AV_EF_EXPLODE)
+                 return ret;
              break;
+         }
          dst += s->rps * stride;
      }
      if (s->predictor == 2) {