CVE-2022-29339 (published 2022-05-05T13:15Z)

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.

Severity: MEDIUM
CVSS v2 base score: 5.0 (AV:N/AC:L/Au:N/C:N/I:N/A:P)
CVSS v3 base score: 7.5, HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)

Weakness information:
cwe_id: CWE-617
cwe_name: Reachable Assertion
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.
extended_description: 
            While assertion is good for catching logic errors and reducing the chances of reaching more serious vulnerability conditions, it can still lead to a denial of service.
            For example, if a server handles multiple simultaneous connections, and an assert() occurs in one single connection that causes all other connections to be dropped, this is a reachable assertion that leads to a denial of service.
         
         

Fix information:
repo_url: https://github.com/gpac/gpac
commit_details: repo_url: https://github.com/gpac/gpac
author: jeanlf
author_date: 2022-04-12 10:56:15+02:00
msg: fixed #2165
repository: repo_url: https://github.com/gpac/gpac
repo_name: gpac/gpac
description: GPAC Ultramedia OSS for Video Streaming & Next-Gen Multimedia Transcoding, Packaging & Delivery
repo_language: C
owner: gpac
file_changes: filename: avc_ext.c
change_type: ModificationType.MODIFY
diff: @@ -3523,6 +3523,11 @@ GF_Err gf_isom_oinf_read_entry(void *entry, GF_BitStream *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);
@@ -3542,6 +3547,10 @@ GF_Err gf_isom_oinf_read_entry(void *entry, GF_BitStream *bs)
 			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);
@@ -3561,6 +3570,10 @@ GF_Err gf_isom_oinf_read_entry(void *entry, GF_BitStream *bs)
 			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);
 	}
 

programming_language: C
filename: bitstream.c
change_type: ModificationType.MODIFY
diff: @@ -375,9 +375,12 @@ static u8 BS_ReadByte(GF_BitStream *bs)
 		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);
@@ -408,7 +411,10 @@ bs_eof:
 		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;

programming_language: C