From 0000ce2271077c3d233d8498f7963ad78502a1f2 Mon Sep 17 00:00:00 2001
From: Jo-Philipp Wich <jow@openwrt.org>
Date: Wed, 11 Jul 2012 09:59:05 +0000
Subject: [PATCH] uhttpd: retry parsing the CGI header until the buffer space
 is exhausted

SVN-Revision: 32662
---
 package/uhttpd/Makefile         |  2 +-
 package/uhttpd/src/uhttpd-cgi.c | 25 +++++++++++++++++--------
 package/uhttpd/src/uhttpd-cgi.h |  6 +++++-
 package/uhttpd/src/uhttpd-lua.h |  1 -
 4 files changed, 23 insertions(+), 11 deletions(-)

diff --git a/package/uhttpd/Makefile b/package/uhttpd/Makefile
index 89ca4b69e8..cefd30bb8c 100644
--- a/package/uhttpd/Makefile
+++ b/package/uhttpd/Makefile
@@ -8,7 +8,7 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=uhttpd
-PKG_RELEASE:=38
+PKG_RELEASE:=39
 
 PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
 PKG_CONFIG_DEPENDS := \
diff --git a/package/uhttpd/src/uhttpd-cgi.c b/package/uhttpd/src/uhttpd-cgi.c
index e527922624..b46ebf2bdd 100644
--- a/package/uhttpd/src/uhttpd-cgi.c
+++ b/package/uhttpd/src/uhttpd-cgi.c
@@ -133,7 +133,7 @@ static void uh_cgi_shutdown(struct uh_cgi_state *state)
 
 static bool uh_cgi_socket_cb(struct client *cl)
 {
-	int i, len, hdroff;
+	int i, len, blen, hdroff;
 	char buf[UH_LIMIT_MSGHEAD];
 
 	struct uh_cgi_state *state = (struct uh_cgi_state *)cl->priv;
@@ -184,15 +184,20 @@ static bool uh_cgi_socket_cb(struct client *cl)
 	}
 
 	/* try to read data from child */
-	while ((len = uh_raw_recv(cl->rpipe.fd, buf, sizeof(buf), -1)) > 0)
+	while ((len = uh_raw_recv(cl->rpipe.fd, buf, state->header_sent
+	                          ? sizeof(buf) : state->httpbuf.len, -1)) > 0)
 	{
 		/* we have not pushed out headers yet, parse input */
 		if (!state->header_sent)
 		{
 			/* try to parse header ... */
-			memcpy(state->httpbuf, buf, len);
+			memcpy(state->httpbuf.ptr, buf, len);
+			state->httpbuf.len -= len;
+			state->httpbuf.ptr += len;
 
-			if (uh_cgi_header_parse(res, state->httpbuf, len, &hdroff))
+			blen = state->httpbuf.ptr - state->httpbuf.buf;
+
+			if (uh_cgi_header_parse(res, state->httpbuf.buf, blen, &hdroff))
 			{
 				/* write status */
 				ensure_out(uh_http_sendf(cl, NULL,
@@ -229,18 +234,19 @@ static bool uh_cgi_socket_cb(struct client *cl)
 				state->header_sent = true;
 
 				/* push out remaining head buffer */
-				if (hdroff < len)
+				if (hdroff < blen)
 				{
 					D("CGI: Child(%d) relaying %d rest bytes\n",
-					  cl->proc.pid, len - hdroff);
+					  cl->proc.pid, blen - hdroff);
 
 					ensure_out(uh_http_send(cl, req,
-											&buf[hdroff], len - hdroff));
+					                        state->httpbuf.buf + hdroff,
+					                        blen - hdroff));
 				}
 			}
 
 			/* ... failed and head buffer exceeded */
-			else
+			else if (!state->httpbuf.len)
 			{
 				/* I would do this ...
 				 *
@@ -536,6 +542,9 @@ bool uh_cgi_request(struct client *cl, struct path_info *pi,
 
 		D("CGI: Child(%d) created: rfd(%d) wfd(%d)\n", child, rfd[0], wfd[1]);
 
+		state->httpbuf.ptr = state->httpbuf.buf;
+		state->httpbuf.len = sizeof(state->httpbuf.buf);
+
 		state->content_length = cl->httpbuf.len;
 
 		/* find content length */
diff --git a/package/uhttpd/src/uhttpd-cgi.h b/package/uhttpd/src/uhttpd-cgi.h
index fffcc5d353..c7094da424 100644
--- a/package/uhttpd/src/uhttpd-cgi.h
+++ b/package/uhttpd/src/uhttpd-cgi.h
@@ -28,7 +28,11 @@
 
 
 struct uh_cgi_state {
-	char httpbuf[UH_LIMIT_MSGHEAD];
+	struct {
+		char buf[UH_LIMIT_MSGHEAD];
+		char *ptr;
+		int len;
+	} httpbuf;
 	int content_length;
 	bool header_sent;
 };
diff --git a/package/uhttpd/src/uhttpd-lua.h b/package/uhttpd/src/uhttpd-lua.h
index ae573a3cec..780d845d87 100644
--- a/package/uhttpd/src/uhttpd-lua.h
+++ b/package/uhttpd/src/uhttpd-lua.h
@@ -33,7 +33,6 @@
 
 
 struct uh_lua_state {
-	char httpbuf[UH_LIMIT_MSGHEAD];
 	int content_length;
 	bool data_sent;
 };
-- 
GitLab