Commit Diff


commit - a6fd182ad357eeabb88cffe83d799b412e4cdab7
commit + 2ac684a4e1b8a971689edc8c5543832dd1b9db0e
blob - c8b7537c3a1a4cb682e0c7af9a311a4f6d09e6c4
blob + 976d5eac6eb1b6d018e514bb87a9afbb78454dc1
--- gotwebd/gotweb.c
+++ gotwebd/gotweb.c
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2016, 2019, 2020-2022 Tracey Emery <tracey@traceyemery.net>
  * Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
+ * Copyright (c) 2014 Reyk Floeter <reyk@openbsd.org>
  * Copyright (c) 2013 David Gwynne <dlg@openbsd.org>
  * Copyright (c) 2013 Florian Obser <florian@openbsd.org>
  *
@@ -23,6 +24,7 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
+#include <ctype.h>
 #include <dirent.h>
 #include <errno.h>
 #include <event.h>
@@ -421,13 +423,62 @@ err:
 	return error;
 }
 
+/*
+ * Adapted from usr.sbin/httpd/httpd.c url_decode.
+ */
 static const struct got_error *
+gotweb_urldecode(char *url)
+{
+	char		*p, *q;
+	char		 hex[3];
+	unsigned long	 x;
+
+	hex[2] = '\0';
+	p = q = url;
+
+	while (*p != '\0') {
+		switch (*p) {
+		case '%':
+			/* Encoding character is followed by two hex chars */
+			if (!isxdigit((unsigned char)p[1]) ||
+			    !isxdigit((unsigned char)p[2]) ||
+			    (p[1] == '0' && p[2] == '0'))
+				return got_error(GOT_ERR_BAD_QUERYSTRING);
+
+			hex[0] = p[1];
+			hex[1] = p[2];
+
+			/*
+			 * We don't have to validate "hex" because it is
+			 * guaranteed to include two hex chars followed by nul.
+			 */
+			x = strtoul(hex, NULL, 16);
+			*q = (char)x;
+			p += 2;
+			break;
+		default:
+			*q = *p;
+			break;
+		}
+		p++;
+		q++;
+	}
+	*q = '\0';
+
+	return NULL;
+}
+
+static const struct got_error *
 gotweb_assign_querystring(struct querystring **qs, char *key, char *value)
 {
 	const struct got_error *error = NULL;
 	const char *errstr;
 	int a_cnt, el_cnt;
 
+	error = gotweb_urldecode(value);
+	if (error)
+		return error;
+
 	for (el_cnt = 0; el_cnt < QSELEM__MAX; el_cnt++) {
 		if (strcmp(key, querystring_keys[el_cnt].name) != 0)
 			continue;
blob - ab13ceafe2a0043b913454118e0c81bab18d3ea1
blob + 32ded08f2703834a744542900c736972cdb203ad
--- include/got_error.h
+++ include/got_error.h
@@ -175,6 +175,7 @@
 #define GOT_ERR_VERIFY_TAG_SIGNATURE 155
 #define GOT_ERR_SIGNING_TAG	156
 #define GOT_ERR_COMMIT_REDUNDANT_AUTHOR 157
+#define GOT_ERR_BAD_QUERYSTRING	158
 
 struct got_error {
         int code;
blob - bee9789607409d33d238a9d098ae9924da0f1344
blob + bd09c98f60e847f0f4694f3931012a07cce40577
--- lib/error.c
+++ lib/error.c
@@ -230,6 +230,7 @@ static const struct got_error got_errors[] = {
 	{ GOT_ERR_SIGNING_TAG, "unable to sign tag" },
 	{ GOT_ERR_COMMIT_REDUNDANT_AUTHOR, "specified author is equal to the "
 	    "default one"},
+	{ GOT_ERR_BAD_QUERYSTRING, "invalid query string" },
 };
 
 static struct got_custom_error {