Instead of storing a pointer to the beginning of the query string within the
request url, store the byte offset instead.

Since the URL is usually kept in the per-client blob buffer which might
change its memory location due to reallocations triggered by blobmsg_add_*,
it is not safe to point to it early in the request life cycle.

This fixes invalid memory access usually manifesting itself as corrupted
query string data in CGI scripts.

Reported-by: P. Wassi <p.wa...@gmx.at>
Signed-off-by: Jo-Philipp Wich <j...@mein.io>
---
 file.c   | 13 +++++++------
 lua.c    |  2 +-
 proc.c   |  2 +-
 uhttpd.h |  2 +-
 4 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/file.c b/file.c
index a1775f5..5ca8db5 100644
--- a/file.c
+++ b/file.c
@@ -156,7 +156,7 @@ uh_path_lookup(struct client *cl, const char *url)
 
        /* separate query string from url */
        if ((pathptr = strchr(url, '?')) != NULL) {
-               p.query = pathptr[1] ? pathptr + 1 : NULL;
+               p.query_offset = pathptr[1] ? (pathptr - url + 1) : 0;
 
                /* urldecode component w/o query */
                if (pathptr > url) {
@@ -239,8 +239,8 @@ uh_path_lookup(struct client *cl, const char *url)
                        ustream_printf(cl->us, "Content-Length: 0\r\n");
                ustream_printf(cl->us, "Location: %s%s%s\r\n\r\n",
                                &path_phys[docroot_len],
-                               p.query ? "?" : "",
-                               p.query ? p.query : "");
+                               p.query_offset ? "?" : "",
+                               p.query_offset ? (url + p.query_offset) : "");
                uh_request_done(cl);
                p.redirected = 1;
                return &p;
@@ -733,14 +733,13 @@ static int field_len(const char *ptr)
        _field(root) \
        _field(phys) \
        _field(name) \
-       _field(info) \
-       _field(query)
+       _field(info)
 
 static void
 uh_defer_script(struct client *cl, struct dispatch_handler *d, struct 
path_info *pi)
 {
        struct deferred_request *dr;
-       char *_root, *_phys, *_name, *_info, *_query;
+       char *_root, *_phys, *_name, *_info;
 
        cl->dispatch.req_free = uh_free_pending_request;
 
@@ -757,6 +756,8 @@ uh_defer_script(struct client *cl, struct dispatch_handler 
*d, struct path_info
 #undef _field
 #define _field(_name) if (pi->_name) dr->pi._name = strcpy(_##_name, 
pi->_name);
                path_info_fields
+
+               dr->pi.query_offset = pi->query_offset;
        } else {
                dr = calloc(1, sizeof(*dr));
        }
diff --git a/lua.c b/lua.c
index 3efe22b..2ad8d35 100644
--- a/lua.c
+++ b/lua.c
@@ -219,7 +219,7 @@ static void lua_main(struct client *cl, struct path_info 
*pi, char *url)
        str = strchr(url, '?');
        if (str) {
                if (*(str + 1))
-                       pi->query = str + 1;
+                       pi->query_offset = str - url + 1;
                path_len = str - url;
        }
 
diff --git a/proc.c b/proc.c
index e360897..ca22430 100644
--- a/proc.c
+++ b/proc.c
@@ -145,7 +145,7 @@ struct env_var *uh_get_process_vars(struct client *cl, 
struct path_info *pi)
        extra_vars[VAR_SCRIPT_NAME].value = pi->name;
        extra_vars[VAR_SCRIPT_FILE].value = pi->phys;
        extra_vars[VAR_DOCROOT].value = pi->root;
-       extra_vars[VAR_QUERY].value = pi->query ? pi->query : "";
+       extra_vars[VAR_QUERY].value = pi->query_offset ? (url + 
pi->query_offset) : "";
        extra_vars[VAR_REQUEST].value = url;
        extra_vars[VAR_PROTO].value = http_versions[req->version];
        extra_vars[VAR_METHOD].value = http_methods[req->method];
diff --git a/uhttpd.h b/uhttpd.h
index 374cd72..6e77457 100644
--- a/uhttpd.h
+++ b/uhttpd.h
@@ -145,7 +145,7 @@ struct path_info {
        const char *phys;
        const char *name;
        const char *info;
-       const char *query;
+       size_t query_offset;
        bool redirected;
        struct stat stat;
        const struct interpreter *ip;
-- 
2.14.2


_______________________________________________
Lede-dev mailing list
Lede-dev@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/lede-dev

Reply via email to