summary refs log tree commit diff
diff options
context:
space:
mode:
authorLeah Neukirchen <leah@vuxu.org>2021-08-10 22:17:19 +0200
committerLeah Neukirchen <leah@vuxu.org>2021-08-10 22:21:42 +0200
commit69a1701438fa91a23b452255e870542dfd250255 (patch)
treed7c9f172ec132e4e21d45660ed4a688312947606
parente894a26cf538f8341b93acf6ececc3df88125bc7 (diff)
downloadhittpd-69a1701438fa91a23b452255e870542dfd250255.tar.gz
hittpd-69a1701438fa91a23b452255e870542dfd250255.tar.xz
hittpd-69a1701438fa91a23b452255e870542dfd250255.zip
fix mimetype lookup
Fix overflow on long mime types, found by Érico Nogueira.
Allow maximum length of mime types, as per spec, then truncate.

Fix mime type lookup when extensions match some mime type.
-rw-r--r--hittpd.c38
1 files changed, 26 insertions, 12 deletions
diff --git a/hittpd.c b/hittpd.c
index 554ed0d..77fcda3 100644
--- a/hittpd.c
+++ b/hittpd.c
@@ -453,27 +453,41 @@ send_ok(http_parser *p, time_t modified, const char *mimetype, off_t filesize)
 	}
 }
 
+static const char *
+getmime(const char *mime, char *ext)
+{
+	size_t extlen = strlen(ext);
+	const char *c = mime;
+
+	do {
+		c++;
+		if (strncmp(c, ext, extlen) == 0 && c[extlen] == '=')
+			return c + extlen + 1;
+	} while ((c = strchr(c, ':')));
+
+	return 0;
+}
+
 const char *
 mimetype(char *ext)
 {
-	static char type[16];
+	static char type[256];  // RFC 6838
 
 	if (!ext)
 		return default_mimetype;
 
-	char *x = strstr(custom_mimetypes, ext);
+	const char *x = getmime(custom_mimetypes, ext);
 	if (!x)
-		x = strstr(mimetypes, ext);
-
-	if (x && x[-1] == ':' && x[strlen(ext)] == '=') {
-		char *t = type;
-		for (char *c = x + strlen(ext) + 1; *c && *c != ':'; )
-			*t++ = *c++;
-		*t = 0;
-		return type;
-	}
+		x = getmime(mimetypes, ext);
+	if (!x)
+		return default_mimetype;
 
-	return default_mimetype;
+	char *t = type;
+	char *e = type + sizeof type - 1;
+	for (const char *c = x; t < e && *c && *c != ':'; )
+		*t++ = *c++;
+	*t = 0;
+	return type;
 }
 
 static inline int