commit 9f006a2127398af12ecf9159cd5ef28b3685e7a6 from: Omar Polo date: Sun Feb 07 18:55:04 2021 UTC [cgi] split the query in words if needed and add them to the argv commit - a13739138b17a21dbb50011cc65fb135e9f804c8 commit + 9f006a2127398af12ecf9159cd5ef28b3685e7a6 blob - bf662e37bc7aecfb660fa7d68f1c2d5885361f33 blob + 187a4ac461eb025869e5586e5aecd819b4ee8344 --- ChangeLog +++ ChangeLog @@ -1,5 +1,7 @@ 2021-02-07 Omar Polo + * ex.c (do_exec): [cgi] split the query in words if needed and add them to the argv + * parse.y (option): added prefork option 2021-02-06 Omar Polo blob - 58f5004c7513d3f6f2e4566099fad2bb3b9cb1c4 blob + 0a65472deabc66510a2c758b4d3ac50ecb837912 --- ex.c +++ ex.c @@ -228,6 +228,46 @@ xasprintf(const char *fmt, ...) va_end(ap); return s; +} + +static void +do_exec(const char *ex, const char *spath, char *query) +{ + char **argv, buf[PATH_MAX], *sname, *t; + size_t i, n; + + strlcpy(buf, spath, sizeof(buf)); + sname = basename(buf); + + if (query == NULL || strchr(query, '=') != NULL) { + if ((argv = calloc(2, sizeof(char*))) == NULL) + err(1, "calloc"); + argv[0] = sname; + execvp(ex, argv); + warn("execvp: %s", argv[0]); + return; + } + + n = 1; + for (t = query ;; t++, n++) { + if ((t = strchr(t, '+')) == NULL) + break; + } + + if ((argv = calloc(n+2, sizeof(char*))) == NULL) + err(1, "calloc"); + + argv[0] = sname; + for (i = 0; i < n; ++i) { + t = strchr(query, '+'); + if (t != NULL) + *t = '\0'; + argv[i+1] = pct_decode_str(query); + query = t+1; + } + + execvp(ex, argv); + warn("execvp: %s", argv[0]); } /* fd or -1 on error */ @@ -246,7 +286,6 @@ launch_cgi(struct iri *iri, const char *spath, char *r return -1; case 0: { /* child */ - char *argv[] = {NULL, NULL}; char *ex, *pwd; char iribuf[GEMINI_URL_LEN]; char path[PATH_MAX]; @@ -256,7 +295,6 @@ launch_cgi(struct iri *iri, const char *spath, char *r goto childerr; ex = xasprintf("%s/%s", vhost->dir, spath); - argv[0] = ex; serialize_iri(iri, iribuf, sizeof(iribuf)); @@ -307,15 +345,15 @@ launch_cgi(struct iri *iri, const char *spath, char *r safe_setenv("TLS_CLIENT_ISSUER", cissuer); safe_setenv("TLS_CLIENT_HASH", chash); - strlcpy(path, argv[0], sizeof(path)); + strlcpy(path, ex, sizeof(path)); + pwd = dirname(path); if (chdir(pwd)) { warn("chdir"); goto childerr; } - execvp(argv[0], argv); - warn("execvp: %s", argv[0]); + do_exec(ex, spath, iri->query); goto childerr; } blob - af829ba968a9fc8b2472ce6efd7403d4811d37ef blob + 1beb95e383fae7773dede8dc27991e251dc5e9d7 --- gmid.h +++ gmid.h @@ -257,6 +257,7 @@ char *utf8_nth(char*, size_t); int parse_iri(char*, struct iri*, const char**); int trim_req_iri(char*, const char **); int serialize_iri(struct iri*, char*, size_t); +char *pct_decode_str(char *); /* puny.c */ int puny_decode(const char*, char*, size_t, const char**); blob - 1d550efe97334463553ecebb6f9d4392cc0a1954 blob + b911b0dd6408e147ca0a6beb908dfc8d5ef53d9c --- iri.c +++ iri.c @@ -75,6 +75,13 @@ valid_pct_encoded(struct parser *p) return 1; } +static void +pct_decode(char *s) +{ + sscanf(s+1, "%2hhx", s); + memmove(s+1, s+3, strlen(s+3)+1); +} + static int parse_pct_encoded(struct parser *p) { @@ -86,8 +93,7 @@ parse_pct_encoded(struct parser *p) return 0; } - sscanf(p->iri+1, "%2hhx", p->iri); - memmove(p->iri+1, p->iri+3, strlen(p->iri+3)+1); + pct_decode(p->iri); if (*p->iri == '\0') { p->err = "illegal percent-encoding"; return 0; @@ -437,3 +443,16 @@ serialize_iri(struct iri *i, char *buf, size_t len) return l < len; } + +char * +pct_decode_str(char *s) +{ + char *t; + + for (t = s; *t; ++t) { + if (*t == '%' && valid_pct_enc_string(t)) + pct_decode(t); + } + + return s; +} blob - 9492b1d92e0ab68cca7f4ac7cd36fb69d7c7cfe9 blob + 1c991b3530bd7f9d63f0b5bedc5690ea41de564a --- regress/runtime +++ regress/runtime @@ -69,6 +69,10 @@ quit() { wait || true } +count() { + wc -l | xargs +} + # usage: eq a b errmsg # if a and b aren't equal strings, exit with errmsg eq() { @@ -152,7 +156,7 @@ echo OK GET / with custom lang check "should be running" -# finally try with CGI scripts +# try with CGI scripts config '' 'cgi "*"' checkconf restart @@ -179,6 +183,13 @@ get /bigfile > bigfile eq "$(cat bigfile.sha)" "$(cat testdata/bigfile.sha)" "Unexpected sha for /serve-bigfile" echo OK GET /serve-bigfile with cgi +# ensure we split the query correctly +eq "$(get /env | awk /^-/ | count)" 1 "Unexpected number of arguments" +eq "$(get /env?foo | awk /^-/ | count)" 2 "Unexpected number of arguments" +eq "$(get /env?foo+bar | awk /^-/ | count)" 3 "Unexpected number of arguments" +eq "$(get /env?foo+bar=5 | awk /^-/ | count)" 1 "Unexpected number of arguments" +eq "$(get /env?foo+bar%3d5 | awk /^-/ | count)" 3 "Unexpected number of arguments" + check "should be running" config '' 'index "foo.gmi"'