VYPR
Medium severity5.5NVD Advisory· Published Jun 1, 2026· Updated Jun 1, 2026

CVE-2025-60481

CVE-2025-60481

Description

A NULL pointer dereference in GPAC's MP4Box allows attackers to cause a Denial of Service via a crafted AC4 audio file.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

A NULL pointer dereference in GPAC's MP4Box allows attackers to cause a Denial of Service via a crafted AC4 audio file.

Vulnerability

A NULL pointer dereference vulnerability exists in the gf_odf_ac4_cfg_dsi_v1 function within odf/descriptors.c of GPAC Project/MP4Box. The issue arises due to insufficient validation of pointers when processing AC4 audio stream configurations, specifically when handling malformed or crafted DSI (Decoder Specific Info) substructures. This vulnerability affects versions prior to 26.02 [1][2].

Exploitation

An attacker can trigger this vulnerability by providing a specially crafted AC4 file to the MP4Box utility. No special privileges or network access are required beyond the ability to supply a malicious file to the application, which then triggers the vulnerable code path during the parsing or information extraction process [2].

Impact

Successful exploitation of this vulnerability results in a segmentation fault, leading to a Denial of Service (DoS) of the MP4Box application. This crash occurs during the processing of the media file, potentially disrupting services or workflows that rely on the utility for media analysis or conversion [2].

Mitigation

This issue is addressed in GPAC/MP4Box versions 26.02 and later. Users are advised to update their installations to the latest version to incorporate the necessary pointer validation checks [1].

AI Insight generated on Jun 1, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

1

Patches

1
e02d1fd24cdc

fix several ac4 fuzzing issues:

