CVE-2021-32132: NULL Pointer Dereference (CWE-476)
value: The abst_box_size 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-13T15:15Z
Repository: https://github.com/gpac/gpac
Language: C
Files changed: include/gpac/internal/isomedia_dev.h, src/isomedia/box_code_adobe.c
Commit date: 2021-04-22 10:59:53 +0200
Commit message: fixed #1753

Diff: diff --git a/include/gpac/internal/isomedia_dev.h b/include/gpac/internal/isomedia_dev.h
index bdcb1ae0821..5a3eb9381a2 100644
--- a/include/gpac/internal/isomedia_dev.h
+++ b/include/gpac/internal/isomedia_dev.h
@@ -597,10 +597,17 @@ typedef struct
 			GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[isom] not enough bytes in box %s: %d left, reading %d (file %s, line %d)\n", gf_4cc_to_str(__ptr->type), (u32) __ptr->size, (bytes), __FILE__, __LINE__ )); \
 			return GF_ISOM_INVALID_FILE; \
 		}\
 		__ptr->size -= bytes; \
 
+#define ISOM_DECREASE_SIZE_GOTO_EXIT(__ptr, bytes)	if (__ptr->size < (bytes) ) {\
+			GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[isom] not enough bytes in box %s: %d left, reading %d (file %s, line %d)\n", gf_4cc_to_str(__ptr->type), (u32) __ptr->size, (bytes), __FILE__, __LINE__ )); \
+			e = GF_ISOM_INVALID_FILE; \
+			goto exit;\
+		}\
+		__ptr->size -= bytes; \
+
 
 #define ISOM_DECREASE_SIZE_NO_ERR(__ptr, bytes)	if (__ptr->size < (bytes) ) {\
 			GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[isom] not enough bytes in box %s: %d left, reading %d (file %s, line %d), skipping box\n", gf_4cc_to_str(__ptr->type), (u32) __ptr->size, (bytes), __FILE__, __LINE__ )); \
 			return GF_OK; \
 		}\
diff --git a/src/isomedia/box_code_adobe.c b/src/isomedia/box_code_adobe.c
index 711d84bf0d9..d61d4dd67c5 100644
--- a/src/isomedia/box_code_adobe.c
+++ b/src/isomedia/box_code_adobe.c
@@ -78,11 +78,11 @@ GF_Err abst_box_read(GF_Box *s, GF_BitStream *bs)
 	GF_AdobeBootstrapInfoBox *ptr = (GF_AdobeBootstrapInfoBox *)s;
 	int i;
 	u32 tmp_strsize;
 	char *tmp_str;
 	Bool zfound=GF_FALSE;
-	GF_Err e;
+	GF_Err e = GF_OK;
 
 	ISOM_DECREASE_SIZE(ptr, 25)
 	ptr->bootstrapinfo_version = gf_bs_read_u32(bs);
 	ptr->profile = gf_bs_read_int(bs, 2);
 	ptr->live = gf_bs_read_int(bs, 1);
@@ -98,139 +98,165 @@ GF_Err abst_box_read(GF_Box *s, GF_BitStream *bs)
 	tmp_str = gf_malloc(sizeof(char)*tmp_strsize);
 	if (!tmp_str) return GF_OUT_OF_MEM;
 	memset(tmp_str, 0, sizeof(char)*tmp_strsize);
 
 	while (tmp_strsize) {
-		ISOM_DECREASE_SIZE(ptr, 1)
+		ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, 1)
 		tmp_str[i] = gf_bs_read_u8(bs);
 		tmp_strsize--;
 		if (!tmp_str[i]) {
 			zfound = GF_TRUE;
 			break;
 		}
 		i++;
 	}
-	if (!zfound)
-		return GF_ISOM_INVALID_FILE;
+	if (!zfound) {
+		e = GF_ISOM_INVALID_FILE;
+		goto exit;
+	}
 	if (i) {
 		ptr->movie_identifier = gf_strdup(tmp_str);
 	}
 
