diff --git a/CHANGES b/CHANGES index 9d339eb..3f8ce1a 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ +4.2: + Remove some bugs in CGI's "Status:" code (reported by Alyssa Milburn). + Make extract_header_field less fragile (reported by Alyssa Milburn). + Possibly fix fake_sendfile (reported by Alyssa Milburn). + 4.1: Fix 0.9 not detected with query_string (Alyssa Milburn). diff --git a/README b/README index e5aa57b..88e378a 100644 --- a/README +++ b/README @@ -81,11 +81,6 @@ if no specific directory for the virtual host was there. eris implements el-cheapo HTTP ranges (only byte ranges and only of the form x-y, not multiple ranges). -eris implements content type matching and Accepts: parsing, but the -content type table is compiled in, i.e. to change it, you have to change -the source code. Shouldn't be a problem because you _have_ the source -code ;) - eris will change dots at the start of file or directory names to colons in the query before trying to answer them. @@ -95,8 +90,6 @@ eris will use sendfile on Linux to enable zero-copy TCP. If eris is given the -c option, it will regard files whose names end with ".cgi" as CGI programs and try to execute them. -CGI programs starting with "nph-" will be handled as no-parse-header -CGIs. Please see for the CGI specification. diff --git a/eris.c b/eris.c index 5df08be..1546832 100644 --- a/eris.c +++ b/eris.c @@ -111,7 +111,6 @@ time_t ims; #define BUFFER_SIZE 8192 -char stdout_buf[BUFFER_SIZE]; /** Log a request */ @@ -406,9 +405,20 @@ cgi_parent(int cin, int cout, int passthru) dolog(302, 0); exit(0); } else if (! strcasecmp(cgiheader, "Status")) { - char *txt = val + 4; + char *txt; - code = atoi(val); + if (val) { + code = (int)strtol(val, &txt, 10); + } else { + code = 0; + } + if (code < 100) { + header(500, "Internal Error"); + printf("CGI returned Status: %d\n", code); + dolog(500, 0); + exit(0); + } + for (; *txt == ' '; txt += 1); header(code, txt); } else { header(200, "OK"); @@ -453,7 +463,7 @@ cgi_parent(int cin, int cout, int passthru) } fflush(stdout); - dolog(200, size); + dolog(code, size); } void @@ -500,7 +510,7 @@ serve_cgi(char *relpath) * Main HTTPd */ -void +ssize_t fake_sendfile(int out_fd, int in_fd, off_t *offset, size_t count) { char buf[BUFFER_SIZE]; @@ -529,6 +539,8 @@ fake_sendfile(int out_fd, int in_fd, off_t *offset, size_t count) } l -= m; } + + return l; } void @@ -580,7 +592,7 @@ serve_file(int fd, char *filename, struct stat *st) alarm(SENDFILE_TIMEOUT); sent = sendfile(1, fd, &range_start, count); if (-1 == sent) { - fake_sendfile(1, fd, &range_start, count); + sent = fake_sendfile(1, fd, &range_start, count); } remain -= sent; } diff --git a/strings.c b/strings.c index f13670b..a9f254c 100644 --- a/strings.c +++ b/strings.c @@ -75,7 +75,7 @@ extract_header_field(char *buf, char **val, int cgi) } } - for (; (buf[len-1] == '\n') || (buf[len-1] == '\r'); len -= 1); + for (; (len > 0) && ((buf[len-1] == '\n') || (buf[len-1] == '\r')); len -= 1); buf[len] = 0; return len; diff --git a/test.sh b/test.sh index 403979a..3b51b89 100755 --- a/test.sh +++ b/test.sh @@ -64,7 +64,18 @@ chmod +x default/redir.cgi cat <<'EOD' > default/status.cgi #! /bin/sh -echo "Status: 300 wat" +case "$PATH_INFO" in +/empty) + echo "Status" + exit 0 + ;; +/nostat) + echo "Status: " + ;; +*) + echo "Status: 300 wat" + ;; +esac echo "Merf: merf" echo echo "james" @@ -240,7 +251,13 @@ title "Redirect" printf 'GET /redir.cgi HTTP/1.0\r\n\r\n' | $HTTPD_CGI 2>/dev/null | grep -Fq 'Location: http://example.com/froot' && pass || fail title "Status" -printf 'GET /status.cgi HTTP/1.0\r\n\r\n' | $HTTPD_CGI 2>/dev/null | d | grep -q '^HTTP/1.0 300 wat#%' && pass || fail +printf 'GET /status.cgi HTTP/1.0\r\n\r\n' | $HTTPD_CGI 2>&1 | d | grep -q '^HTTP/1.0 300 wat#%.*.null. 300 6' && pass || fail + +title "Status bug" +printf 'GET /status.cgi/empty HTTP/1.0\r\n\r\n' | $HTTPD_CGI 2>/dev/null | d | grep -q '^HTTP/1.0 500 ' && pass || fail + +title "No status" +printf 'GET /status.cgi/nostat HTTP/1.0\r\n\r\n' | $HTTPD_CGI 2>/dev/null | d | grep -q '^HTTP/1.0 500 ' && pass || fail H "Timeouts"