Commit Diff


commit - 22a742e4cb81812769f1efa6e24ee24ad10f1a60
commit + a2fd80132769e268bee6af754eca6eb13035de78
blob - 7f9216e14774690e29c10e082732daf65c9dd451
blob + 2b6a1c86c9ed55ad4c9710bbe351fcecffb2bd66
--- gmid.h
+++ gmid.h
@@ -240,7 +240,7 @@ int		 parse_iri(char*, struct iri*, const char**);
 int		 trim_req_iri(char*, const char **);
 
 /* puny.c */
-int		 puny_decode(const char*, char*, size_t);
+int		 puny_decode(const char*, char*, size_t, const char**);
 
 /* utils.c */
 int		 starts_with(const char*, const char*);
blob - c84f4e01a9fe6b4ae81f8447d7f89e48876cdf5e
blob + 8bb66c1953b8269da0a14fd85ed9f4ec01e7eb81
--- puny.c
+++ puny.c
@@ -91,26 +91,34 @@ digit_value(char c)
 }
 
 static int
-insert(char *out, size_t len, int codepoint, size_t i)
+insert(char *out, size_t len, int codepoint, size_t i, char **err)
 {
 	int l;
 	char *t;
 
-	if (codepoint <= 0x7F)
+	if (codepoint <= 0x7F) {
+		*err = "puny: invalid decoded character (ASCII range)";
 		return 0;
-	else if (codepoint <= 0x7FF)
+	} else if (codepoint <= 0x7FF) {
 		l = 2;
-	else if (codepoint <= 0xFFFF)
+	} else if (codepoint <= 0xFFFF) {
 		l = 3;
-	else if (codepoint <= 0x10FFFF)
+	} else if (codepoint <= 0x10FFFF) {
 		l = 4;
-	else
+	} else {
+		*err = "puny: invalid decoded character";
 		return 0;
+	}
 
-	if ((t = utf8_nth(out, i)) == NULL)
+	if ((t = utf8_nth(out, i)) == NULL) {
+		*err = "puny: invalid insert position";
 		return 0;
-	if (t + l >= out + len)
+	}
+
+	if (t + l >= out + len) {
+		*err = "puny: insert would overflow";
 		return 0;
+	}
 
 	memmove(t + l, t, strlen(t));
 
@@ -135,7 +143,7 @@ insert(char *out, size_t len, int codepoint, size_t i)
 }
 
 static int
-decode(const char *str, char *out, size_t len)
+decode(const char *str, char *out, size_t len, const char **err)
 {
 	size_t i;
 	uint32_t n;
@@ -152,8 +160,10 @@ decode(const char *str, char *out, size_t len)
 	str += 4;
 
 	if (strchr(str, '-') != NULL) {
-		if ((s = copy_label(str, out, len)) == NULL)
+		if ((s = copy_label(str, out, len)) == NULL) {
+			*err = "puny: invalid label";
 			return 0;
+		}
 		if (*s == '-')
 			s++;
 	} else
@@ -170,8 +180,10 @@ decode(const char *str, char *out, size_t len)
 		w = 1;
 
 		for (k = BASE; ; k += BASE) {
-			if (*s == '\0')
+			if (*s == '\0') {
+				*err = "puny: label truncated?";
 				return 0;
+			}
 			/* fail eventually? */
 			digit = digit_value(*s);
 			s++;
@@ -213,7 +225,7 @@ end_of_label(const char *hostname)
 }
 
 int
-puny_decode(const char *hostname, char *out, size_t len)
+puny_decode(const char *hostname, char *out, size_t len, const char **err)
 {
 	char label[LABEL_LEN];
 	const char *s, *end;
@@ -227,24 +239,30 @@ puny_decode(const char *hostname, char *out, size_t le
 	for (;;) {
 		end = end_of_label(s);
 		l = end - s;
-		if (l >= sizeof(label))
+		if (l >= sizeof(label)) {
+			*err = "label too long";
 			return 0;
+		}
 
 		memcpy(label, s, l);
 		label[l] = '\0';
 
-		if (!decode(label, out, len))
+		if (!decode(label, out, len, err))
 			return 0;
 
 		if (*end == '\0')
 			return 1;
 
-		if (strlcat(out, ".", len) >= len)
+		if (strlcat(out, ".", len) >= len) {
+			*err = "domain name too long";
 			return 0;
+		}
 
 		l = strlen(out);
-		if (l >= len)
+		if (l >= len) {
+			*err = "domain name too long";
 			return 0;
+		}
 		out += l;
 		len -= l;
 
blob - f19116fa076b5d3e18a5593ca0bbe99e049b12d6
blob + 137103ff3985eeaba927c7d38e0c0c205856cb69
--- server.c
+++ server.c
@@ -320,14 +320,13 @@ handle_open_conn(struct pollfd *fds, struct client *c)
 	}
 
 	if (!trim_req_iri(c->req, &parse_err)
-	    || !parse_iri(c->req, &c->iri, &parse_err)) {
+	    || !parse_iri(c->req, &c->iri, &parse_err)
+	    || !puny_decode(c->iri.host, decoded, sizeof(decoded), &parse_err)) {
 		LOGI(c, "iri parse error: %s", parse_err);
 		start_reply(fds, c, BAD_REQUEST, "invalid request");
 		return;
 	}
 
-	puny_decode(c->iri.host, decoded, sizeof(decoded));
-
 	if (c->iri.port_no != conf.port
 	    || strcmp(c->iri.schema, "gemini")
 	    || strcmp(decoded, c->domain)) {