https://github.com/gpac/gpacAurelien DavidJul 15, 2025via nvd-ref
2 files changed · +117 34
  • src/media_tools/av_parsers.c+50 3 modified
    @@ -15277,6 +15277,9 @@ static Bool gf_ac4_substream_group_info(GF_BitStream *bs,
     			gf_ac4_oamd_substream_info(bs, ginfo->b_substreams_present);
     		}
     
    +		if (ginfo->substreams) {
    +			gf_list_del(ginfo->substreams);
    +		}
     		ginfo->substreams = gf_list_new();
     
     		for (i = 0; i < ginfo->n_lf_substreams; i++) {
    @@ -15508,7 +15511,7 @@ static Bool gf_ac4_presentation_v1_info(GF_BitStream *bs,
     		if (pinfo->n_add_emdf_substreams == 0) {
     			pinfo->n_add_emdf_substreams = gf_ac4_variable_bits(bs, 2) + 4;
     		}
    -		for (i = 0; i < pinfo->n_add_emdf_substreams; i++) {
    +		for (i = 0; i < pinfo->n_add_emdf_substreams && i < MIN(GF_ARRAY_LENGTH(pinfo->substream_emdf_version), GF_ARRAY_LENGTH(pinfo->substream_key_id)); i++) {
     			gf_ac4_emdf_info(bs, &emdf_version, &key_id);
     
     			// ETSI TS 103 190-2 V1.2.1 (2018-02) E.8.16 & E.8.17
    @@ -15532,7 +15535,7 @@ static GF_AC4PresentationV1* gf_ac4_get_presentation_by_substreamgroup(GF_AC4Str
     		p = gf_list_get(stream->presentations, i);
     		for (j = 0; j < p->n_substream_groups; j++) {
     			x = gf_list_get(p->substream_group_indexs, j);
    -			if(idx == *x) {
    +			if(x && idx == *x) {
     				return p;
     			}
     		}
    @@ -15638,8 +15641,10 @@ static s32 gf_ac4_presentation_ch_mode(GF_AC4PresentationV1 *p)
     	// ETSI TS 103 190-2 V1.2.1 (2018-02) 6.3.3.1.27 Table 91
         for (i = 0; i < p->n_substream_groups; i++){
     		group = gf_list_get(p->substream_groups, i);
    +		if (!group) continue;
             for (j = 0; j < group->n_lf_substreams; j++){
     			substream = gf_list_get(group->substreams, j);
    +			if (!substream) continue;
                 if (group->b_channel_coded){
                     pres_ch_mode = gf_ac4_cfg_super_set(pres_ch_mode, substream->ch_mode);
                 }else {
    @@ -15663,6 +15668,7 @@ static u32 gf_ac4_presentation_channel_mask_v1(GF_AC4PresentationV1 *p)
     	// ETSI TS 103 190-2 V1.2.1 (2018-02) E.10.14
         for (i = 0; i < p->n_substream_groups; i++){
     		group = gf_list_get(p->substream_groups, i);
    +		if (!group) continue;
             for (j = 0; j < group->n_lf_substreams; j++){
     			substream = gf_list_get(group->substreams, j);
                 if (group->b_channel_coded){
    @@ -15766,8 +15772,10 @@ static s32 gf_ac4_get_b_presentation_core_differs(GF_AC4PresentationV1 *p, s32 p
     	// ETSI TS 103 190-2 V1.2.1 (2018-02) Table 93
         for (i = 0; i < p->n_substream_groups; i ++){
     		group = gf_list_get(p->substream_groups, i);
    +		if (!group) continue;
             for (j = 0; j < group->n_lf_substreams; j++){
     			substream = gf_list_get(group->substreams, j);
    +			if (!substream) continue;
                 if (group->b_channel_coded){
     				ch_mode_core = gf_ac4_get_ch_mode_core(group->b_channel_coded,
     													   substream->b_ajoc,
    @@ -15957,10 +15965,13 @@ static Bool gf_ac4_raw_frame(GF_BitStream *bs, GF_AC4Config* hdr, Bool full_pars
     		for (i = 0; i < n_presentations; i++) {
     			GF_AC4PresentationV1 *p = (GF_AC4PresentationV1*)gf_list_get(hdr_p_list, i);
     
    +
     			// calloc the space for GF_LIST<GF_AC4SubStreamGroupV1>
     			p->substream_groups = gf_list_new();
    +
     			for (j = 0; j < p->n_substream_groups; j++) {
     				idx = gf_list_get(p->substream_group_indexs, j);
    +				if (!idx) continue;
     				group = (GF_AC4SubStreamGroupV1*)gf_list_get(temp_groups, *idx);
     				if (group) {
     					gf_list_add(p->substream_groups, group);
    @@ -15970,6 +15981,13 @@ static Bool gf_ac4_raw_frame(GF_BitStream *bs, GF_AC4Config* hdr, Bool full_pars
     					break;
     				}
     			}
    +			// remove added groups from temp to avoid double frees
    +			for (j=0; j < gf_list_count(p->substream_groups); j++) {
    +				group = (GF_AC4SubStreamGroupV1*)gf_list_get(p->substream_groups, j);
    +				if (group) {
    +					gf_list_del_item(temp_groups, group);
    +				}
    +			}
     
     			// ETSI TS 103 190-2 V1.2.1 (2018-02) E.10
     			// other elements in GF_AC4PresentationV1 for Sample Description Box
    @@ -16007,7 +16025,17 @@ static Bool gf_ac4_raw_frame(GF_BitStream *bs, GF_AC4Config* hdr, Bool full_pars
     			gf_list_del(p->substream_group_indexs);
     		}
     
    -		// free auxiliary information temp_groups, don't delete the memory of GF_AC4SubStreamGroupV1
    +		// free auxiliary information temp_groups that have not been copied elsewhere
    +		while ((group = (GF_AC4SubStreamGroupV1*)gf_list_pop_back(temp_groups))) {
    +			if (group->substreams) {
    +				for (int s = 0; s < gf_list_count(group->substreams); s++) {
    +					GF_AC4SubStream* subs = gf_list_get(group->substreams, s);
    +					gf_free(subs);
    +				}
    +				gf_list_del(group->substreams);
    +			}
    +			gf_free(group);
    +		}
     		gf_list_del(temp_groups);
     
     		// If the substreams are channel-based, calculate channel_count with speaker_group_index_mask of the first/default presentation. If the substreams are non-channel-based, set channel_count to max(channel_count)
    @@ -16132,11 +16160,30 @@ Bool gf_ac4_parser_bs(GF_BitStream *bs, GF_AC4Config *hdr, Bool full_parse)
     
     	/* fill some AC4 DSI info */
     	stream->ac4_dsi_version = 1;
    +	if (stream->fs_index >= GF_ARRAY_LENGTH(AC4_SAMPLING_FREQ_TABLE)) {
    +		GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[AC4] stream fs_index %d >= length AC4_SAMPLING_FREQ_TABLE\n", stream->fs_index));
    +		gf_bs_seek(bs, pos);
    +		return GF_FALSE;
    +	}
     	hdr->sample_rate = AC4_SAMPLING_FREQ_TABLE[stream->fs_index];
     	if (stream->fs_index == 0) {
    +
    +		if (stream->frame_rate_index >= MIN(GF_ARRAY_LENGTH(AC4_SAMPLE_DELTA_TABLE_441), GF_ARRAY_LENGTH(AC4_MEDIA_TIMESCALE_441))) {
    +			GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[AC4] stream frame_rate_index %d >= length AC4_SAMPLE_DELTA_TABLE_441 or AC4_MEDIA_TIMESCALE_441\n", stream->frame_rate_index));
    +			gf_bs_seek(bs, pos);
    +			return GF_FALSE;
    +		}
     		hdr->sample_duration = AC4_SAMPLE_DELTA_TABLE_441[stream->frame_rate_index];
     		hdr->media_time_scale = AC4_MEDIA_TIMESCALE_441[stream->frame_rate_index];
    +
     	} else {
    +
    +		if (stream->frame_rate_index >= MIN(GF_ARRAY_LENGTH(AC4_SAMPLE_DELTA_TABLE_48), GF_ARRAY_LENGTH(AC4_MEDIA_TIMESCALE_48))) {
    +			GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[AC4] stream frame_rate_index %d >= length AC4_SAMPLE_DELTA_TABLE_48 or AC4_MEDIA_TIMESCALE_48\n", stream->frame_rate_index));
    +			gf_bs_seek(bs, pos);
    +			return GF_FALSE;
    +		}
    +
     		hdr->sample_duration = AC4_SAMPLE_DELTA_TABLE_48[stream->frame_rate_index];
     		hdr->media_time_scale = AC4_MEDIA_TIMESCALE_48[stream->frame_rate_index];
     	}
    
  • src/odf/descriptors.c+67 31 modified
    @@ -1895,10 +1895,19 @@ GF_Err gf_odf_ac4_cfg_alternative_info(GF_AC4AlternativeInfo *info, GF_BitStream
     	u32 i;
     
     	GF_AC4_SSS(bs, info->name_len, 16, size, desc_mode);
    +
    +	if (info->name_len >= GF_ARRAY_LENGTH(info->presentation_name))
    +		return GF_ISOM_INVALID_MEDIA;
    +
     	for (i = 0; i < info->name_len; i++) {
     		GF_AC4_SSS(bs, info->presentation_name[i], 8, size, desc_mode);
     	}
    +
     	GF_AC4_SSS(bs, info->n_targets, 5, size, desc_mode);
    +
    +	if (info->n_targets >= MIN(GF_ARRAY_LENGTH(info->target_md_compat), GF_ARRAY_LENGTH(info->target_device_category)))
    +		return GF_ISOM_INVALID_MEDIA;
    +
     	for (i = 0; i < info->n_targets; i++) {
     		GF_AC4_SSS(bs, info->target_md_compat[i], 3, size, desc_mode);
     		GF_AC4_SSS(bs, info->target_device_category[i], 8, size, desc_mode);
    @@ -1957,6 +1966,9 @@ GF_Err gf_odf_ac4_cfg_substream_group_dsi(GF_AC4SubStreamGroupV1 *g, GF_BitStrea
     	u32 i;
     	GF_AC4SubStream *s;
     
    +	if (!g)
    +		return GF_BAD_PARAM;
    +
     	GF_AC4_SSS(bs, g->b_substreams_present, 1, size, desc_mode);
         GF_AC4_SSS(bs, g->b_hsf_ext, 1, size, desc_mode);
         GF_AC4_SSS(bs, g->b_channel_coded, 1, size, desc_mode);
    @@ -2045,7 +2057,8 @@ GF_Err gf_odf_ac4_cfg_presentation_v1_dsi(GF_AC4PresentationV1 *p, GF_BitStream
     			} else { // write or get_size
     				g = (GF_AC4SubStreamGroupV1*)gf_list_get(p->substream_groups, 0);
     			}
    -			gf_odf_ac4_cfg_substream_group_dsi(g, bs, size, desc_mode);
    +			if (g)
    +				gf_odf_ac4_cfg_substream_group_dsi(g, bs, size, desc_mode);
     		}
     		else {
     			GF_AC4_SSS(bs, p->b_multi_pid, 1, size, desc_mode);
    @@ -2088,7 +2101,7 @@ GF_Err gf_odf_ac4_cfg_presentation_v1_dsi(GF_AC4PresentationV1 *p, GF_BitStream
     	}
     	if (p->b_add_emdf_substreams) {
     		GF_AC4_SSS(bs, p->n_add_emdf_substreams, 7, size, desc_mode);
    -		for (i = 0; i < p->n_add_emdf_substreams; i++) {
    +		for (i = 0; i < p->n_add_emdf_substreams && i < GF_ARRAY_LENGTH(p->substream_emdf_version) && i < GF_ARRAY_LENGTH(p->substream_key_id); i++) {
     			GF_AC4_SSS(bs, p->substream_emdf_version[i], 5, size, desc_mode);
     			GF_AC4_SSS(bs, p->substream_key_id[i], 10, size, desc_mode);
     		}
    @@ -2136,6 +2149,9 @@ GF_Err gf_odf_ac4_cfg_dsi_v1(GF_AC4StreamInfo *dsi, GF_BitStream *bs, u64 *size,
     	u8 *t_data = NULL;
     	GF_BitStream *t_bs;
     
    +	if (!dsi)
    +		return GF_BAD_PARAM;
    +
     	GF_AC4_SSS(bs, dsi->ac4_dsi_version, 3, size, desc_mode);
     	GF_AC4_SSS(bs, dsi->bitstream_version, 7, size, desc_mode);
     	GF_AC4_SSS(bs, dsi->fs_index, 1, size, desc_mode);
    @@ -2145,6 +2161,7 @@ GF_Err gf_odf_ac4_cfg_dsi_v1(GF_AC4StreamInfo *dsi, GF_BitStream *bs, u64 *size,
     		// check whether legacy presentations are added in the presentations
     		for (i = 0; i < dsi->n_presentations; i++) {
     			p = gf_list_get(dsi->presentations, i);
    +			if (!p) continue;
     			if (p->presentation_version == 1) {
     				legacy_pres_num += 1;
     			} else if (p->presentation_version == 2) {
    @@ -2219,12 +2236,13 @@ GF_Err gf_odf_ac4_cfg_dsi_v1(GF_AC4StreamInfo *dsi, GF_BitStream *bs, u64 *size,
     			presentation_bytes = (u32) (gf_bs_get_position(bs) - pos);
     			skip_bytes = pres_bytes - presentation_bytes;
     
    -			for (j = 0; j < skip_bytes; j++) {
    +			for (j = 0; j < skip_bytes && gf_bs_available(bs); j++) {
     				gf_bs_read_int(bs, 8);
     			}
     		}
     		else if (desc_mode == GF_AC4_DESCMODE_WRITE) {
     			p = gf_list_get(dsi->presentations, i);
    +			if (!p) continue;
     
     			t_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     			if (p->presentation_version == 0) {
    @@ -2343,7 +2361,7 @@ void gf_odf_ac4_cfg_deep_copy(GF_AC4Config *dst, GF_AC4Config *src)
     
     	memcpy(dst, src, sizeof(GF_AC4Config));
     
    -	if (!src->stream.presentations || gf_list_count(presentations_src) == 0) {
    +	if (!src->stream.presentations) {
     		return;
     	}
     
    @@ -2369,7 +2387,7 @@ void gf_odf_ac4_presentation_deep_copy(GF_AC4PresentationV1 *pres_dst, GF_AC4Pre
     
     	memcpy(pres_dst, pres_src, sizeof(GF_AC4PresentationV1));
     
    -	if (!pres_src->substream_groups || gf_list_count(pres_src->substream_groups) == 0) {
    +	if (!pres_src->substream_groups) {
     		return;
     	}
     
    @@ -2381,7 +2399,7 @@ void gf_odf_ac4_presentation_deep_copy(GF_AC4PresentationV1 *pres_dst, GF_AC4Pre
     		memcpy(group_dst, group_src, sizeof(GF_AC4SubStreamGroupV1));
     		gf_list_add(pres_dst->substream_groups, group_dst);
     
    -		if (!group_src->substreams || gf_list_count(group_src->substreams) == 0) {
    +		if (!group_src->substreams) {
     			continue;
     		}
     
    @@ -2399,44 +2417,62 @@ void gf_odf_ac4_presentation_deep_copy(GF_AC4PresentationV1 *pres_dst, GF_AC4Pre
     GF_EXPORT
     void gf_odf_ac4_cfg_clean_list(GF_AC4Config *cfg)
     {
    -	u32 i, j, s;
    +	u32 i, s;
     	GF_AC4PresentationV1 *pres;
     	GF_AC4SubStreamGroupV1 *group;
     	GF_AC4SubStream *subs;
     
    -	if (!cfg || !cfg->stream.presentations) {
    +	if (!cfg)
     		return;
    -	}
     
    -	for (i = 0; i < gf_list_count(cfg->stream.presentations); i++) {
    -		pres = gf_list_get(cfg->stream.presentations, i);
    -		if (!pres || !pres->substream_groups) {
    -			continue;
    -		}
    +	if (cfg->stream.presentations) {
     
    -		for (j = 0; pres && j < gf_list_count(pres->substream_groups); j++) {
    -			group = gf_list_get(pres->substream_groups, j);
    -			if (!group || !group->substreams) {
    -				continue;
    -			}
    +		while ( (pres = gf_list_pop_back(cfg->stream.presentations)) ) {
    +
    +			if (pres->substream_groups) {
    +
    +				while ( (group = gf_list_pop_back(pres->substream_groups)) ) {
    +
    +					if (group->substreams) {
    +
    +						for (s = 0; s < gf_list_count(group->substreams); s++) {
    +							subs = gf_list_get(group->substreams, s);
    +							if (!subs) {
    +								continue;
    +							}
    +
    +							gf_free(subs);
    +						}
    +						gf_list_del(group->substreams);
    +
    +					}
    +					gf_free(group);
    +
    +					// remove potential duplicates of group
    +					s32 idx = 1;
    +					while (idx>=0) {
    +						idx = gf_list_find(pres->substream_groups, group);
    +						if (idx>=0) gf_list_rem(pres->substream_groups, idx);
    +					}
    +				}
    +				gf_list_del(pres->substream_groups);
    +
    +				// remove potential duplicates of substream_groups
    +				for (i=0; i<gf_list_count(cfg->stream.presentations); i++) {
    +					GF_AC4PresentationV1* pres2 = gf_list_get(cfg->stream.presentations, i);
    +					if (pres2 && pres2->substream_groups == pres->substream_groups) {
    +						pres2->substream_groups = NULL;
    +					}
     
    -			for (s = 0; group && s < gf_list_count(group->substreams); s++) {
    -				subs = gf_list_get(group->substreams, s);
    -				if (!subs) {
    -					continue;
     				}
     
    -				gf_free(subs);
     			}
    -			gf_list_del(group->substreams);
    -			gf_free(group);
    +			gf_free(pres);
     		}
    -		gf_list_del(pres->substream_groups);
    -		gf_free(pres);
    -	}
     
    -	gf_list_del(cfg->stream.presentations);
    -	cfg->stream.presentations = NULL;
    +		gf_list_del(cfg->stream.presentations);
    +		cfg->stream.presentations = NULL;
    +	}
     }
     
     GF_EXPORT
    

Vulnerability mechanics

Synthesis attempt was rejected by the grounding validator. Re-run pending.

References

4

News mentions

0

No linked articles in our index yet.