-	ISOM_DECREASE_SIZE(ptr, 1)
+	ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, 1)
 	ptr->server_entry_count = gf_bs_read_u8(bs);
 	for (i=0; i<ptr->server_entry_count; i++) {
 		int j=0;
 		zfound = GF_FALSE;
 		tmp_strsize=(u32)ptr->size;
 		while (tmp_strsize) {
-			ISOM_DECREASE_SIZE(ptr, 1)
+			ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, 1)
 			tmp_str[j] = gf_bs_read_u8(bs);
 			tmp_strsize--;
 			if (!tmp_str[j]) {
 				zfound = GF_TRUE;
 				break;
 			}
 			j++;
 		}
-		if (!zfound)
-			return GF_ISOM_INVALID_FILE;
+		if (!zfound) {
+			e = GF_ISOM_INVALID_FILE;
+			goto exit;
+		}
 		if (j) {
 			gf_list_insert(ptr->server_entry_table, gf_strdup(tmp_str), i);
 		}
 	}
+	if (ptr->server_entry_count != gf_list_count(ptr->server_entry_table)) {
+		e = GF_ISOM_INVALID_FILE;
+		goto exit;
+	}
 
-	ISOM_DECREASE_SIZE(ptr, 1)
+	ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, 1)
 	ptr->quality_entry_count = gf_bs_read_u8(bs);
 	for (i=0; i<ptr->quality_entry_count; i++) {
 		int j=0;
 		zfound = GF_FALSE;
 		tmp_strsize=(u32)ptr->size;
 		while (tmp_strsize) {
-			ISOM_DECREASE_SIZE(ptr, 1)
+			ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, 1)
 			tmp_str[j] = gf_bs_read_u8(bs);
 			tmp_strsize--;
 			if (!tmp_str[j]) {
 				zfound = GF_TRUE;
 				break;
 			}
 			j++;
 		}
 
-		if (!zfound)
-			return GF_ISOM_INVALID_FILE;
+		if (!zfound) {
+			e = GF_ISOM_INVALID_FILE;
+			goto exit;
+		}
 		if (j) {
 			gf_list_insert(ptr->quality_entry_table, gf_strdup(tmp_str), i);
 		}
 	}
+	if (ptr->quality_entry_count != gf_list_count(ptr->quality_entry_table)) {
+		e = GF_ISOM_INVALID_FILE;
+		goto exit;
+	}
 
 	i=0;
 	tmp_strsize=(u32)ptr->size;
 	zfound = GF_FALSE;
 	while (tmp_strsize) {
-		ISOM_DECREASE_SIZE(ptr, 1)
+		ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, 1)
 		tmp_str[i] = gf_bs_read_u8(bs);
 		tmp_strsize--;
 		if (!tmp_str[i]) {
 			zfound = GF_TRUE;
 			break;
 		}
 		i++;
 	}
-	if (!zfound)
-		return GF_ISOM_INVALID_FILE;
+	if (!zfound) {
+		e = GF_ISOM_INVALID_FILE;
+		goto exit;
+	}
+
 	if (i) {
 		ptr->drm_data = gf_strdup(tmp_str);
 	}
 
 	i=0;
 	tmp_strsize=(u32)ptr->size;
 	zfound = GF_FALSE;
 	while (tmp_strsize) {
-		ISOM_DECREASE_SIZE(ptr, 1)
+		ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, 1)
 		tmp_str[i] = gf_bs_read_u8(bs);
 		tmp_strsize--;
 		if (!tmp_str[i]) {
 			zfound = GF_TRUE;
 			break;
 		}
 		i++;
 	}
-	if (!zfound)
-		return GF_ISOM_INVALID_FILE;
+	if (!zfound) {
+		e = GF_ISOM_INVALID_FILE;
+		goto exit;
+	}
+
 	if (i) {
 		ptr->meta_data = gf_strdup(tmp_str);
 	}
 
-	ISOM_DECREASE_SIZE(ptr, 1)
+	ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, 1)
 	ptr->segment_run_table_count = gf_bs_read_u8(bs);
 	for (i=0; i<ptr->segment_run_table_count; i++) {
 		GF_AdobeSegmentRunTableBox *asrt = NULL;
 		e = gf_isom_box_parse((GF_Box **)&asrt, bs);
 		if (e) {
 			if (asrt) gf_isom_box_del((GF_Box*)asrt);
-			gf_free(tmp_str);
-			return e;
+			goto exit;
 		}
 		gf_list_add(ptr->segment_run_table_entries, asrt);
 	}
+	if (ptr->segment_run_table_count != gf_list_count(ptr->segment_run_table_entries)) {
+		e = GF_ISOM_INVALID_FILE;
+		goto exit;
+	}
 
