From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from krisdoz.my.domain (schwarze@localhost [127.0.0.1]) by krisdoz.my.domain (8.14.5/8.14.5) with ESMTP id s6PG7G2i029576 for ; Fri, 25 Jul 2014 12:07:16 -0400 (EDT) Received: (from schwarze@localhost) by krisdoz.my.domain (8.14.5/8.14.3/Submit) id s6PG7D3i000189; Fri, 25 Jul 2014 12:07:13 -0400 (EDT) Date: Fri, 25 Jul 2014 12:07:13 -0400 (EDT) Message-Id: <201407251607.s6PG7D3i000189@krisdoz.my.domain> X-Mailinglist: mdocml-source Reply-To: source@mdocml.bsd.lv MIME-Version: 1.0 From: schwarze@mdocml.bsd.lv To: source@mdocml.bsd.lv Subject: mdocml: Rewrite http_parse() completely: 1. X-Mailer: activitymail 1.26, http://search.cpan.org/dist/activitymail/ Content-Type: text/plain; charset=utf-8 Log Message: ----------- Rewrite http_parse() completely: 1. Make sure the last occurrence of each key is used, even if it is empty, in which case it resets the value to the default. 2. When there is an HTTP encoding error, skip the affected key-value pair only, but not all subsequent key-value pairs. 3. Do not modify a string returned from getenv(3). 4. Do not assume the NULL pointer is all null bits. Modified Files: -------------- mdocml: cgi.c Revision Data ------------- Index: cgi.c =================================================================== RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/cgi.c,v retrieving revision 1.82 retrieving revision 1.83 diff -Lcgi.c -Lcgi.c -u -p -r1.82 -r1.83 --- cgi.c +++ cgi.c @@ -39,10 +39,10 @@ * A query as passed to the search function. */ struct query { - const char *manpath; /* desired manual directory */ - const char *arch; /* architecture */ - const char *sec; /* manual section */ - const char *expr; /* unparsed expression string */ + char *manpath; /* desired manual directory */ + char *arch; /* architecture */ + char *sec; /* manual section */ + char *expr; /* unparsed expression string */ int equal; /* match whole names, not substrings */ }; @@ -58,7 +58,7 @@ static void html_print(const char *); static void html_printquery(const struct req *); static void html_putchar(char); static int http_decode(char *); -static void http_parse(struct req *, char *); +static void http_parse(struct req *, const char *); static void http_print(const char *); static void http_putchar(char); static void http_printquery(const struct req *); @@ -213,65 +213,114 @@ html_print(const char *p) } /* - * Parse out key-value pairs from an HTTP request variable. - * This can be either a cookie or a POST/GET string, although man.cgi - * uses only GET for simplicity. + * Transfer the responsibility for the allocated string *val + * to the query structure. */ static void -http_parse(struct req *req, char *p) +set_query_attr(char **attr, char **val) { - char *key, *val; - memset(&req->q, 0, sizeof(struct query)); - req->q.manpath = req->p[0]; - req->q.equal = 1; + free(*attr); + if (**val == '\0') { + *attr = NULL; + free(*val); + } else + *attr = *val; + *val = NULL; +} - while ('\0' != *p) { - key = p; - val = NULL; +/* + * Parse the QUERY_STRING for key-value pairs + * and store the values into the query structure. + */ +static void +http_parse(struct req *req, const char *qs) +{ + char *key, *val; + size_t keysz, valsz; - p += (int)strcspn(p, ";&"); - if ('\0' != *p) - *p++ = '\0'; - if (NULL != (val = strchr(key, '='))) - *val++ = '\0'; + req->q.manpath = NULL; + req->q.arch = NULL; + req->q.sec = NULL; + req->q.expr = NULL; + req->q.equal = 1; - if ('\0' == *key || NULL == val || '\0' == *val) - continue; + key = val = NULL; + while (*qs != '\0') { + + /* Parse one key. */ - /* Just abort handling. */ + keysz = strcspn(qs, "=;&"); + key = mandoc_strndup(qs, keysz); + qs += keysz; + if (*qs != '=') + goto next; - if ( ! http_decode(key)) - break; - if (NULL != val && ! http_decode(val)) - break; - - if (0 == strcmp(key, "query")) - req->q.expr = val; - else if (0 == strcmp(key, "manpath")) { + /* Parse one value. */ + + valsz = strcspn(++qs, ";&"); + val = mandoc_strndup(qs, valsz); + qs += valsz; + + /* Decode and catch encoding errors. */ + + if ( ! (http_decode(key) && http_decode(val))) + goto next; + + /* Handle key-value pairs. */ + + if ( ! strcmp(key, "query")) + set_query_attr(&req->q.expr, &val); + + else if ( ! strcmp(key, "apropos")) + req->q.equal = !strcmp(val, "0"); + + else if ( ! strcmp(key, "manpath")) { #ifdef COMPAT_OLDURI - if (0 == strncmp(val, "OpenBSD ", 8)) { + if ( ! strncmp(val, "OpenBSD ", 8)) { val[7] = '-'; if ('C' == val[8]) val[8] = 'c'; } #endif - req->q.manpath = val; - } else if (0 == strcmp(key, "apropos")) - req->q.equal = !strcmp(val, "0"); - else if (0 == strcmp(key, "sec")) { - if (strcmp(val, "0")) - req->q.sec = val; + set_query_attr(&req->q.manpath, &val); + } + + else if ( ! (strcmp(key, "sec") #ifdef COMPAT_OLDURI - } else if (0 == strcmp(key, "sektion")) { - if (strcmp(val, "0")) - req->q.sec = val; + && strcmp(key, "sektion") #endif - } else if (0 == strcmp(key, "arch")) { - if (strcmp(val, "default")) - req->q.arch = val; + )) { + if ( ! strcmp(val, "0")) + *val = '\0'; + set_query_attr(&req->q.sec, &val); } + + else if ( ! strcmp(key, "arch")) { + if ( ! strcmp(val, "default")) + *val = '\0'; + set_query_attr(&req->q.arch, &val); + } + + /* + * The key must be freed in any case. + * The val may have been handed over to the query + * structure, in which case it is now NULL. + */ +next: + free(key); + key = NULL; + free(val); + val = NULL; + + if (*qs != '\0') + qs++; } + + /* Fall back to the default manpath. */ + + if (req->q.manpath == NULL) + req->q.manpath = mandoc_strdup(req->p[0]); } static void @@ -895,8 +944,10 @@ pg_show(struct req *req, const char *pat return; } - if (strcmp(path, "mandoc")) - req->q.manpath = path; + if (strcmp(path, "mandoc")) { + free(req->q.manpath); + req->q.manpath = mandoc_strdup(path); + } resp_begin_html(200, NULL); resp_searchform(req); @@ -987,7 +1038,7 @@ main(void) { struct req req; const char *path; - char *querystring; + const char *querystring; int i; /* Scan our run-time environment. */ @@ -1050,6 +1101,10 @@ main(void) else pg_index(&req); + free(req.q.manpath); + free(req.q.arch); + free(req.q.sec); + free(req.q.expr); for (i = 0; i < (int)req.psz; i++) free(req.p[i]); free(req.p); -- To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv