summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorStefan Fritsch <sf@sfritsch.de>2011-12-27 19:42:33 +0100
committerStefan Fritsch <sf@sfritsch.de>2011-12-27 19:42:33 +0100
commitad14e19ad0400e289b06fb7728aea815e6ed49be (patch)
treebd29489cafb04b303940169ae7b00c1171a5a34c /server
parent02a0e3b89d2ea1b984365e692c910668d75c6dcd (diff)
downloadapache2-ad14e19ad0400e289b06fb7728aea815e6ed49be.tar.gz
Upstream tarball 2.2.12upstream/2.2.12
Diffstat (limited to 'server')
-rw-r--r--server/config.c6
-rw-r--r--server/core.c35
-rw-r--r--server/core_filters.c11
-rw-r--r--server/gen_test_char.c20
-rw-r--r--server/listen.c6
-rw-r--r--server/log.c59
-rw-r--r--server/mpm/prefork/prefork.c40
-rw-r--r--server/protocol.c7
-rw-r--r--server/request.c58
-rw-r--r--server/util.c14
-rw-r--r--server/util_script.c11
-rw-r--r--server/vhost.c2
12 files changed, 219 insertions, 50 deletions
diff --git a/server/config.c b/server/config.c
index 9747c284..101d0e4e 100644
--- a/server/config.c
+++ b/server/config.c
@@ -1510,7 +1510,7 @@ static const char *process_command_config(server_rec *s,
parms.temp_pool = ptemp;
parms.server = s;
parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
- parms.override_opts = OPT_ALL | OPT_INCNOEXEC | OPT_SYM_OWNER | OPT_MULTI;
+ parms.override_opts = OPT_ALL | OPT_SYM_OWNER | OPT_MULTI;
parms.config_file = ap_pcfg_open_custom(p, "-c/-C directives",
&arr_parms, NULL,
@@ -1617,7 +1617,7 @@ static const char *process_resource_config_nofnmatch(server_rec *s,
parms.temp_pool = ptemp;
parms.server = s;
parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
- parms.override_opts = OPT_ALL | OPT_INCNOEXEC | OPT_SYM_OWNER | OPT_MULTI;
+ parms.override_opts = OPT_ALL | OPT_SYM_OWNER | OPT_MULTI;
rv = ap_pcfg_openfile(&cfp, p, fname);
if (rv != APR_SUCCESS) {
@@ -1755,7 +1755,7 @@ AP_DECLARE(int) ap_process_config_tree(server_rec *s,
parms.temp_pool = ptemp;
parms.server = s;
parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
- parms.override_opts = OPT_ALL | OPT_INCNOEXEC | OPT_SYM_OWNER | OPT_MULTI;
+ parms.override_opts = OPT_ALL | OPT_SYM_OWNER | OPT_MULTI;
parms.limited = -1;
errmsg = ap_walk_config(conftree, &parms, s->lookup_defaults);
diff --git a/server/core.c b/server/core.c
index 3b1b01b7..ab437197 100644
--- a/server/core.c
+++ b/server/core.c
@@ -108,8 +108,7 @@ static void *create_core_dir_config(apr_pool_t *a, char *dir)
conf->opts = dir ? OPT_UNSET : OPT_UNSET|OPT_ALL;
conf->opts_add = conf->opts_remove = OPT_NONE;
conf->override = dir ? OR_UNSET : OR_UNSET|OR_ALL;
- conf->override_opts = OPT_UNSET | OPT_ALL | OPT_INCNOEXEC | OPT_SYM_OWNER
- | OPT_MULTI;
+ conf->override_opts = OPT_UNSET | OPT_ALL | OPT_SYM_OWNER | OPT_MULTI;
conf->content_md5 = 2;
conf->accept_path_info = 3;
@@ -242,8 +241,15 @@ static void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv)
conf->opts_remove = (conf->opts_remove & ~new->opts_add)
| new->opts_remove;
conf->opts = (conf->opts & ~conf->opts_remove) | conf->opts_add;
- if ((base->opts & OPT_INCNOEXEC) && (new->opts & OPT_INCLUDES)) {
- conf->opts = (conf->opts & ~OPT_INCNOEXEC) | OPT_INCLUDES;
+
+ /* If Includes was enabled with exec in the base config, but
+ * was enabled without exec in the new config, then disable
+ * exec in the merged set. */
+ if (((base->opts & (OPT_INCLUDES|OPT_INC_WITH_EXEC))
+ == (OPT_INCLUDES|OPT_INC_WITH_EXEC))
+ && ((new->opts & (OPT_INCLUDES|OPT_INC_WITH_EXEC))
+ == OPT_INCLUDES)) {
+ conf->opts &= ~OPT_INC_WITH_EXEC;
}
}
else {
@@ -655,7 +661,16 @@ AP_DECLARE(int) ap_allow_options(request_rec *r)
core_dir_config *conf =
(core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
- return conf->opts;
+ /* Per comment in http_core.h - the OPT_INC_WITH_EXEC bit is
+ * inverted, such that the exposed semantics match that of
+ * OPT_INCNOEXEC; i.e., the bit is only enabled if exec= is *not*
+ * permitted. */
+ if (conf->opts & OPT_INCLUDES) {
+ return conf->opts ^ OPT_INC_WITH_EXEC;
+ }
+ else {
+ return conf->opts;
+ }
}
AP_DECLARE(int) ap_allow_overrides(request_rec *r)
@@ -1304,10 +1319,12 @@ static const char *set_allow_opts(cmd_parms *cmd, allow_options_t *opts,
opt = OPT_INDEXES;
}
else if (!strcasecmp(w, "Includes")) {
- opt = OPT_INCLUDES;
+ /* If Includes is permitted, both Includes and
+ * IncludesNOEXEC may be changed. */
+ opt = (OPT_INCLUDES | OPT_INC_WITH_EXEC);
}
else if (!strcasecmp(w, "IncludesNOEXEC")) {
- opt = (OPT_INCLUDES | OPT_INCNOEXEC);
+ opt = OPT_INCLUDES;
}
else if (!strcasecmp(w, "FollowSymLinks")) {
opt = OPT_SYM_LINKS;
@@ -1428,10 +1445,10 @@ static const char *set_options(cmd_parms *cmd, void *d_, const char *l)
opt = OPT_INDEXES;
}
else if (!strcasecmp(w, "Includes")) {
- opt = OPT_INCLUDES;
+ opt = (OPT_INCLUDES | OPT_INC_WITH_EXEC);
}
else if (!strcasecmp(w, "IncludesNOEXEC")) {
- opt = (OPT_INCLUDES | OPT_INCNOEXEC);
+ opt = OPT_INCLUDES;
}
else if (!strcasecmp(w, "FollowSymLinks")) {
opt = OPT_SYM_LINKS;
diff --git a/server/core_filters.c b/server/core_filters.c
index acbe1901..c2ebe981 100644
--- a/server/core_filters.c
+++ b/server/core_filters.c
@@ -542,6 +542,12 @@ apr_status_t ap_core_output_filter(ap_filter_t *f, apr_bucket_brigade *b)
apr_read_type_e eblock = APR_NONBLOCK_READ;
apr_pool_t *input_pool = b->p;
+ /* Fail quickly if the connection has already been aborted. */
+ if (c->aborted) {
+ apr_brigade_cleanup(b);
+ return APR_ECONNABORTED;
+ }
+
if (ctx == NULL) {
ctx = apr_pcalloc(c->pool, sizeof(*ctx));
net->out_ctx = ctx;
@@ -909,12 +915,9 @@ apr_status_t ap_core_output_filter(ap_filter_t *f, apr_bucket_brigade *b)
/* No need to check for SUCCESS, we did that above. */
if (!APR_STATUS_IS_EAGAIN(rv)) {
c->aborted = 1;
+ return APR_ECONNABORTED;
}
- /* The client has aborted, but the request was successful. We
- * will report success, and leave it to the access and error
- * logs to note that the connection was aborted.
- */
return APR_SUCCESS;
}
diff --git a/server/gen_test_char.c b/server/gen_test_char.c
index 59947d58..3835102d 100644
--- a/server/gen_test_char.c
+++ b/server/gen_test_char.c
@@ -14,9 +14,27 @@
* limitations under the License.
*/
+#ifdef CROSS_COMPILE
+
+#define apr_isalnum(c) (isalnum(((unsigned char)(c))))
+#define apr_isalpha(c) (isalpha(((unsigned char)(c))))
+#define apr_iscntrl(c) (iscntrl(((unsigned char)(c))))
+#define apr_isprint(c) (isprint(((unsigned char)(c))))
+#include <ctype.h>
+#define APR_HAVE_STDIO_H 1
+#define APR_HAVE_STRING_H 1
+
+#else
+
#include "apr.h"
#include "apr_lib.h"
+#if defined(WIN32) || defined(OS2)
+#define WANT_WIN32_OS2
+#endif
+
+#endif
+
#if APR_HAVE_STDIO_H
#include <stdio.h>
#endif
@@ -62,7 +80,7 @@ int main(int argc, char *argv[])
printf("\n ");
/* escape_shell_cmd */
-#if defined(WIN32) || defined(OS2)
+#if defined(WANT_WIN32_OS2)
/* Win32/OS2 have many of the same vulnerable characters
* as Unix sh, plus the carriage return and percent char.
* The proper escaping of these characters varies from unix
diff --git a/server/listen.c b/server/listen.c
index d1e6da8e..b284d83b 100644
--- a/server/listen.c
+++ b/server/listen.c
@@ -633,7 +633,11 @@ AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy,
}
if (argc != 2) {
- proto = "http";
+ if (port == 443) {
+ proto = "https";
+ } else {
+ proto = "http";
+ }
}
else {
proto = apr_pstrdup(cmd->pool, argv[1]);
diff --git a/server/log.c b/server/log.c
index 3aa20b0b..42a77290 100644
--- a/server/log.c
+++ b/server/log.c
@@ -265,7 +265,8 @@ static void log_child_errfn(apr_pool_t *pool, apr_status_t err,
* stderr for the child will be the same as the stdout of the parent.
* Otherwise the child will inherit the stderr from the parent. */
static int log_child(apr_pool_t *p, const char *progname,
- apr_file_t **fpin, int dummy_stderr)
+ apr_file_t **fpin, apr_cmdtype_e cmdtype,
+ int dummy_stderr)
{
/* Child process code for 'ErrorLog "|..."';
* may want a common framework for this, since I expect it will
@@ -277,8 +278,7 @@ static int log_child(apr_pool_t *p, const char *progname,
apr_file_t *outfile, *errfile;
if (((rc = apr_procattr_create(&procattr, p)) == APR_SUCCESS)
- && ((rc = apr_procattr_cmdtype_set(procattr,
- APR_SHELLCMD_ENV)) == APR_SUCCESS)
+ && ((rc = apr_procattr_cmdtype_set(procattr, cmdtype)) == APR_SUCCESS)
&& ((rc = apr_procattr_io_set(procattr,
APR_FULL_BLOCK,
APR_NO_PIPE,
@@ -325,12 +325,26 @@ static int open_error_log(server_rec *s, int is_main, apr_pool_t *p)
if (*s->error_fname == '|') {
apr_file_t *dummy = NULL;
+ apr_cmdtype_e cmdtype = APR_SHELLCMD_ENV;
+ fname = s->error_fname + 1;
+ /* In 2.4 favor PROGRAM_ENV, accept "||prog" syntax for compatibility
+ * and "|$cmd" to override the default.
+ * Any 2.2 backport would continue to favor SHELLCMD_ENV so there
+ * accept "||prog" to override, and "|$cmd" to ease conversion.
+ */
+ if (*fname == '|') {
+ cmdtype = APR_PROGRAM_ENV;
+ ++fname;
+ }
+ if (*fname == '$')
+ ++fname;
+
/* Spawn a new child logger. If this is the main server_rec,
* the new child must use a dummy stderr since the current
* stderr might be a pipe to the old logger. Otherwise, the
* child inherits the parents stderr. */
- rc = log_child(p, s->error_fname + 1, &dummy, is_main);
+ rc = log_child(p, fname, &dummy, cmdtype, is_main);
if (rc != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_STARTUP, rc, NULL,
"Couldn't start ErrorLog process");
@@ -883,12 +897,12 @@ static apr_status_t piped_log_spawn(piped_log *pl)
apr_status_t status;
if (((status = apr_procattr_create(&procattr, pl->p)) != APR_SUCCESS) ||
- ((status = apr_procattr_cmdtype_set(procattr,
- APR_SHELLCMD_ENV)) != APR_SUCCESS) ||
+ ((status = apr_procattr_cmdtype_set(procattr, pl->cmdtype))
+ != APR_SUCCESS) ||
((status = apr_procattr_child_in_set(procattr,
ap_piped_log_read_fd(pl),
ap_piped_log_write_fd(pl)))
- != APR_SUCCESS) ||
+ != APR_SUCCESS) ||
((status = apr_procattr_child_errfn_set(procattr, log_child_errfn))
!= APR_SUCCESS) ||
((status = apr_procattr_error_check_set(procattr, 1)) != APR_SUCCESS)) {
@@ -1012,7 +1026,9 @@ static apr_status_t piped_log_cleanup(void *data)
}
-AP_DECLARE(piped_log *) ap_open_piped_log(apr_pool_t *p, const char *program)
+AP_DECLARE(piped_log *) ap_open_piped_log_ex(apr_pool_t *p,
+ const char *program,
+ apr_cmdtype_e cmdtype)
{
piped_log *pl;
@@ -1020,6 +1036,7 @@ AP_DECLARE(piped_log *) ap_open_piped_log(apr_pool_t *p, const char *program)
pl->p = p;
pl->program = apr_pstrdup(p, program);
pl->pid = NULL;
+ pl->cmdtype = cmdtype;
if (apr_file_pipe_create(&ap_piped_log_read_fd(pl),
&ap_piped_log_write_fd(pl), p) != APR_SUCCESS) {
return NULL;
@@ -1045,13 +1062,15 @@ static apr_status_t piped_log_cleanup(void *data)
return APR_SUCCESS;
}
-AP_DECLARE(piped_log *) ap_open_piped_log(apr_pool_t *p, const char *program)
+AP_DECLARE(piped_log *) ap_open_piped_log_ex(apr_pool_t *p,
+ const char *program,
+ apr_cmdtype_e cmdtype)
{
piped_log *pl;
apr_file_t *dummy = NULL;
int rc;
- rc = log_child(p, program, &dummy, 0);
+ rc = log_child(p, program, &dummy, cmdtype, 0);
if (rc != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_STARTUP, rc, NULL,
"Couldn't start piped log process");
@@ -1069,6 +1088,26 @@ AP_DECLARE(piped_log *) ap_open_piped_log(apr_pool_t *p, const char *program)
#endif
+AP_DECLARE(piped_log *) ap_open_piped_log(apr_pool_t *p,
+ const char *program)
+{
+ apr_cmdtype_e cmdtype = APR_SHELLCMD_ENV;
+
+ /* In 2.4 favor PROGRAM_ENV, accept "||prog" syntax for compatibility
+ * and "|$cmd" to override the default.
+ * Any 2.2 backport would continue to favor SHELLCMD_ENV so there
+ * accept "||prog" to override, and "|$cmd" to ease conversion.
+ */
+ if (*program == '|') {
+ cmdtype = APR_PROGRAM_ENV;
+ ++program;
+ }
+ if (*program == '$')
+ ++program;
+
+ return ap_open_piped_log_ex(p, program, cmdtype);
+}
+
AP_DECLARE(void) ap_close_piped_log(piped_log *pl)
{
apr_pool_cleanup_run(pl->p, pl, piped_log_cleanup);
diff --git a/server/mpm/prefork/prefork.c b/server/mpm/prefork/prefork.c
index 3849c222..28b60573 100644
--- a/server/mpm/prefork/prefork.c
+++ b/server/mpm/prefork/prefork.c
@@ -517,8 +517,12 @@ static void child_main(int child_num_arg)
(void) ap_update_child_status(sbh, SERVER_READY, (request_rec *) NULL);
/* Set up the pollfd array */
- /* ### check the status */
- (void) apr_pollset_create(&pollset, num_listensocks, pchild, 0);
+ status = apr_pollset_create(&pollset, num_listensocks, pchild, 0);
+ if (status != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, status, ap_server_conf,
+ "Couldn't create pollset in child; check system or user limits");
+ clean_child_exit(APEXIT_CHILDSICK); /* assume temporary resource issue */
+ }
for (lr = ap_listeners, i = num_listensocks; i--; lr = lr->next) {
apr_pollfd_t pfd = { 0 };
@@ -573,19 +577,27 @@ static void child_main(int child_num_arg)
apr_int32_t numdesc;
const apr_pollfd_t *pdesc;
- /* timeout == -1 == wait forever */
- status = apr_pollset_poll(pollset, -1, &numdesc, &pdesc);
+ /* check for termination first so we don't sleep for a while in
+ * poll if already signalled
+ */
+ if (one_process && shutdown_pending) {
+ SAFE_ACCEPT(accept_mutex_off());
+ return;
+ }
+ else if (die_now) {
+ /* In graceful stop/restart; drop the mutex
+ * and terminate the child. */
+ SAFE_ACCEPT(accept_mutex_off());
+ clean_child_exit(0);
+ }
+ /* timeout == 10 seconds to avoid a hang at graceful restart/stop
+ * caused by the closing of sockets by the signal handler
+ */
+ status = apr_pollset_poll(pollset, apr_time_from_sec(10),
+ &numdesc, &pdesc);
if (status != APR_SUCCESS) {
- if (APR_STATUS_IS_EINTR(status)) {
- if (one_process && shutdown_pending) {
- return;
- }
- else if (die_now) {
- /* In graceful stop/restart; drop the mutex
- * and terminate the child. */
- SAFE_ACCEPT(accept_mutex_off());
- clean_child_exit(0);
- }
+ if (APR_STATUS_IS_TIMEUP(status) ||
+ APR_STATUS_IS_EINTR(status)) {
continue;
}
/* Single Unix documents select as returning errnos
diff --git a/server/protocol.c b/server/protocol.c
index e5b2e030..23ef080f 100644
--- a/server/protocol.c
+++ b/server/protocol.c
@@ -1643,6 +1643,7 @@ static int send_header(void *data, const char *key, const char *val)
AP_DECLARE(void) ap_send_interim_response(request_rec *r, int send_headers)
{
hdr_ptr x;
+ char *status_line = NULL;
if (r->proto_num < 1001) {
/* don't send interim response to HTTP/1.0 Client */
@@ -1654,9 +1655,13 @@ AP_DECLARE(void) ap_send_interim_response(request_rec *r, int send_headers)
return;
}
+ status_line = apr_pstrcat(r->pool, AP_SERVER_PROTOCOL, " ", r->status_line, CRLF, NULL);
+ ap_xlate_proto_to_ascii(status_line, strlen(status_line));
+
x.f = r->connection->output_filters;
x.bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
- ap_fputstrs(x.f, x.bb, AP_SERVER_PROTOCOL, " ", r->status_line, CRLF, NULL);
+
+ ap_fputs(x.f, x.bb, status_line);
if (send_headers) {
apr_table_do(send_header, &x, r->headers_out, NULL);
apr_table_clear(r->headers_out);
diff --git a/server/request.c b/server/request.c
index fe4026a3..6ca30f92 100644
--- a/server/request.c
+++ b/server/request.c
@@ -558,17 +558,71 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r)
&& (!r->path_info || !*r->path_info)))
&& (cache->dir_conf_tested == sec_ent)
&& (strcmp(entry_dir, cache->cached) == 0)) {
+
+ int familiar = 0;
+
/* Well this looks really familiar! If our end-result (per_dir_result)
* didn't change, we have absolutely nothing to do :)
* Otherwise (as is the case with most dir_merged/file_merged requests)
* we must merge our dir_conf_merged onto this new r->per_dir_config.
*/
if (r->per_dir_config == cache->per_dir_result) {
- return OK;
+ familiar = 1;
}
- if (r->per_dir_config == cache->dir_conf_merged) {
+ else if (r->per_dir_config == cache->dir_conf_merged) {
r->per_dir_config = cache->per_dir_result;
+ familiar = 1;
+ }
+ if (familiar) {
+ apr_finfo_t thisinfo;
+ int res;
+ allow_options_t opts;
+ core_dir_config *this_dir;
+
+ this_dir = ap_get_module_config(r->per_dir_config, &core_module);
+ opts = this_dir->opts;
+ /*
+ * If Symlinks are allowed in general we do not need the following
+ * check.
+ */
+ if (!(opts & OPT_SYM_LINKS)) {
+ rv = apr_stat(&thisinfo, r->filename,
+ APR_FINFO_MIN | APR_FINFO_NAME | APR_FINFO_LINK,
+ r->pool);
+ /*
+ * APR_INCOMPLETE is as fine as result as APR_SUCCESS as we
+ * have added APR_FINFO_NAME to the wanted parameter of
+ * apr_stat above. On Unix platforms this means that apr_stat
+ * is always going to return APR_INCOMPLETE in the case that
+ * the call to the native stat / lstat did not fail.
+ */
+ if ((rv != APR_INCOMPLETE) && (rv != APR_SUCCESS)) {
+ /*
+ * This should never happen, because we did a stat on the
+ * same file, resolving a possible symlink several lines
+ * above. Therefore do not make a detailed analysis of rv
+ * in this case for the reason of the failure, just bail out
+ * with a HTTP_FORBIDDEN in case we hit a race condition
+ * here.
+ */
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ "access to %s failed; stat of '%s' failed.",
+ r->uri, r->filename);
+ return r->status = HTTP_FORBIDDEN;
+ }
+ if (thisinfo.filetype == APR_LNK) {
+ /* Is this a possibly acceptable symlink? */
+ if ((res = resolve_symlink(r->filename, &thisinfo,
+ opts, r->pool)) != OK) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "Symbolic link not allowed "
+ "or link target not accessible: %s",
+ r->filename);
+ return r->status = res;
+ }
+ }
+ }
return OK;
}
diff --git a/server/util.c b/server/util.c
index 3c927c23..e16b8eb2 100644
--- a/server/util.c
+++ b/server/util.c
@@ -1737,7 +1737,7 @@ AP_DECLARE(char *) ap_os_escape_path(apr_pool_t *p, const char *path, int partia
/* ap_escape_uri is now a macro for os_escape_path */
-AP_DECLARE(char *) ap_escape_html(apr_pool_t *p, const char *s)
+AP_DECLARE(char *) ap_escape_html2(apr_pool_t *p, const char *s, int toasc)
{
int i, j;
char *x;
@@ -1750,6 +1750,8 @@ AP_DECLARE(char *) ap_escape_html(apr_pool_t *p, const char *s)
j += 4;
else if (s[i] == '"')
j += 5;
+ else if (toasc && !apr_isascii(s[i]))
+ j += 5;
if (j == 0)
return apr_pstrmemdup(p, s, i);
@@ -1772,13 +1774,21 @@ AP_DECLARE(char *) ap_escape_html(apr_pool_t *p, const char *s)
memcpy(&x[j], "&quot;", 6);
j += 5;
}
+ else if (toasc && !apr_isascii(s[i])) {
+ char *esc = apr_psprintf(p, "&#%3.3d;", (unsigned char)s[i]);
+ memcpy(&x[j], esc, 6);
+ j += 5;
+ }
else
x[j] = s[i];
x[j] = '\0';
return x;
}
-
+AP_DECLARE(char *) ap_escape_html(apr_pool_t *p, const char *s)
+{
+ return ap_escape_html2(p, s, 0);
+}
AP_DECLARE(char *) ap_escape_logitem(apr_pool_t *p, const char *str)
{
char *ret;
diff --git a/server/util_script.c b/server/util_script.c
index 09c8dd41..6d6f3f4a 100644
--- a/server/util_script.c
+++ b/server/util_script.c
@@ -430,12 +430,19 @@ AP_DECLARE(int) ap_scan_script_header_err_core(request_rec *r, char *buffer,
while (1) {
- if ((*getsfunc) (w, MAX_STRING_LEN - 1, getsfunc_data) == 0) {
+ int rv = (*getsfunc) (w, MAX_STRING_LEN - 1, getsfunc_data);
+ if (rv == 0) {
ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_TOCLIENT, 0, r,
"Premature end of script headers: %s",
apr_filepath_name_get(r->filename));
return HTTP_INTERNAL_SERVER_ERROR;
}
+ else if (rv == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_TOCLIENT, 0, r,
+ "Script timed out before returning headers: %s",
+ apr_filepath_name_get(r->filename));
+ return HTTP_GATEWAY_TIME_OUT;
+ }
/* Delete terminal (CR?)LF */
@@ -629,7 +636,7 @@ static int getsfunc_BRIGADE(char *buf, int len, void *arg)
rv = apr_bucket_read(e, &bucket_data, &bucket_data_len,
APR_BLOCK_READ);
if (rv != APR_SUCCESS || (bucket_data_len == 0)) {
- return 0;
+ return APR_STATUS_IS_TIMEUP(rv) ? -1 : 0;
}
src = bucket_data;
src_end = bucket_data + bucket_data_len;
diff --git a/server/vhost.c b/server/vhost.c
index d7a0a07e..5b79fea5 100644
--- a/server/vhost.c
+++ b/server/vhost.c
@@ -677,7 +677,7 @@ AP_DECLARE(void) ap_fini_vhost_config(apr_pool_t *p, server_rec *main_s)
#endif
if (ap_exists_config_define("DUMP_VHOSTS")) {
apr_file_t *thefile = NULL;
- apr_file_open_stderr(&thefile, p);
+ apr_file_open_stdout(&thefile, p);
dump_vhost_config(thefile);
}
}