avformat/mxfdec: store parition score instead of partition pointer in metadata

Partition struct may be reallocated, so let's store the score directly in order
to avoid use-after-free.

Also mxf->current_partition might be null when reading some local tags.

Signed-off-by: Marton Balint <cus@passwd.hu>
This commit is contained in:
Marton Balint 2021-08-11 20:30:55 +02:00
parent f852490f72
commit f0d4077c53
1 changed files with 17 additions and 14 deletions

View File

@ -108,7 +108,7 @@ typedef struct MXFPartition {
typedef struct MXFMetadataSet { typedef struct MXFMetadataSet {
UID uid; UID uid;
MXFPartition *partition; uint64_t partition_score;
enum MXFMetadataSetType type; enum MXFMetadataSetType type;
} MXFMetadataSet; } MXFMetadataSet;
@ -831,21 +831,25 @@ static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size
return 0; return 0;
} }
static int partition_score(MXFPartition *p) static uint64_t partition_score(MXFPartition *p)
{ {
uint64_t score;
if (!p)
return 0;
if (p->type == Footer) if (p->type == Footer)
return 5; score = 5;
if (p->complete) else if (p->complete)
return 4; score = 4;
if (p->closed) else if (p->closed)
return 3; score = 3;
return 1; else
score = 1;
return (score << 60) | ((uint64_t)p->this_partition >> 4);
} }
static int mxf_add_metadata_set(MXFContext *mxf, MXFMetadataSet **metadata_set) static int mxf_add_metadata_set(MXFContext *mxf, MXFMetadataSet **metadata_set)
{ {
MXFMetadataSet **tmp; MXFMetadataSet **tmp;
MXFPartition *new_p = (*metadata_set)->partition;
enum MXFMetadataSetType type = (*metadata_set)->type; enum MXFMetadataSetType type = (*metadata_set)->type;
// Index Table is special because it might be added manually without // Index Table is special because it might be added manually without
@ -854,10 +858,9 @@ static int mxf_add_metadata_set(MXFContext *mxf, MXFMetadataSet **metadata_set)
if (type != IndexTableSegment) { if (type != IndexTableSegment) {
for (int i = 0; i < mxf->metadata_sets_count; i++) { for (int i = 0; i < mxf->metadata_sets_count; i++) {
if (!memcmp((*metadata_set)->uid, mxf->metadata_sets[i]->uid, 16) && type == mxf->metadata_sets[i]->type) { if (!memcmp((*metadata_set)->uid, mxf->metadata_sets[i]->uid, 16) && type == mxf->metadata_sets[i]->type) {
MXFPartition *old_p = mxf->metadata_sets[i]->partition; uint64_t old_s = mxf->metadata_sets[i]->partition_score;
int old_s = partition_score(old_p); uint64_t new_s = (*metadata_set)->partition_score;
int new_s = partition_score(new_p); if (old_s > new_s) {
if (old_s > new_s || old_s == new_s && old_p->this_partition > new_p->this_partition) {
mxf_free_metadataset(metadata_set, 1); mxf_free_metadataset(metadata_set, 1);
return 0; return 0;
} }
@ -2894,7 +2897,7 @@ static const MXFMetadataReadTableEntry mxf_metadata_read_table[] = {
static int mxf_metadataset_init(MXFMetadataSet *ctx, enum MXFMetadataSetType type, MXFPartition *partition) static int mxf_metadataset_init(MXFMetadataSet *ctx, enum MXFMetadataSetType type, MXFPartition *partition)
{ {
ctx->type = type; ctx->type = type;
ctx->partition = partition; ctx->partition_score = partition_score(partition);
switch (type){ switch (type){
case MultipleDescriptor: case MultipleDescriptor:
case Descriptor: case Descriptor: