CVE-2023-0760: Heap-based Buffer Overflow (CWE-122)
value: Heap-based Buffer Overflow in GitHub repository gpac/gpac prior to V2.1.0-DEV.
CWE description: A heap overflow condition is a buffer overflow, where the buffer that can be overwritten is allocated in the heap portion of memory, generally meaning that the buffer was allocated using a routine such as malloc().
CVSS v3 base score: 7.8
Published: 2023-02-09T14:15Z
Repository: https://github.com/gpac/gpac
Language: C
Files changed: src/isomedia/box_code_base.c, src/isomedia/box_funcs.c, src/isomedia/isom_read.c
Commit date: 2023-02-09 09:10:52 +0100
Commit message: sgpd box entry: disallow null grouping_type (#2389)

Diff: diff --git a/src/isomedia/box_code_base.c b/src/isomedia/box_code_base.c
index baf07ff352f0..9a9ad09b456d 100644
--- a/src/isomedia/box_code_base.c
+++ b/src/isomedia/box_code_base.c
@@ -4427,11 +4427,11 @@ GF_Err video_sample_entry_box_size(GF_Box *s)
 	gf_isom_check_position(s, (GF_Box *)ptr->hevc_config, &pos);
 	gf_isom_check_position(s, (GF_Box *)ptr->lhvc_config, &pos);
 
 	/*VVC*/
 	gf_isom_check_position(s, (GF_Box *)ptr->vvc_config, &pos);
-	
+
 	/*AV1*/
 	gf_isom_check_position(s, (GF_Box *)ptr->av1_config, &pos);
 
 	/*VPx*/
 	gf_isom_check_position(s, (GF_Box *)ptr->vp_config, &pos);
@@ -8855,11 +8855,11 @@ GF_Err dac3_box_write(GF_Box *s, GF_BitStream *bs)
 
 	if (ptr->cfg.is_ec3) s->type = GF_ISOM_BOX_TYPE_DEC3;
 	e = gf_isom_box_write_header(s, bs);
 	if (ptr->cfg.is_ec3) s->type = GF_ISOM_BOX_TYPE_DAC3;
 	if (e) return e;
-	
+
 	e = gf_odf_ac3_cfg_write_bs(&ptr->cfg, bs);
 	if (e) return e;
 
 	if (ptr->cfg.atmos_ec3_ext || ptr->cfg.complexity_index_type) {
 		gf_bs_write_int(bs, 0, 7);
@@ -9981,10 +9981,13 @@ static void *sgpd_parse_entry(u32 grouping_type, GF_BitStream *bs, s32 bytes_in_
 			ptr->groupIDs[i] = gf_bs_read_u16(bs);
 			*total_bytes += 2;
 		}
 		return ptr;
 	}
+	case 0:
+		GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] sgpd entry null grouping_type is invalid\n") );
+		return NULL;
 	default:
 		break;
 	}
 
 	if (!entry_size && !null_size_ok) {
diff --git a/src/isomedia/box_funcs.c b/src/isomedia/box_funcs.c
index 98ff6bbff6d4..eb7f4415105d 100644
--- a/src/isomedia/box_funcs.c
+++ b/src/isomedia/box_funcs.c
@@ -102,11 +102,11 @@ GF_Err gf_isom_box_parse_ex(GF_Box **outBox, GF_BitStream *bs, u32 parent_type,
 	u8 *uncomp_data = NULL;
 	u32 compressed_size=0;
 	GF_Box *newBox;
 	Bool skip_logs = (gf_bs_get_cookie(bs) & GF_ISOM_BS_COOKIE_NO_LOGS ) ? GF_TRUE : GF_FALSE;
 	Bool is_special = GF_TRUE;
-	
+
 	if ((bs == NULL) || (outBox == NULL) ) return GF_BAD_PARAM;
 	*outBox = NULL;
 	if (gf_bs_available(bs) < 8) {
 		return GF_ISOM_INCOMPLETE_FILE;
 	}
@@ -1526,11 +1526,11 @@ static struct box_registry_entry {
 	BOX_DEFINE_S_CHILD( GF_QT_SUBTYPE_IYUV, video_sample_entry, "stsd", "apple"),
 	BOX_DEFINE_S_CHILD( GF_QT_SUBTYPE_YV12, video_sample_entry, "stsd", "apple"),
 	BOX_DEFINE_S_CHILD( GF_QT_SUBTYPE_YVYU, video_sample_entry, "stsd", "apple"),
 	BOX_DEFINE_S_CHILD( GF_QT_SUBTYPE_RGBA, video_sample_entry, "stsd", "apple"),
 	BOX_DEFINE_S_CHILD( GF_QT_SUBTYPE_ABGR, video_sample_entry, "stsd", "apple"),
-	
+
 	FBOX_DEFINE_S(GF_QT_BOX_TYPE_STPS, stss, "stbl", 0, "apple"),
 
 	//dolby boxes
 	BOX_DEFINE_S_CHILD( GF_ISOM_BOX_TYPE_AC3, audio_sample_entry, "stsd", "dolby"),
 	BOX_DEFINE_S_CHILD( GF_ISOM_BOX_TYPE_EC3, audio_sample_entry, "stsd", "dolby"),
@@ -1916,11 +1916,11 @@ void gf_isom_check_position(GF_Box *s, GF_Box *child, u32 *pos)
 	if (s->internal_flags & GF_ISOM_ORDER_FREEZE)
 		return;
 
 	s32 cur_pos = gf_list_find(s->child_boxes, child);
 
-	//happens when partially cloning boxes 
+	//happens when partially cloning boxes
 	if (cur_pos < 0) return;
 
 	if (cur_pos != (s32) *pos) {
 		gf_list_del_item(s->child_boxes, child);
 		gf_list_insert(s->child_boxes, child, *pos);
@@ -1947,11 +1947,11 @@ GF_Err gf_isom_box_write(GF_Box *a, GF_BitStream *bs)
 	GF_Err e;
 	u64 pos = gf_bs_get_position(bs);
 	if (!a) return GF_BAD_PARAM;
 	//box has been disabled, do not write
 	if (!a->size) return GF_OK;
-	
+
 	if (a->registry->disabled) {
 		GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[iso file] Box %s disabled registry, skip write\n", gf_4cc_to_str(a->type)));
 		return GF_OK;
 	}
 
diff --git a/src/isomedia/isom_read.c b/src/isomedia/isom_read.c
index ba474c335f38..5484d862355f 100644
--- a/src/isomedia/isom_read.c
+++ b/src/isomedia/isom_read.c
@@ -2302,11 +2302,11 @@ GF_Err gf_isom_get_sample_for_media_time(GF_ISOFile *the_file, u32 trackNumber,
 		shadow->dataLength = 0;
 		gf_isom_sample_del(&shadow);
 	}
 	if (static_sample && ! (*sample)->alloc_size )
 		 (*sample)->alloc_size =  (*sample)->dataLength;
-		 
+
 	return GF_OK;
 }
 
 GF_EXPORT
 GF_Err gf_isom_get_sample_for_movie_time(GF_ISOFile *the_file, u32 trackNumber, u64 movieTime, u32 *StreamDescriptionIndex, GF_ISOSearchMode SearchMode, GF_ISOSample **sample, u32 *sampleNumber, u64 *data_offset)
@@ -4672,11 +4672,11 @@ const u32 *gf_isom_get_track_switch_parameter(GF_ISOFile *movie, u32 trackNumber
 
 	map = udta_getEntry(trak->udta, GF_ISOM_BOX_TYPE_TSEL, NULL);
 	if (!map) return NULL;
 	tsel = (GF_TrackSelectionBox*)gf_list_get(map->boxes, group_index-1);
 	if (!tsel) return NULL;
-	
+
 	*switchGroupID = tsel->switchGroup;
 	*criteriaListSize = tsel->attributeListCount;
 	return (const u32 *) tsel->attributeList;
 }
 
@@ -5407,11 +5407,11 @@ GF_Err gf_isom_get_sample_cenc_info_internal(GF_TrackBox *trak, void *traf, GF_S
 	if (IsEncrypted) *IsEncrypted = GF_FALSE;
 	if (crypt_byte_block) *crypt_byte_block = 0;
 	if (skip_byte_block) *skip_byte_block = 0;
 	if (key_info) *key_info = NULL;
 	if (key_info_size) *key_info_size = 0;
-	
+
 	if (!trak) return GF_BAD_PARAM;
 
 #ifdef	GPAC_DISABLE_ISOM_FRAGMENTS
 	if (traf)
 		return GF_NOT_SUPPORTED;

Vulnerable code: 	
	
	
	
	//happens when partially cloning boxes 
	
		 
	
	
Fixed code: 

	case 0:
		GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] sgpd entry null grouping_type is invalid\n") );
		return NULL;


	//happens when partially cloning boxes