-	ISOM_DECREASE_SIZE(ptr, 1)
+	ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, 1)
 	ptr->fragment_run_table_count = gf_bs_read_u8(bs);
 	for (i=0; i<ptr->fragment_run_table_count; i++) {
 		GF_AdobeFragmentRunTableBox *afrt = NULL;
 		e = gf_isom_box_parse((GF_Box **)&afrt, bs);
 		if (e) {
 			if (afrt) gf_isom_box_del((GF_Box*)afrt);
-			gf_free(tmp_str);
-			return e;
+			goto exit;
 		}
 		gf_list_add(ptr->fragment_run_table_entries, afrt);
 	}
+	if (ptr->fragment_run_table_count != gf_list_count(ptr->fragment_run_table_entries)) {
+		e = GF_ISOM_INVALID_FILE;
+		goto exit;
+	}
 
+exit:
 	gf_free(tmp_str);
-
-	return GF_OK;
+	return e;
 }
 
 GF_Box *abst_box_new()
 {
 	ISOM_DECL_BOX_ALLOC(GF_AdobeBootstrapInfoBox, GF_ISOM_BOX_TYPE_ABST);

Vulnerable code: 	GF_Err e;
		ISOM_DECREASE_SIZE(ptr, 1)
	if (!zfound)
		return GF_ISOM_INVALID_FILE;
	ISOM_DECREASE_SIZE(ptr, 1)
			ISOM_DECREASE_SIZE(ptr, 1)
		if (!zfound)
			return GF_ISOM_INVALID_FILE;
	ISOM_DECREASE_SIZE(ptr, 1)
			ISOM_DECREASE_SIZE(ptr, 1)
		if (!zfound)
			return GF_ISOM_INVALID_FILE;
		ISOM_DECREASE_SIZE(ptr, 1)
	if (!zfound)
		return GF_ISOM_INVALID_FILE;
		ISOM_DECREASE_SIZE(ptr, 1)
	if (!zfound)
		return GF_ISOM_INVALID_FILE;
	ISOM_DECREASE_SIZE(ptr, 1)
			gf_free(tmp_str);
			return e;
	ISOM_DECREASE_SIZE(ptr, 1)
			gf_free(tmp_str);
			return e;

	return GF_OK;
Fixed code: #define ISOM_DECREASE_SIZE_GOTO_EXIT(__ptr, bytes)	if (__ptr->size < (bytes) ) {\
			GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[isom] not enough bytes in box %s: %d left, reading %d (file %s, line %d)\n", gf_4cc_to_str(__ptr->type), (u32) __ptr->size, (bytes), __FILE__, __LINE__ )); \
			e = GF_ISOM_INVALID_FILE; \
			goto exit;\
		}\
		__ptr->size -= bytes; \

	GF_Err e = GF_OK;
		ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, 1)
	if (!zfound) {
		e = GF_ISOM_INVALID_FILE;
		goto exit;
	}
	ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, 1)
			ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, 1)
		if (!zfound) {
			e = GF_ISOM_INVALID_FILE;
			goto exit;
		}
	if (ptr->server_entry_count != gf_list_count(ptr->server_entry_table)) {
		e = GF_ISOM_INVALID_FILE;
		goto exit;
	}
	ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, 1)
			ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, 1)
		if (!zfound) {
			e = GF_ISOM_INVALID_FILE;
			goto exit;
		}
	if (ptr->quality_entry_count != gf_list_count(ptr->quality_entry_table)) {
		e = GF_ISOM_INVALID_FILE;
		goto exit;
	}
		ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, 1)
	if (!zfound) {
		e = GF_ISOM_INVALID_FILE;
		goto exit;
	}

		ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, 1)
	if (!zfound) {
		e = GF_ISOM_INVALID_FILE;
		goto exit;
	}

	ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, 1)
			goto exit;
	if (ptr->segment_run_table_count != gf_list_count(ptr->segment_run_table_entries)) {
		e = GF_ISOM_INVALID_FILE;
		goto exit;
	}
	ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, 1)
			goto exit;
	if (ptr->fragment_run_table_count != gf_list_count(ptr->fragment_run_table_entries)) {
		e = GF_ISOM_INVALID_FILE;
		goto exit;
	}
exit:
	return e;