CVE-2021-32134: NULL Pointer Dereference (CWE-476)
value: The gf_odf_desc_copy function in GPAC 1.0.1 allows attackers to cause a denial of service (NULL pointer dereference) via a crafted file in the MP4Box command.
CWE description: The product dereferences a pointer that it expects to be valid but is NULL.
CVSS v3 base score: 5.5
Published: 2021-09-13T14:15Z
Repository: https://github.com/gpac/gpac
Language: C
Files changed: src/isomedia/box_code_base.c, src/isomedia/media.c, src/isomedia/sample_descs.c
Commit date: 2021-04-23 14:35:56 +0200
Commit message: fixed #1756

Diff: diff --git a/src/isomedia/box_code_base.c b/src/isomedia/box_code_base.c
index a5a46d8d748..752bd5464fa 100644
--- a/src/isomedia/box_code_base.c
+++ b/src/isomedia/box_code_base.c
@@ -4109,19 +4109,17 @@ GF_Err mp4s_box_read(GF_Box *s, GF_BitStream *bs)
 
 GF_Box *mp4s_box_new()
 {
 	ISOM_DECL_BOX_ALLOC(GF_MPEGSampleEntryBox, GF_ISOM_BOX_TYPE_MP4S);
 	gf_isom_sample_entry_init((GF_SampleEntryBox*)tmp);
-	tmp->internal_type = GF_ISOM_SAMPLE_ENTRY_MP4S;
 	return (GF_Box *)tmp;
 }
 
 GF_Box *encs_box_new()
 {
 	ISOM_DECL_BOX_ALLOC(GF_MPEGSampleEntryBox, GF_ISOM_BOX_TYPE_ENCS);
 	gf_isom_sample_entry_init((GF_SampleEntryBox*)tmp);
-	tmp->internal_type = GF_ISOM_SAMPLE_ENTRY_MP4S;
 	return (GF_Box *)tmp;
 }
 
 
 #ifndef GPAC_DISABLE_ISOM_WRITE
diff --git a/src/isomedia/media.c b/src/isomedia/media.c
index bb50ecf230b..97f9db55232 100644
--- a/src/isomedia/media.c
+++ b/src/isomedia/media.c
@@ -179,12 +179,15 @@ GF_Err Media_GetESD(GF_MediaBox *mdia, u32 sampleDescIndex, GF_ESD **out_esd, Bo
 			type = sinf->original_format->data_format;
 		}
 		break;
 	}
 
+
 	switch (type) {
 	case GF_ISOM_BOX_TYPE_MP4V:
+		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO)
+			return GF_ISOM_INVALID_MEDIA;
 		ESDa = ((GF_MPEGVisualSampleEntryBox*)entry)->esd;
 		if (ESDa) esd = (GF_ESD *) ESDa->desc;
 		/*avc1 encrypted*/
 		else esd = ((GF_MPEGVisualSampleEntryBox*) entry)->emul_esd;
 		break;
@@ -200,38 +203,50 @@ GF_Err Media_GetESD(GF_MediaBox *mdia, u32 sampleDescIndex, GF_ESD **out_esd, Bo
 	case GF_ISOM_BOX_TYPE_264B:
 	case GF_ISOM_BOX_TYPE_265B:
 	case GF_ISOM_BOX_TYPE_DVHE:
 	case GF_ISOM_BOX_TYPE_VVC1:
 	case GF_ISOM_BOX_TYPE_VVI1:
+		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO)
+			return GF_ISOM_INVALID_MEDIA;
 		esd = ((GF_MPEGVisualSampleEntryBox*) entry)->emul_esd;
 		break;
 	case GF_ISOM_BOX_TYPE_SVC1:
 	case GF_ISOM_BOX_TYPE_MVC1:
+		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO)
+			return GF_ISOM_INVALID_MEDIA;
 		if ((mdia->mediaTrack->extractor_mode & 0x0000FFFF) != GF_ISOM_NALU_EXTRACT_INSPECT)
 			AVC_RewriteESDescriptorEx((GF_MPEGVisualSampleEntryBox*) entry, mdia);
 		else
 			AVC_RewriteESDescriptorEx((GF_MPEGVisualSampleEntryBox*) entry, NULL);
 		esd = ((GF_MPEGVisualSampleEntryBox*) entry)->emul_esd;
 		break;
 	case GF_ISOM_BOX_TYPE_LHE1:
 	case GF_ISOM_BOX_TYPE_LHV1:
+		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO)
+			return GF_ISOM_INVALID_MEDIA;
 		if ((mdia->mediaTrack->extractor_mode & 0x0000FFFF) != GF_ISOM_NALU_EXTRACT_INSPECT)
 			HEVC_RewriteESDescriptorEx((GF_MPEGVisualSampleEntryBox*) entry, mdia);
 		else
 			HEVC_RewriteESDescriptorEx((GF_MPEGVisualSampleEntryBox*) entry, NULL);
 		esd = ((GF_MPEGVisualSampleEntryBox*) entry)->emul_esd;
 		break;
 	case GF_ISOM_BOX_TYPE_AV01:
+		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO)
+			return GF_ISOM_INVALID_MEDIA;
 		AV1_RewriteESDescriptorEx((GF_MPEGVisualSampleEntryBox*)entry, mdia);
 		esd = ((GF_MPEGVisualSampleEntryBox*)entry)->emul_esd;
 		break;
 	case GF_ISOM_BOX_TYPE_VP08:
 	case GF_ISOM_BOX_TYPE_VP09:
+		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO)
+			return GF_ISOM_INVALID_MEDIA;
 		VP9_RewriteESDescriptorEx((GF_MPEGVisualSampleEntryBox*)entry, mdia);
 		esd = ((GF_MPEGVisualSampleEntryBox*)entry)->emul_esd;
 		break;
 	case GF_ISOM_BOX_TYPE_MP4A:
+		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_AUDIO)
+			return GF_ISOM_INVALID_MEDIA;
         {
             GF_MPEGAudioSampleEntryBox *ase = (GF_MPEGAudioSampleEntryBox*)entry;
             ESDa = ase->esd;
             if (ESDa) {
 				esd = (GF_ESD *) ESDa->desc;
@@ -268,20 +283,25 @@ GF_Err Media_GetESD(GF_MediaBox *mdia, u32 sampleDescIndex, GF_ESD **out_esd, Bo
 		}
 		break;
 #ifndef GPAC_DISABLE_TTXT
 	case GF_ISOM_BOX_TYPE_TX3G:
 	case GF_ISOM_BOX_TYPE_TEXT:
+		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_MP4S)
+			return GF_ISOM_INVALID_MEDIA;
+
 		if (!true_desc_only && mdia->mediaTrack->moov->mov->convert_streaming_text) {
 			GF_Err e = gf_isom_get_ttxt_esd(mdia, out_esd);
 			if (e) return e;
 			break;
 		}
 		else
 			return GF_ISOM_INVALID_MEDIA;
 #endif
 #ifndef GPAC_DISABLE_VTT
 	case GF_ISOM_BOX_TYPE_WVTT:
+		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_MP4S)
+			return GF_ISOM_INVALID_MEDIA;
 	{
 		GF_WebVTTSampleEntryBox*vtte = (GF_WebVTTSampleEntryBox*)entry;
 		esd =  gf_odf_desc_esd_new(2);
 		*out_esd = esd;
 		esd->decoderConfig->streamType = GF_STREAM_TEXT;
@@ -302,17 +322,22 @@ GF_Err Media_GetESD(GF_MediaBox *mdia, u32 sampleDescIndex, GF_ESD **out_esd, Bo
 	case GF_ISOM_SUBTYPE_3GP_AMR:
 	case GF_ISOM_SUBTYPE_3GP_AMR_WB:
 	case GF_ISOM_SUBTYPE_3GP_EVRC:
 	case GF_ISOM_SUBTYPE_3GP_QCELP:
 	case GF_ISOM_SUBTYPE_3GP_SMV:
+		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_AUDIO)
+			return GF_ISOM_INVALID_MEDIA;
 		if (!true_desc_only) {
 			GF_Err e = gf_isom_get_3gpp_audio_esd(mdia->information->sampleTable, type, (GF_GenericAudioSampleEntryBox*)entry, out_esd);
 			if (e) return e;
 			break;
 		} else return GF_ISOM_INVALID_MEDIA;
 
-	case GF_ISOM_SUBTYPE_OPUS: {
+	case GF_ISOM_SUBTYPE_OPUS:
+		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_AUDIO)
+			return GF_ISOM_INVALID_MEDIA;
+	{
 		GF_OpusSpecificBox *e = ((GF_MPEGAudioSampleEntryBox*)entry)->cfg_opus;
 		GF_BitStream *bs_out;
 		if (!e) {
 			GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("ESD not found for Opus\n)"));
 			break;
@@ -329,10 +354,12 @@ GF_Err Media_GetESD(GF_MediaBox *mdia, u32 sampleDescIndex, GF_ESD **out_esd, Bo
 		gf_bs_get_content(bs_out, & (*out_esd)->decoderConfig->decoderSpecificInfo->data, & (*out_esd)->decoderConfig->decoderSpecificInfo->dataLength);
 		gf_bs_del(bs_out);
 		break;
 	}
 	case GF_ISOM_SUBTYPE_3GP_H263:
+		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO)
+			return GF_ISOM_INVALID_MEDIA;
 		if (true_desc_only) {
 			return GF_ISOM_INVALID_MEDIA;
 		} else {
 			esd =  gf_odf_desc_esd_new(2);
 			*out_esd = esd;
@@ -340,10 +367,12 @@ GF_Err Media_GetESD(GF_MediaBox *mdia, u32 sampleDescIndex, GF_ESD **out_esd, Bo
 			esd->decoderConfig->objectTypeIndication = GF_CODECID_H263;
 			break;
 		}
 
 	case GF_ISOM_SUBTYPE_MP3:
+		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_AUDIO)
+			return GF_ISOM_INVALID_MEDIA;
 		if (true_desc_only) {
 			return GF_ISOM_INVALID_MEDIA;
 		} else {
 			esd =  gf_odf_desc_esd_new(2);
 			*out_esd = esd;
@@ -351,10 +380,12 @@ GF_Err Media_GetESD(GF_MediaBox *mdia, u32 sampleDescIndex, GF_ESD **out_esd, Bo
 			esd->decoderConfig->objectTypeIndication = GF_CODECID_MPEG_AUDIO;
 			break;
 		}
 
 	case GF_ISOM_SUBTYPE_LSR1:
+		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_MP4S)
+			return GF_ISOM_INVALID_MEDIA;
 		if (true_desc_only) {
 			return GF_ISOM_INVALID_MEDIA;
 		} else {
 			GF_LASeRSampleEntryBox*ptr = (GF_LASeRSampleEntryBox*)entry;
 			esd =  gf_odf_desc_esd_new(2);
@@ -369,10 +400,13 @@ GF_Err Media_GetESD(GF_MediaBox *mdia, u32 sampleDescIndex, GF_ESD **out_esd, Bo
 		}
 	case GF_ISOM_SUBTYPE_MH3D_MHA1:
 	case GF_ISOM_SUBTYPE_MH3D_MHA2:
 	case GF_ISOM_SUBTYPE_MH3D_MHM1:
 	case GF_ISOM_SUBTYPE_MH3D_MHM2:
+		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_AUDIO)
+			return GF_ISOM_INVALID_MEDIA;
+
 		if (true_desc_only) {
 			return GF_ISOM_INVALID_MEDIA;
 		} else {
 			GF_MPEGAudioSampleEntryBox*ptr = (GF_MPEGAudioSampleEntryBox*)entry;
 			esd = gf_odf_desc_esd_new(2);
diff --git a/src/isomedia/sample_descs.c b/src/isomedia/sample_descs.c
index 1663b42ac30..b0b65aa7740 100644
--- a/src/isomedia/sample_descs.c
+++ b/src/isomedia/sample_descs.c
@@ -43,10 +43,11 @@ void gf_isom_sample_entry_predestroy(GF_SampleEntryBox *ptr)
 {
 }
 
 void gf_isom_sample_entry_init(GF_SampleEntryBox *ent)
 {
+	ent->internal_type = GF_ISOM_SAMPLE_ENTRY_MP4S;
 }
 
 void gf_isom_video_sample_entry_init(GF_VisualSampleEntryBox *ent)
 {
 	gf_isom_sample_entry_init((GF_SampleEntryBox*)ent);

Vulnerable code: 	tmp->internal_type = GF_ISOM_SAMPLE_ENTRY_MP4S;
	tmp->internal_type = GF_ISOM_SAMPLE_ENTRY_MP4S;
	case GF_ISOM_SUBTYPE_OPUS: {
Fixed code: 
		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO)
			return GF_ISOM_INVALID_MEDIA;
		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO)
			return GF_ISOM_INVALID_MEDIA;
		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO)
			return GF_ISOM_INVALID_MEDIA;
		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO)
			return GF_ISOM_INVALID_MEDIA;
		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO)
			return GF_ISOM_INVALID_MEDIA;
		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO)
			return GF_ISOM_INVALID_MEDIA;
		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_AUDIO)
			return GF_ISOM_INVALID_MEDIA;
		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_MP4S)
			return GF_ISOM_INVALID_MEDIA;

		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_MP4S)
			return GF_ISOM_INVALID_MEDIA;
		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_AUDIO)
			return GF_ISOM_INVALID_MEDIA;
	case GF_ISOM_SUBTYPE_OPUS:
		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_AUDIO)
			return GF_ISOM_INVALID_MEDIA;
	{
		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO)
			return GF_ISOM_INVALID_MEDIA;
		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_AUDIO)
			return GF_ISOM_INVALID_MEDIA;
		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_MP4S)
			return GF_ISOM_INVALID_MEDIA;
		if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_AUDIO)
			return GF_ISOM_INVALID_MEDIA;

	ent->internal_type = GF_ISOM_SAMPLE_ENTRY_MP4S;