CVE-2018-20762 (published 2019-02-06T23:29Z)

GPAC version 0.7.1 and earlier has a buffer overflow vulnerability in the cat_multiple_files function in applications/mp4box/fileimport.c when MP4Box is used for a local directory containing crafted filenames.

Severity: MEDIUM
CVSS v2 base score: 6.8 (AV:N/AC:M/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 7.8, HIGH (CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-119
cwe_name: Improper Restriction of Operations within the Bounds of a Memory Buffer
description: The product performs operations on a memory buffer, but it reads from or writes to a memory location outside the buffer's intended boundary. This may result in read or write operations on unexpected memory locations that could be linked to other variables, data structures, or internal program data.
extended_description: 
            Certain languages allow direct addressing of memory locations and do not automatically ensure that these locations are valid for the memory buffer that is being referenced. This can cause read or write operations to be performed on memory locations that may be associated with other variables, data structures, or internal program data.
         
         

Fix information:
repo_url: https://github.com/gpac/gpac
commit_details: repo_url: https://github.com/gpac/gpac
author: Aurelien David
author_date: 2019-01-11 11:32:54+01:00
msg: fix some overflows due to strcpy

fixes #1184, #1186, #1187 among other things
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: fileimport.c
change_type: ModificationType.MODIFY
diff: @@ -2356,17 +2356,33 @@ GF_Err cat_multiple_files(GF_ISOFile *dest, char *fileName, u32 import_flags, Do
 	cat_enum.align_timelines = align_timelines;
 	cat_enum.allow_add_in_command = allow_add_in_command;
 
+	if (strlen(fileName) >= sizeof(cat_enum.szPath)) {
+		GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("File name %s is too long.\n", fileName));
+		return GF_NOT_SUPPORTED;
+	}
 	strcpy(cat_enum.szPath, fileName);
 	sep = strrchr(cat_enum.szPath, GF_PATH_SEPARATOR);
 	if (!sep) sep = strrchr(cat_enum.szPath, '/');
 	if (!sep) {
 		strcpy(cat_enum.szPath, ".");
+		if (strlen(fileName) >= sizeof(cat_enum.szRad1)) {
+			GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("File name %s is too long.\n", fileName));
+			return GF_NOT_SUPPORTED;
+		}
 		strcpy(cat_enum.szRad1, fileName);
 	} else {
+		if (strlen(sep + 1) >= sizeof(cat_enum.szRad1)) {
+			GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("File name %s is too long.\n", (sep + 1)));
+			return GF_NOT_SUPPORTED;
+		}
 		strcpy(cat_enum.szRad1, sep+1);
 		sep[0] = 0;
 	}
 	sep = strchr(cat_enum.szRad1, '*');
+	if (strlen(sep + 1) >= sizeof(cat_enum.szRad2)) {
+		GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("File name %s is too long.\n", (sep + 1)));
+		return GF_NOT_SUPPORTED;
+	}
 	strcpy(cat_enum.szRad2, sep+1);
 	sep[0] = 0;
 	sep = strchr(cat_enum.szRad2, '%');
@@ -2374,6 +2390,10 @@ GF_Err cat_multiple_files(GF_ISOFile *dest, char *fileName, u32 import_flags, Do
 	if (!sep) sep = strchr(cat_enum.szRad2, ':');
 	strcpy(cat_enum.szOpt, "");
 	if (sep) {
+		if (strlen(sep) >= sizeof(cat_enum.szOpt)) {
+			GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("Invalid option: %s.\n", sep));
+			return GF_NOT_SUPPORTED;
+		}
 		strcpy(cat_enum.szOpt, sep);
 		sep[0] = 0;
 	}

programming_language: C
filename: main.c
change_type: ModificationType.MODIFY
diff: @@ -910,7 +910,8 @@ Bool GPAC_EventProc(void *ptr, GF_Event *evt)
 		break;
 	case GF_EVENT_NAVIGATE:
 		if (gf_term_is_supported_url(term, evt->navigate.to_url, 1, no_mime_check)) {
-			strcpy(the_url, evt->navigate.to_url);
+			strncpy(the_url, evt->navigate.to_url, sizeof(the_url)-1);
+			the_url[sizeof(the_url) - 1] = 0;
 			fprintf(stderr, "Navigating to URL %s\n", the_url);
 			gf_term_navigate_to(term, evt->navigate.to_url);
 			return 1;
@@ -1099,6 +1100,11 @@ void set_cfg_option(char *opt_string)
 	}
 	{
 		const size_t sepIdx = sep - opt_string;
+		if (sepIdx >= sizeof(szSec)) {
+			fprintf(stderr, "Badly formatted option %s - Section name is too long\n", opt_string);
+			return;
+		}
+
 		strncpy(szSec, opt_string, sepIdx);
 		szSec[sepIdx] = 0;
 	}
@@ -1110,8 +1116,16 @@ void set_cfg_option(char *opt_string)
 	}
 	{
 		const size_t sepIdx = sep2 - sep;
+		if (sepIdx >= sizeof(szKey)) {
+			fprintf(stderr, "Badly formatted option %s - key name is too long\n", opt_string);
+			return;
+		}
 		strncpy(szKey, sep, sepIdx);
 		szKey[sepIdx] = 0;
+		if (strlen(sep2 + 1) >= sizeof(szVal)) {
+			fprintf(stderr, "Badly formatted option %s - value is too long\n", opt_string);
+			return;
+		}
 		strcpy(szVal, sep2+1);
 	}
 
@@ -1680,7 +1694,14 @@ int mp4client_main(int argc, char **argv)
 	else if (!gui_mode && url_arg) {
 		char *ext;
 
-		strcpy(the_url, url_arg);
+		if (strlen(url_arg) >= sizeof(the_url)) {
+			fprintf(stderr, "Input url %s is too long, truncating to %d chars.\n", url_arg, (int)(sizeof(the_url) - 1));
+			strncpy(the_url, url_arg, sizeof(the_url)-1);
+			the_url[sizeof(the_url) - 1] = 0;
+		}
+		else {
+			strcpy(the_url, url_arg);
+		}
 		ext = strrchr(the_url, '.');
 		if (ext && (!stricmp(ext, ".m3u") || !stricmp(ext, ".pls"))) {
 			GF_Err e = GF_OK;
@@ -1692,7 +1713,10 @@ int mp4client_main(int argc, char **argv)
 				GF_DownloadSession *sess = gf_dm_sess_new(term->downloader, the_url, GF_NETIO_SESSION_NOT_THREADED, NULL, NULL, &e);
 				if (sess) {
 					e = gf_dm_sess_process(sess);
-					if (!e) strcpy(the_url, gf_dm_sess_get_cache_name(sess));
+					if (!e) {
+						strncpy(the_url, gf_dm_sess_get_cache_name(sess), sizeof(the_url) - 1);
+						the_url[sizeof(the_cfg) - 1] = 0;
+					}
 					gf_dm_sess_del(sess);
 				}
 			}
@@ -1715,7 +1739,8 @@ int mp4client_main(int argc, char **argv)
 		fprintf(stderr, "Hit 'h' for help\n\n");
 		str = gf_cfg_get_key(cfg_file, "General", "StartupFile");
 		if (str) {
-			strcpy(the_url, "MP4Client "GPAC_FULL_VERSION);
+			strncpy(the_url, "MP4Client "GPAC_FULL_VERSION , sizeof(the_url)-1);
+			the_url[sizeof(the_url) - 1] = 0;
 			gf_term_connect(term, str);
 			startup_file = 1;
 			is_connected = 1;

programming_language: C
filename: ffmpeg_demux.c
change_type: ModificationType.MODIFY
diff: @@ -227,7 +227,7 @@ static Bool FFD_CanHandleURL(GF_InputService *plug, const char *url)
 	AVFormatContext *ctx;
 	AVOutputFormat *fmt_out;
 	Bool ret = GF_FALSE;
-	char *ext, szName[1000], szExt[20];
+	char *ext, szName[1024], szExt[20];
 	const char *szExtList;
 	FFDemux *ffd;
 	if (!plug || !url)
@@ -243,6 +243,9 @@ static Bool FFD_CanHandleURL(GF_InputService *plug, const char *url)
 
 	ffd = (FFDemux*)plug->priv;
 
+	if (strlen(url) >= sizeof(szName))
+		return GF_FALSE;
+
 	strcpy(szName, url);
 	ext = strrchr(szName, '#');
 	if (ext) ext[0] = 0;
@@ -252,7 +255,7 @@ static Bool FFD_CanHandleURL(GF_InputService *plug, const char *url)
 	ext = strrchr(szName, '.');
 	if (ext && strlen(ext) > 19) ext = NULL;
 
-	if (ext && strlen(ext) > 1) {
+	if (ext && strlen(ext) > 1 && strlen(ext) <= sizeof(szExt)) {
 		strcpy(szExt, &ext[1]);
 		strlwr(szExt);
 #ifndef FFMPEG_DEMUX_ENABLE_MPEG2TS

programming_language: C
filename: scene_manager.c
change_type: ModificationType.MODIFY
diff: @@ -646,6 +646,10 @@ GF_Err gf_sm_load_init(GF_SceneLoader *load)
 				ext[0] = '.';
 				ext = anext;
 			}
+			if (strlen(ext) < 2 || strlen(ext) > sizeof(szExt)) {
+				GF_LOG(GF_LOG_ERROR, GF_LOG_SCENE, ("[Scene Manager] invalid extension in file name %s\n", load->fileName));
+				return GF_NOT_SUPPORTED;
+			}
 			strcpy(szExt, &ext[1]);
 			strlwr(szExt);
 			if (strstr(szExt, "bt")) load->type = GF_SM_LOAD_BT;

programming_language: C