History

avformat/mov: use an array of pointers for heif_item

Pointers to specific entries in the array are stored in other structs, so in the scenario where heif_item was reallocated when parsing an iloc box after and iinf one, the pointers may end up referencing freed memory. Fixes use-after-free with such samples.

James Almer committed 2 years ago

Commit 2e338151 parent 7f51cf72 files · +50 −29Browse files

Unified · Split

2 files
  1. libavformat/isom.h +1 −1
  2. libavformat/mov.c +49 −28
libavformat/isom.h+1−1
@@ -360,7 +360,7 @@ typedef struct MOVContext { · 359 unmodified lines
360360 uint32_t max_stts_delta;
361361 int primary_item_id;
362362 int cur_item_id;
363− HEIFItem *heif_item;
363+ HEIFItem **heif_item;
364364 int nb_heif_item;
365365 HEIFGrid *heif_grid;
366366 int nb_heif_grid;
libavformat/mov.c+49−28
@@ -197,10 +197,10 @@ static HEIFItem *heif_cur_item(MOVContext *c) · 196 unmodified lines
197197 HEIFItem *item = NULL;
198198
199199 for (int i = 0; i < c->nb_heif_item; i++) {
200− if (c->heif_item[i].item_id != c->cur_item_id)
200+ if (c->heif_item[i]->item_id != c->cur_item_id)
201201 continue;
202202
203− item = &c->heif_item[i];
203+ item = c->heif_item[i];
204204 break;
205205 }
206206
@@ -8657,7 +8657,7 @@ static int mov_read_idat(MOVContext *c, AVIOContext *pb, MOVAtom atom) · 8450 unmodified lines
86578657
86588658 static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
86598659 {
8660− HEIFItem *heif_item;
8660+ HEIFItem **heif_item;
86618661 int version, offset_size, length_size, base_offset_size, index_size;
86628662 int item_count, extent_count;
86638663 int64_t base_offset, extent_offset, extent_length;
@@ -8688,12 +8688,12 @@ static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom) · 24 unmodified lines
86888688 return AVERROR(ENOMEM);
86898689 c->heif_item = heif_item;
86908690 if (item_count > c->nb_heif_item)
8691− memset(c->heif_item + c->nb_heif_item, 0,
8691+ memset(&c->heif_item[c->nb_heif_item], 0,
86928692 sizeof(*c->heif_item) * (item_count - c->nb_heif_item));
8693− c->nb_heif_item = FFMAX(c->nb_heif_item, item_count);
86948693
86958694 av_log(c->fc, AV_LOG_TRACE, "iloc: item_count %d\n", item_count);
86968695 for (int i = 0; i < item_count; i++) {
8696+ HEIFItem *item = c->heif_item[i];
86978697 int item_id = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
86988698 int offset_type = (version > 0) ? avio_rb16(pb) & 0xf : 0;
86998699
@@ -8703,7 +8703,6 @@ static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom) · 3 unmodified lines
87038703 avpriv_report_missing_feature(c->fc, "iloc offset type %d", offset_type);
87048704 return AVERROR_PATCHWELCOME;
87058705 }
8706− c->heif_item[i].item_id = item_id;
87078706
87088707 avio_rb16(pb); // data_reference_index.
87098708 if (rb_size(pb, &base_offset, base_offset_size) < 0)
@@ -8714,19 +8713,28 @@ static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom) · 4 unmodified lines
87148713 avpriv_report_missing_feature(c->fc, "iloc: extent_count > 1");
87158714 return AVERROR_PATCHWELCOME;
87168715 }
8717− for (int j = 0; j < extent_count; j++) {
8716+
87188717 if (rb_size(pb, &extent_offset, offset_size) < 0 ||
87198718 rb_size(pb, &extent_length, length_size) < 0 ||
87208719 base_offset > INT64_MAX - extent_offset)
87218720 return AVERROR_INVALIDDATA;
8721+
8722+ if (!item)
8723+ item = c->heif_item[i] = av_mallocz(sizeof(*item));
8724+ if (!item)
8725+ return AVERROR(ENOMEM);
8726+
8727+ item->item_id = item_id;
8728+
87228729 if (offset_type == 1)
8723− c->heif_item[i].is_idat_relative = 1;
8724− c->heif_item[i].extent_length = extent_length;
8725− c->heif_item[i].extent_offset = base_offset + extent_offset;
8730+ item->is_idat_relative = 1;
8731+ item->extent_length = extent_length;
8732+ item->extent_offset = base_offset + extent_offset;
87268733 av_log(c->fc, AV_LOG_TRACE, "iloc: item_idx %d, offset_type %d, "
87278734 "extent_offset %"PRId64", extent_length %"PRId64"\n",
8728− i, offset_type, c->heif_item[i].extent_offset, c->heif_item[i].extent_length);
8729− }
8735+ i, offset_type, item->extent_offset, item->extent_length);
8736+
8737+ c->nb_heif_item = FFMAX(c->nb_heif_item, i + 1);
87308738 }
87318739
87328740 c->found_iloc = 1;
@@ -8735,6 +8743,7 @@ static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom) · 2 unmodified lines
87358743
87368744 static int mov_read_infe(MOVContext *c, AVIOContext *pb, MOVAtom atom, int idx)
87378745 {
8746+ HEIFItem *item;
87388747 AVBPrint item_name;
87398748 int64_t size = atom.size;
87408749 uint32_t item_type;
@@ -8774,15 +8783,21 @@ static int mov_read_infe(MOVContext *c, AVIOContext *pb, MOVAtom atom, int idx) · 33 unmodified lines
87748783 if (size > 0)
87758784 avio_skip(pb, size);
87768785
8786+ item = c->heif_item[idx];
8787+ if (!item)
8788+ item = c->heif_item[idx] = av_mallocz(sizeof(*item));
8789+ if (!item)
8790+ return AVERROR(ENOMEM);
8791+
87778792 if (ret)
8778− av_bprint_finalize(&item_name, &c->heif_item[idx].name);
8779− c->heif_item[idx].item_id = item_id;
8780− c->heif_item[idx].type = item_type;
8793+ av_bprint_finalize(&item_name, &c->heif_item[idx]->name);
8794+ c->heif_item[idx]->item_id = item_id;
8795+ c->heif_item[idx]->type = item_type;
87818796
87828797 switch (item_type) {
87838798 case MKTAG('a','v','0','1'):
87848799 case MKTAG('h','v','c','1'):
8785− ret = heif_add_stream(c, &c->heif_item[idx]);
8800+ ret = heif_add_stream(c, c->heif_item[idx]);
87868801 if (ret < 0)
87878802 return ret;
87888803 break;
@@ -8793,7 +8808,7 @@ static int mov_read_infe(MOVContext *c, AVIOContext *pb, MOVAtom atom, int idx) · 4 unmodified lines
87938808
87948809 static int mov_read_iinf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
87958810 {
8796− HEIFItem *heif_item;
8811+ HEIFItem **heif_item;
87978812 int entry_count;
87988813 int version, got_stream = 0, ret, i;
87998814
@@ -8811,15 +8826,16 @@ static int mov_read_iinf(MOVContext *c, AVIOContext *pb, MOVAtom atom) · 11 unmodified lines
88118826 return AVERROR(ENOMEM);
88128827 c->heif_item = heif_item;
88138828 if (entry_count > c->nb_heif_item)
8814− memset(c->heif_item + c->nb_heif_item, 0,
8829+ memset(&c->heif_item[c->nb_heif_item], 0,
88158830 sizeof(*c->heif_item) * (entry_count - c->nb_heif_item));
8816− c->nb_heif_item = FFMAX(c->nb_heif_item, entry_count);
88178831
88188832 for (i = 0; i < entry_count; i++) {
88198833 MOVAtom infe;
88208834
8821− if (avio_feof(pb))
8822− return AVERROR_INVALIDDATA;
8835+ if (avio_feof(pb)) {
8836+ ret = AVERROR_INVALIDDATA;
8837+ goto fail;
8838+ }
88238839 infe.size = avio_rb32(pb) - 8;
88248840 infe.type = avio_rl32(pb);
88258841 ret = mov_read_infe(c, pb, infe, i);
@@ -8827,13 +8843,17 @@ static int mov_read_iinf(MOVContext *c, AVIOContext *pb, MOVAtom atom) · 1 unmodified line
88278843 goto fail;
88288844 if (!ret)
88298845 got_stream = 1;
8846+ c->nb_heif_item = FFMAX(c->nb_heif_item, i + 1);
88308847 }
88318848
88328849 c->found_iinf = got_stream;
88338850 return 0;
88348851 fail:
88358852 for (; i >= 0; i--) {
8836− HEIFItem *item = &c->heif_item[i];
8853+ HEIFItem *item = c->heif_item[i];
8854+
8855+ if (!item)
8856+ continue;
88378857
88388858 av_freep(&item->name);
88398859 if (!item->st)
@@ -8861,9 +8881,9 @@ static int mov_read_iref_dimg(MOVContext *c, AVIOContext *pb, int version) · 21 unmodified lines
88618881 }
88628882 }
88638883 for (int i = 0; i < c->nb_heif_item; i++) {
8864− if (c->heif_item[i].item_id != from_item_id)
8884+ if (c->heif_item[i]->item_id != from_item_id)
88658885 continue;
8866− item = &c->heif_item[i];
8886+ item = c->heif_item[i];
88678887
88688888 switch (item->type) {
88698889 case MKTAG('g','r','i','d'):
@@ -9779,8 +9799,9 @@ static int mov_read_close(AVFormatContext *s) · 909 unmodified lines
97799799 av_freep(&mov->aes_decrypt);
97809800 av_freep(&mov->chapter_tracks);
97819801 for (i = 0; i < mov->nb_heif_item; i++) {
9782− av_freep(&mov->heif_item[i].name);
9783− av_freep(&mov->heif_item[i].icc_profile);
9802+ av_freep(&mov->heif_item[i]->name);
9803+ av_freep(&mov->heif_item[i]->icc_profile);
9804+ av_freep(&mov->heif_item[i]);
97849805 }
97859806 av_freep(&mov->heif_item);
97869807 for (i = 0; i < mov->nb_heif_grid; i++) {
@@ -10164,7 +10185,7 @@ static int mov_parse_tiles(AVFormatContext *s) · 377 unmodified lines
1016410185 int k;
1016510186
1016610187 for (k = 0; k < mov->nb_heif_item; k++) {
10167− HEIFItem *item = &mov->heif_item[k];
10188+ HEIFItem *item = mov->heif_item[k];
1016810189 AVStream *st = item->st;
1016910190
1017010191 if (item->item_id != tile_id)
@@ -10233,7 +10254,7 @@ static int mov_parse_heif_items(AVFormatContext *s) · 62 unmodified lines
1023310254 int err;
1023410255
1023510256 for (int i = 0; i < mov->nb_heif_item; i++) {
10236− HEIFItem *item = &mov->heif_item[i];
10257+ HEIFItem *item = mov->heif_item[i];
1023710258 MOVStreamContext *sc;
1023810259 AVStream *st;
1023910260 int64_t offset = 0;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t