From 3309ef975cf570aeb5c1dbf568af323c19bbb3c0 Mon Sep 17 00:00:00 2001 From: Omar Polo Date: Sat, 23 Jan 2021 15:32:38 +0000 Subject: [PATCH] accumulate the whole response line for CGI scripts --- regress/Makefile | 2 +- regress/invalid | 3 +++ regress/runtime | 4 ++++ server.c | 59 ++++++++++++++++++++++++++++++++++++++---------- 4 files changed, 55 insertions(+), 13 deletions(-) create mode 100755 regress/invalid diff --git a/regress/Makefile b/regress/Makefile index 863e5e4..f14b0fa 100644 --- a/regress/Makefile +++ b/regress/Makefile @@ -33,7 +33,7 @@ testdata: fill-file ./sha testdata/bigfile testdata/bigfile.sha printf "# hello world\n" > testdata/index.gmi ./sha testdata/index.gmi testdata/index.gmi.sha - cp hello slow err testdata/ + cp hello slow err invalid testdata/ mkdir testdata/dir cp testdata/index.gmi testdata/dir/foo.gmi diff --git a/regress/invalid b/regress/invalid new file mode 100755 index 0000000..97cca8c --- /dev/null +++ b/regress/invalid @@ -0,0 +1,3 @@ +#!/bin/sh + +echo 'iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii' diff --git a/regress/runtime b/regress/runtime index e9f193c..edfcf74 100755 --- a/regress/runtime +++ b/regress/runtime @@ -159,5 +159,9 @@ eq "$(head /err)" "" "Unexpected head for /err" eq "$(get /err)" "" "Unexpected body for /err" echo OK GET /err with cgi +eq "$(head /invalid | wc -c | xargs)" 2049 "Unexpected body for /invalid" +eq "$(get /invalid)" "" "Unexpected body for /invalid" +echo OK GET /invalid with cgi + check "should be running" quit diff --git a/server.c b/server.c index 8337dcf..69d79c1 100644 --- a/server.c +++ b/server.c @@ -448,6 +448,43 @@ cgi_poll_on_client(struct pollfd *fds, struct client *c) c->fd = fd; } +/* handle the read from the child process. Return like read(2) */ +static ssize_t +read_from_cgi(struct client *c) +{ + void *buf; + size_t len; + ssize_t r; + + /* if we haven't read a whole response line, we want to + * continue reading. */ + + if (c->code == -1) { + buf = c->sbuf + c->len; + len = sizeof(c->sbuf) - c->len; + } else { + buf = c->sbuf; + len = sizeof(c->sbuf); + } + + r = read(c->fd, buf, len); + if (r == 0 || r == -1) + return r; + + c->len += r; + c->off = 0; + + if (c->code != -1) + return r; + + if (strchr(c->sbuf, '\n') || c->len == sizeof(c->sbuf)) { + c->code = 0; + log_request(c, c->sbuf, c->len); + } + + return r; +} + void handle_cgi(struct pollfd *fds, struct client *c) { @@ -457,25 +494,23 @@ handle_cgi(struct pollfd *fds, struct client *c) cgi_poll_on_client(fds, c); while (1) { - if (c->len == 0) { - if ((r = read(c->fd, c->sbuf, sizeof(c->sbuf))) == 0) + if (c->code == -1 || c->len == 0) { + switch (r = read_from_cgi(c)) { + case 0: goto end; - if (r == -1) { + + case -1: if (errno == EAGAIN || errno == EWOULDBLOCK) { cgi_poll_on_child(fds, c); return; } - goto end; + goto end; } - c->len = r; - c->off = 0; + } - /* XXX: if we haven't still read a whole - * reply line, we should go back to poll! */ - if (c->code == -1) { - c->code = 0; - log_request(c, c->sbuf, sizeof(c->sbuf)); - } + if (c->code == -1) { + cgi_poll_on_child(fds, c); + return; } while (c->len > 0) {