Merge commit '0f8512c4a87b89b4694053d8ffda48066ee1da62'
authorJames Almer <jamrial@gmail.com>
Tue, 17 Oct 2017 18:27:43 +0000 (15:27 -0300)
committerJames Almer <jamrial@gmail.com>
Tue, 17 Oct 2017 18:27:43 +0000 (15:27 -0300)
* commit '0f8512c4a87b89b4694053d8ffda48066ee1da62':
  mov: Validate spherical metadata version

Merged-by: James Almer <jamrial@gmail.com>
1  2 
libavformat/mov.c

@@@ -4721,149 -3267,20 +4721,155 @@@ static int mov_read_smdm(MOVContext *c
          return 0;
      }
      avio_skip(pb, 3); /* flags */
 -    avio_skip(pb, size - 12); /* metadata_source */
  
 -    size = avio_rb32(pb);
 -    if (size > atom.size)
 -        return AVERROR_INVALIDDATA;
 +    sc->mastering = av_mastering_display_metadata_alloc();
 +    if (!sc->mastering)
 +        return AVERROR(ENOMEM);
  
 -    tag = avio_rl32(pb);
 -    if (tag != MKTAG('p','r','o','j')) {
 -        av_log(c->fc, AV_LOG_ERROR, "Missing projection box\n");
 -        return 0;
 -    }
 +    for (i = 0; i < 3; i++)
 +        for (j = 0; j < 2; j++)
 +            sc->mastering->display_primaries[i][j] =
 +                av_make_q(lrint(((double)avio_rb16(pb) / (1 << 16)) * chroma_den), chroma_den);
 +    for (i = 0; i < 2; i++)
 +        sc->mastering->white_point[i] =
 +            av_make_q(lrint(((double)avio_rb16(pb) / (1 << 16)) * chroma_den), chroma_den);
 +    sc->mastering->max_luminance =
 +        av_make_q(lrint(((double)avio_rb32(pb) / (1 <<  8)) * luma_den), luma_den);
 +    sc->mastering->min_luminance =
 +        av_make_q(lrint(((double)avio_rb32(pb) / (1 << 14)) * luma_den), luma_den);
 +
 +    sc->mastering->has_primaries = 1;
 +    sc->mastering->has_luminance = 1;
  
 -    size = avio_rb32(pb);
 -    if (size > atom.size)
 +    return 0;
 +}
 +
 +static int mov_read_coll(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 +{
 +    MOVStreamContext *sc;
 +    int version;
 +
 +    if (c->fc->nb_streams < 1)
 +        return AVERROR_INVALIDDATA;
 +
 +    sc = c->fc->streams[c->fc->nb_streams - 1]->priv_data;
 +
 +    if (atom.size < 5) {
 +        av_log(c->fc, AV_LOG_ERROR, "Empty Content Light Level box\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    version = avio_r8(pb);
 +    if (version) {
 +        av_log(c->fc, AV_LOG_WARNING, "Unsupported Content Light Level box version %d\n", version);
 +        return 0;
 +    }
 +    avio_skip(pb, 3); /* flags */
 +
 +    sc->coll = av_content_light_metadata_alloc(&sc->coll_size);
 +    if (!sc->coll)
 +        return AVERROR(ENOMEM);
 +
 +    sc->coll->MaxCLL  = avio_rb16(pb);
 +    sc->coll->MaxFALL = avio_rb16(pb);
 +
 +    return 0;
 +}
 +
 +static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 +{
 +    AVStream *st;
 +    MOVStreamContext *sc;
 +    enum AVStereo3DType type;
 +    int mode;
 +
 +    if (c->fc->nb_streams < 1)
 +        return 0;
 +
 +    st = c->fc->streams[c->fc->nb_streams - 1];
 +    sc = st->priv_data;
 +
 +    if (atom.size < 5) {
 +        av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +    avio_skip(pb, 4); /* version + flags */
 +
 +    mode = avio_r8(pb);
 +    switch (mode) {
 +    case 0:
 +        type = AV_STEREO3D_2D;
 +        break;
 +    case 1:
 +        type = AV_STEREO3D_TOPBOTTOM;
 +        break;
 +    case 2:
 +        type = AV_STEREO3D_SIDEBYSIDE;
 +        break;
 +    default:
 +        av_log(c->fc, AV_LOG_WARNING, "Unknown st3d mode value %d\n", mode);
 +        return 0;
 +    }
 +
 +    sc->stereo3d = av_stereo3d_alloc();
 +    if (!sc->stereo3d)
 +        return AVERROR(ENOMEM);
 +
 +    sc->stereo3d->type = type;
 +    return 0;
 +}
 +
 +static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 +{
 +    AVStream *st;
 +    MOVStreamContext *sc;
-     int size, layout;
++    int size, version, layout;
 +    int32_t yaw, pitch, roll;
 +    uint32_t l = 0, t = 0, r = 0, b = 0;
 +    uint32_t tag, padding = 0;
 +    enum AVSphericalProjection projection;
 +
 +    if (c->fc->nb_streams < 1)
 +        return 0;
 +
 +    st = c->fc->streams[c->fc->nb_streams - 1];
 +    sc = st->priv_data;
 +
 +    if (atom.size < 8) {
 +        av_log(c->fc, AV_LOG_ERROR, "Empty spherical video box\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    size = avio_rb32(pb);
 +    if (size <= 12 || size > atom.size)
 +        return AVERROR_INVALIDDATA;
 +
 +    tag = avio_rl32(pb);
 +    if (tag != MKTAG('s','v','h','d')) {
 +        av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n");
 +        return 0;
 +    }
-     avio_skip(pb, 4); /*  version + flags */
++    version = avio_r8(pb);
++    if (version != 0) {
++        av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
++               version);
++        return 0;
++    }
++    avio_skip(pb, 3); /* flags */
 +    avio_skip(pb, size - 12); /* metadata_source */
 +
 +    size = avio_rb32(pb);
 +    if (size > atom.size)
 +        return AVERROR_INVALIDDATA;
 +
 +    tag = avio_rl32(pb);
 +    if (tag != MKTAG('p','r','o','j')) {
 +        av_log(c->fc, AV_LOG_ERROR, "Missing projection box\n");
 +        return 0;
 +    }
 +
 +    size = avio_rb32(pb);
 +    if (size > atom.size)
          return AVERROR_INVALIDDATA;
  
      tag = avio_rl32(pb);
          return AVERROR_INVALIDDATA;
  
      tag = avio_rl32(pb);
-     avio_skip(pb, 4); /*  version + flags */
+     version = avio_r8(pb);
+     if (version != 0) {
+         av_log(c->fc, AV_LOG_WARNING, "Unknown spherical version %d\n",
+                version);
+         return 0;
+     }
+     avio_skip(pb, 3); /* flags */
      switch (tag) {
      case MKTAG('c','b','m','p'):
 +        layout = avio_rb32(pb);
 +        if (layout) {
 +            av_log(c->fc, AV_LOG_WARNING,
 +                   "Unsupported cubemap layout %d\n", layout);
 +            return 0;
 +        }
          projection = AV_SPHERICAL_CUBEMAP;
 +        padding = avio_rb32(pb);
          break;
      case MKTAG('e','q','u','i'):
 -        projection = AV_SPHERICAL_EQUIRECTANGULAR;
 +        t = avio_rb32(pb);
 +        b = avio_rb32(pb);
 +        l = avio_rb32(pb);
 +        r = avio_rb32(pb);
 +
 +        if (b >= UINT_MAX - t || r >= UINT_MAX - l) {
 +            av_log(c->fc, AV_LOG_ERROR,
 +                   "Invalid bounding rectangle coordinates "
 +                   "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b);
 +            return AVERROR_INVALIDDATA;
 +        }
 +
 +        if (l || t || r || b)
 +            projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE;
 +        else
 +            projection = AV_SPHERICAL_EQUIRECTANGULAR;
          break;
      default:
          av_log(c->fc, AV_LOG_ERROR, "Unknown projection type\n");