From 2bfb1e012abca1dbb3797bc5e72e2af3ee741dec Mon Sep 17 00:00:00 2001
From: Jo-Philipp Wich <jow@openwrt.org>
Date: Thu, 3 May 2012 17:19:16 +0000
Subject: [PATCH] uhttpd URL-codec bug fixes.

* Fixed output-buffer-overflow bug in uh_urlencode() and uh_urldecode() [tested
  input-buffer index against output-buffer length].  In reality, this would not
  typically cause an overflow on decode, where the output string would be
  expected to be shorter than the input string; and uh_urlencode() seems to have
  been unreferenced in the source.

* Fixed bug: uh_urlencode() and uh_urldecode() both read one extra byte from the
  input-string.  While this could manifest in C code, the result was most
  egregious when called from Lua, where it caused an extra null byte to be
  embedded at the end of the output string.

* uh_urlencode() cleanup: removed redundant bitwise-and.

Signed-off-by: David Favro <openwrt@meta-dynamic.com>

SVN-Revision: 31569
---
 package/uhttpd/src/uhttpd-utils.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/package/uhttpd/src/uhttpd-utils.c b/package/uhttpd/src/uhttpd-utils.c
index a47f175ba6..1073f3bb34 100644
--- a/package/uhttpd/src/uhttpd-utils.c
+++ b/package/uhttpd/src/uhttpd-utils.c
@@ -305,6 +305,9 @@ int uh_http_send(
 }
 
 
+/* blen is the size of buf; slen is the length of src.  The input-string need
+** not be, and the output string will not be, null-terminated.  Returns the
+** length of the decoded string. */
 int uh_urldecode(char *buf, int blen, const char *src, int slen)
 {
 	int i;
@@ -315,11 +318,11 @@ int uh_urldecode(char *buf, int blen, const char *src, int slen)
 		(((x) <= 'F') ? ((x) - 'A' + 10) : \
 			((x) - 'a' + 10)))
 
-	for( i = 0; (i <= slen) && (i <= blen); i++ )
+	for( i = 0; (i < slen) && (len < blen); i++ )
 	{
 		if( src[i] == '%' )
 		{
-			if( ((i+2) <= slen) && isxdigit(src[i+1]) && isxdigit(src[i+2]) )
+			if( ((i+2) < slen) && isxdigit(src[i+1]) && isxdigit(src[i+2]) )
 			{
 				buf[len++] = (char)(16 * hex(src[i+1]) + hex(src[i+2]));
 				i += 2;
@@ -338,13 +341,16 @@ int uh_urldecode(char *buf, int blen, const char *src, int slen)
 	return len;
 }
 
+/* blen is the size of buf; slen is the length of src.  The input-string need
+** not be, and the output string will not be, null-terminated.  Returns the
+** length of the encoded string. */
 int uh_urlencode(char *buf, int blen, const char *src, int slen)
 {
 	int i;
 	int len = 0;
 	const char hex[] = "0123456789abcdef";
 
-	for( i = 0; (i <= slen) && (i <= blen); i++ )
+	for( i = 0; (i < slen) && (len < blen); i++ )
 	{
 		if( isalnum(src[i]) || (src[i] == '-') || (src[i] == '_') ||
 		    (src[i] == '.') || (src[i] == '~') )
@@ -355,7 +361,7 @@ int uh_urlencode(char *buf, int blen, const char *src, int slen)
 		{
 			buf[len++] = '%';
 			buf[len++] = hex[(src[i] >> 4) & 15];
-			buf[len++] = hex[(src[i] & 15) & 15];
+			buf[len++] = hex[ src[i]       & 15];
 		}
 		else
 		{
@@ -527,7 +533,7 @@ struct path_info * uh_path_lookup(struct client *cl, const char *url)
 			uh_urldecode(
 				&buffer[strlen(docroot)],
 				sizeof(buffer) - strlen(docroot) - 1,
-				url, (int)(pathptr - url) - 1
+				url, pathptr - url
 			);
 	}
 
-- 
GitLab