CVE-2022-29339: Reachable Assertion (CWE-617)
value: In GPAC 2.1-DEV-rev87-g053aae8-master, function BS_ReadByte() in utils/bitstream.c has a failed assertion, which causes a Denial of Service. This vulnerability was fixed in commit 9ea93a2.
CWE description: The product contains an assert() or similar statement that can be triggered by an attacker, which leads to an application exit or other behavior that is more severe than necessary.
CVSS v3 base score: 7.5
Published: 2022-05-05T13:15Z
Repository: https://github.com/gpac/gpac
Language: C
Files changed: src/isomedia/avc_ext.c, src/utils/bitstream.c
Commit date: 2022-04-12 10:56:15 +0200
Commit message: fixed #2165

Diff: diff --git a/src/isomedia/avc_ext.c b/src/isomedia/avc_ext.c
index d4a58492bb58..365fa6b940e4 100644
--- a/src/isomedia/avc_ext.c
+++ b/src/isomedia/avc_ext.c
@@ -3521,10 +3521,15 @@ GF_Err gf_isom_oinf_read_entry(void *entry, GF_BitStream *bs)
 		for (j = 0; j < op->layer_count; j++) {
 			op->layers_info[j].ptl_idx = gf_bs_read_u8(bs);
 			op->layers_info[j].layer_id = gf_bs_read_int(bs, 6);
 			op->layers_info[j].is_outputlayer = gf_bs_read_int(bs, 1) ? GF_TRUE : GF_FALSE;
 			op->layers_info[j].is_alternate_outputlayer = gf_bs_read_int(bs, 1) ? GF_TRUE : GF_FALSE;
+
+			if (gf_bs_is_overflow(bs)) {
+				gf_free(op);
+				return GF_NON_COMPLIANT_BITSTREAM;
+			}
 		}
 		op->minPicWidth = gf_bs_read_u16(bs);
 		op->minPicHeight = gf_bs_read_u16(bs);
 		op->maxPicWidth = gf_bs_read_u16(bs);
 		op->maxPicHeight = gf_bs_read_u16(bs);
@@ -3540,10 +3545,14 @@ GF_Err gf_isom_oinf_read_entry(void *entry, GF_BitStream *bs)
 		}
 		if (op->bit_rate_info_flag) {
 			op->maxBitRate = gf_bs_read_u32(bs);
 			op->avgBitRate = gf_bs_read_u32(bs);
 		}
+		if (gf_bs_is_overflow(bs)) {
+			gf_free(op);
+			return GF_NON_COMPLIANT_BITSTREAM;
+		}
 		gf_list_add(ptr->operating_points, op);
 	}
 	count = gf_bs_read_u8(bs);
 	for (i = 0; i < count; i++) {
 		LHEVC_DependentLayer *dep;
@@ -3559,10 +3568,14 @@ GF_Err gf_isom_oinf_read_entry(void *entry, GF_BitStream *bs)
 			dep->dependent_on_layerID[j] = gf_bs_read_u8(bs);
 		for (j = 0; j < 16; j++) {
 			if (ptr->scalability_mask & (1 << j))
 				dep->dimension_identifier[j] = gf_bs_read_u8(bs);
 		}
+		if (gf_bs_is_overflow(bs)) {
+			gf_free(dep);
+			return GF_NON_COMPLIANT_BITSTREAM;
+		}
 		gf_list_add(ptr->dependency_layers, dep);
 	}
 
 	return GF_OK;
 }
diff --git a/src/utils/bitstream.c b/src/utils/bitstream.c
index 6ea644ca121d..a446499c669f 100644
--- a/src/utils/bitstream.c
+++ b/src/utils/bitstream.c
@@ -373,13 +373,16 @@ static u8 BS_ReadByte(GF_BitStream *bs)
 	}
 	if (bs->cache_write)
 		bs_flush_write_cache(bs);
 
 	is_eos = gf_feof(bs->stream);
+	//cache not fully read, reset EOS
+	if (bs->cache_read && (bs->cache_read_pos<bs->cache_read_size))
+		is_eos = GF_FALSE;
 
 	/*we are in FILE mode, test for end of file*/
-	if (!is_eos || bs->cache_read) {
+	if (!is_eos) {
 		u8 res;
 		Bool loc_eos=GF_FALSE;
 		assert(bs->position<=bs->size);
 		bs->position++;
 
@@ -406,11 +409,14 @@ static u8 BS_ReadByte(GF_BitStream *bs)
 bs_eof:
 	if (bs->EndOfStream) {
 		bs->EndOfStream(bs->par);
 		if (!bs->overflow_state) bs->overflow_state = 1;
 	} else {
-		GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[BS] Attempt to overread bitstream\n"));
+		if (!bs->overflow_state) {
+			bs->overflow_state = 1;
+			GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[BS] Attempt to overread bitstream\n"));
+		}
 	}
 	assert(bs->position <= 1+bs->size);
 	return 0;
 }
 

Vulnerable code: 	if (!is_eos || bs->cache_read) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[BS] Attempt to overread bitstream\n"));
Fixed code: 
			if (gf_bs_is_overflow(bs)) {
				gf_free(op);
				return GF_NON_COMPLIANT_BITSTREAM;
			}
		if (gf_bs_is_overflow(bs)) {
			gf_free(op);
			return GF_NON_COMPLIANT_BITSTREAM;
		}
		if (gf_bs_is_overflow(bs)) {
			gf_free(dep);
			return GF_NON_COMPLIANT_BITSTREAM;
		}
	//cache not fully read, reset EOS
	if (bs->cache_read && (bs->cache_read_pos<bs->cache_read_size))
		is_eos = GF_FALSE;
	if (!is_eos) {
		if (!bs->overflow_state) {
			bs->overflow_state = 1;
			GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[BS] Attempt to overread bitstream\n"));
		}