summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorStefan Fritsch <sf@sfritsch.de>2014-03-29 21:56:19 +0100
committerStefan Fritsch <sf@sfritsch.de>2014-03-29 21:56:45 +0100
commit2a463b3cd73c32ee9dcd508248d0194923f435f4 (patch)
tree2ff478255a77a55031056790918b6f983bb7b20a /server
parent86d5cc79d9d6750da8771fdb0c9ab22c19b8ad45 (diff)
downloadapache2-2a463b3cd73c32ee9dcd508248d0194923f435f4.tar.gz
Imported Upstream version 2.4.9upstream/2.4.9
Diffstat (limited to 'server')
-rw-r--r--server/core.c16
-rw-r--r--server/log.c8
-rw-r--r--server/mpm/event/event.c14
-rw-r--r--server/mpm/event/fdqueue.c47
-rw-r--r--server/mpm/winnt/child.c9
-rw-r--r--server/mpm_unix.c5
-rw-r--r--server/protocol.c41
-rw-r--r--server/request.c122
-rw-r--r--server/util.c20
-rw-r--r--server/util_ebcdic.c2
-rw-r--r--server/util_pcre.c42
-rw-r--r--server/util_regex.c3
12 files changed, 254 insertions, 75 deletions
diff --git a/server/core.c b/server/core.c
index 936bf47f..da895ab0 100644
--- a/server/core.c
+++ b/server/core.c
@@ -209,6 +209,7 @@ static void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv)
conf->d_is_fnmatch = new->d_is_fnmatch;
conf->d_components = new->d_components;
conf->r = new->r;
+ conf->refs = new->refs;
conf->condition = new->condition;
if (new->opts & OPT_UNSET) {
@@ -2159,6 +2160,11 @@ static const char *dirsection(cmd_parms *cmd, void *mconfig, const char *arg)
conf->d = cmd->path;
conf->d_is_fnmatch = (apr_fnmatch_test(conf->d) != 0);
+ if (r) {
+ conf->refs = apr_array_make(cmd->pool, 8, sizeof(char *));
+ ap_regname(r, conf->refs, AP_REG_MATCH, 1);
+ }
+
/* Make this explicit - the "/" root has 0 elements, that is, we
* will always merge it, and it will always sort and merge first.
* All others are sorted and tested by the number of slashes.
@@ -2235,6 +2241,11 @@ static const char *urlsection(cmd_parms *cmd, void *mconfig, const char *arg)
conf->d_is_fnmatch = apr_fnmatch_test(conf->d) != 0;
conf->r = r;
+ if (r) {
+ conf->refs = apr_array_make(cmd->pool, 8, sizeof(char *));
+ ap_regname(r, conf->refs, AP_REG_MATCH, 1);
+ }
+
ap_add_per_url_conf(cmd->server, new_url_conf);
if (*arg != '\0') {
@@ -2317,6 +2328,11 @@ static const char *filesection(cmd_parms *cmd, void *mconfig, const char *arg)
conf->d_is_fnmatch = apr_fnmatch_test(conf->d) != 0;
conf->r = r;
+ if (r) {
+ conf->refs = apr_array_make(cmd->pool, 8, sizeof(char *));
+ ap_regname(r, conf->refs, AP_REG_MATCH, 1);
+ }
+
ap_add_file_conf(cmd->pool, (core_dir_config *)mconfig, new_file_conf);
if (*arg != '\0') {
diff --git a/server/log.c b/server/log.c
index bcfdcdb6..9a15d24d 100644
--- a/server/log.c
+++ b/server/log.c
@@ -331,10 +331,8 @@ static int log_child(apr_pool_t *p, const char *progname,
&& ((rc = apr_procattr_child_errfn_set(procattr, log_child_errfn))
== APR_SUCCESS)) {
char **args;
- const char *pname;
apr_tokenize_to_argv(progname, &args, p);
- pname = apr_pstrdup(p, args[0]);
procnew = (apr_proc_t *)apr_pcalloc(p, sizeof(*procnew));
if (dummy_stderr) {
@@ -342,7 +340,7 @@ static int log_child(apr_pool_t *p, const char *progname,
rc = apr_procattr_child_err_set(procattr, errfile, NULL);
}
- rc = apr_proc_create(procnew, pname, (const char * const *)args,
+ rc = apr_proc_create(procnew, args[0], (const char * const *)args,
NULL, procattr, p);
if (rc == APR_SUCCESS) {
@@ -1566,12 +1564,10 @@ static apr_status_t piped_log_spawn(piped_log *pl)
}
else {
char **args;
- const char *pname;
apr_tokenize_to_argv(pl->program, &args, pl->p);
- pname = apr_pstrdup(pl->p, args[0]);
procnew = apr_pcalloc(pl->p, sizeof(apr_proc_t));
- status = apr_proc_create(procnew, pname, (const char * const *) args,
+ status = apr_proc_create(procnew, args[0], (const char * const *) args,
NULL, procattr, pl->p);
if (status == APR_SUCCESS) {
diff --git a/server/mpm/event/event.c b/server/mpm/event/event.c
index 306837db..7a95498e 100644
--- a/server/mpm/event/event.c
+++ b/server/mpm/event/event.c
@@ -2866,16 +2866,14 @@ static int event_pre_config(apr_pool_t * pconf, apr_pool_t * plog,
}
++retained->module_loads;
if (retained->module_loads == 2) {
- int i;
- static apr_uint32_t foo = 0;
+ /* test for correct operation of fdqueue */
+ static apr_uint32_t foo1, foo2;
- apr_atomic_inc32(&foo);
- apr_atomic_dec32(&foo);
- apr_atomic_dec32(&foo);
- i = apr_atomic_dec32(&foo);
- if (i >= 0) {
+ apr_atomic_set32(&foo1, 100);
+ foo2 = apr_atomic_add32(&foo1, -10);
+ if (foo2 != 100 || foo1 != 90) {
ap_log_error(APLOG_MARK, APLOG_CRIT, 0, NULL, APLOGNO(02405)
- "atomics not working as expected");
+ "atomics not working as expected - add32 of negative number");
return HTTP_INTERNAL_SERVER_ERROR;
}
rv = apr_pollset_create(&event_pollset, 1, plog,
diff --git a/server/mpm/event/fdqueue.c b/server/mpm/event/fdqueue.c
index 028bca10..2fa7e1e5 100644
--- a/server/mpm/event/fdqueue.c
+++ b/server/mpm/event/fdqueue.c
@@ -17,18 +17,20 @@
#include "fdqueue.h"
#include "apr_atomic.h"
-typedef struct recycled_pool
+static apr_uint32_t zero_pt = APR_UINT32_MAX/2;
+
+struct recycled_pool
{
apr_pool_t *pool;
struct recycled_pool *next;
-} recycled_pool;
+};
struct fd_queue_info_t
{
- apr_int32_t idlers; /**
- * 0 or positive: number of idle worker threads
- * negative: number of threads blocked waiting
- * for an idle worker
+ apr_uint32_t idlers; /**
+ * >= zero_pt: number of idle worker threads
+ * < zero_pt: number of threads blocked waiting
+ * for an idle worker
*/
apr_thread_mutex_t *idlers_mutex;
apr_thread_cond_t *wait_for_idler;
@@ -36,7 +38,7 @@ struct fd_queue_info_t
int max_idlers;
int max_recycled_pools;
apr_uint32_t recycled_pools_count;
- recycled_pool *recycled_pools;
+ struct recycled_pool *recycled_pools;
};
static apr_status_t queue_info_cleanup(void *data_)
@@ -82,6 +84,7 @@ apr_status_t ap_queue_info_create(fd_queue_info_t ** queue_info,
qi->recycled_pools = NULL;
qi->max_recycled_pools = max_recycled_pools;
qi->max_idlers = max_idlers;
+ qi->idlers = zero_pt;
apr_pool_cleanup_register(pool, qi, queue_info_cleanup,
apr_pool_cleanup_null);
@@ -94,17 +97,12 @@ apr_status_t ap_queue_info_set_idle(fd_queue_info_t * queue_info,
apr_pool_t * pool_to_recycle)
{
apr_status_t rv;
- int prev_idlers;
+ apr_int32_t prev_idlers;
ap_push_pool(queue_info, pool_to_recycle);
/* Atomically increment the count of idle workers */
- /*
- * TODO: The atomics expect unsigned whereas we're using signed.
- * Need to double check that they work as expected or else
- * rework how we determine blocked.
- */
- prev_idlers = apr_atomic_inc32((apr_uint32_t *)&(queue_info->idlers));
+ prev_idlers = apr_atomic_inc32(&(queue_info->idlers)) - zero_pt;
/* If other threads are waiting on a worker, wake one up */
if (prev_idlers < 0) {
@@ -129,10 +127,10 @@ apr_status_t ap_queue_info_set_idle(fd_queue_info_t * queue_info,
apr_status_t ap_queue_info_try_get_idler(fd_queue_info_t * queue_info)
{
- int prev_idlers;
- prev_idlers = apr_atomic_dec32((apr_uint32_t *)&(queue_info->idlers));
- if (prev_idlers <= 0) {
- apr_atomic_inc32((apr_uint32_t *)&(queue_info->idlers)); /* back out dec */
+ apr_int32_t new_idlers;
+ new_idlers = apr_atomic_add32(&(queue_info->idlers), -1) - zero_pt;
+ if (--new_idlers <= 0) {
+ apr_atomic_inc32(&(queue_info->idlers)); /* back out dec */
return APR_EAGAIN;
}
return APR_SUCCESS;
@@ -142,11 +140,11 @@ apr_status_t ap_queue_info_wait_for_idler(fd_queue_info_t * queue_info,
int *had_to_block)
{
apr_status_t rv;
- int prev_idlers;
+ apr_int32_t prev_idlers;
/* Atomically decrement the idle worker count, saving the old value */
/* See TODO in ap_queue_info_set_idle() */
- prev_idlers = apr_atomic_add32((apr_uint32_t *)&(queue_info->idlers), -1);
+ prev_idlers = apr_atomic_add32(&(queue_info->idlers), -1) - zero_pt;
/* Block if there weren't any idle workers */
if (prev_idlers <= 0) {
@@ -154,7 +152,7 @@ apr_status_t ap_queue_info_wait_for_idler(fd_queue_info_t * queue_info,
if (rv != APR_SUCCESS) {
AP_DEBUG_ASSERT(0);
/* See TODO in ap_queue_info_set_idle() */
- apr_atomic_inc32((apr_uint32_t *)&(queue_info->idlers)); /* back out dec */
+ apr_atomic_inc32(&(queue_info->idlers)); /* back out dec */
return rv;
}
/* Re-check the idle worker count to guard against a
@@ -173,10 +171,11 @@ apr_status_t ap_queue_info_wait_for_idler(fd_queue_info_t * queue_info,
* now non-negative, it's safe for this function to
* return immediately.
*
- * A negative value in queue_info->idlers tells how many
+ * A "negative value" (relative to zero_pt) in
+ * queue_info->idlers tells how many
* threads are waiting on an idle worker.
*/
- if (queue_info->idlers < 0) {
+ if (queue_info->idlers < zero_pt) {
*had_to_block = 1;
rv = apr_thread_cond_wait(queue_info->wait_for_idler,
queue_info->idlers_mutex);
@@ -207,7 +206,7 @@ apr_status_t ap_queue_info_wait_for_idler(fd_queue_info_t * queue_info,
apr_uint32_t ap_queue_info_get_idlers(fd_queue_info_t * queue_info)
{
apr_int32_t val;
- val = (apr_int32_t)apr_atomic_read32((apr_uint32_t *)&queue_info->idlers);
+ val = (apr_int32_t)apr_atomic_read32(&queue_info->idlers) - zero_pt;
if (val < 0)
return 0;
return val;
diff --git a/server/mpm/winnt/child.c b/server/mpm/winnt/child.c
index c9168b08..6879179f 100644
--- a/server/mpm/winnt/child.c
+++ b/server/mpm/winnt/child.c
@@ -878,12 +878,13 @@ static DWORD __stdcall worker_main(void *thread_num_val)
if (!c->aborted) {
ap_run_process_connection(c);
+ }
- apr_socket_opt_get(context->sock, APR_SO_DISCONNECTED,
- &disconnected);
+ apr_socket_opt_get(context->sock, APR_SO_DISCONNECTED, &disconnected);
- if (!disconnected) {
- context->accept_socket = INVALID_SOCKET;
+ if (!disconnected) {
+ context->accept_socket = INVALID_SOCKET;
+ if (!c->aborted) {
ap_lingering_close(c);
}
}
diff --git a/server/mpm_unix.c b/server/mpm_unix.c
index 063af725..0000cb66 100644
--- a/server/mpm_unix.c
+++ b/server/mpm_unix.c
@@ -742,7 +742,12 @@ void ap_mpm_pod_killpg(ap_pod_t *pod, int num)
* readers stranded (a number of them could be tied up for
* a while serving time-consuming requests)
*/
+ /* Recall: we only worry about IDLE child processes here */
for (i = 0; i < num && rv == APR_SUCCESS; i++) {
+ if (ap_scoreboard_image->servers[i][0].status != SERVER_READY ||
+ ap_scoreboard_image->servers[i][0].pid == 0) {
+ continue;
+ }
rv = dummy_connection(pod);
}
}
diff --git a/server/protocol.c b/server/protocol.c
index a0b32464..bf915a0a 100644
--- a/server/protocol.c
+++ b/server/protocol.c
@@ -997,6 +997,8 @@ request_rec *ap_read_request(conn_rec *conn)
}
if (!r->assbackwards) {
+ const char *tenc;
+
ap_get_mime_headers_core(r, tmp_bb);
if (r->status != HTTP_OK) {
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00567)
@@ -1008,12 +1010,34 @@ request_rec *ap_read_request(conn_rec *conn)
goto traceout;
}
- if (apr_table_get(r->headers_in, "Transfer-Encoding")
- && apr_table_get(r->headers_in, "Content-Length")) {
- /* 2616 section 4.4, point 3: "if both Transfer-Encoding
- * and Content-Length are received, the latter MUST be
- * ignored"; so unset it here to prevent any confusion
- * later. */
+ tenc = apr_table_get(r->headers_in, "Transfer-Encoding");
+ if (tenc) {
+ /* http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-23
+ * Section 3.3.3.3: "If a Transfer-Encoding header field is
+ * present in a request and the chunked transfer coding is not
+ * the final encoding ...; the server MUST respond with the 400
+ * (Bad Request) status code and then close the connection".
+ */
+ if (!(strcasecmp(tenc, "chunked") == 0 /* fast path */
+ || ap_find_last_token(r->pool, tenc, "chunked"))) {
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02539)
+ "client sent unknown Transfer-Encoding "
+ "(%s): %s", tenc, r->uri);
+ r->status = HTTP_BAD_REQUEST;
+ conn->keepalive = AP_CONN_CLOSE;
+ ap_send_error_response(r, 0);
+ ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
+ ap_run_log_transaction(r);
+ apr_brigade_destroy(tmp_bb);
+ goto traceout;
+ }
+
+ /* http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-23
+ * Section 3.3.3.3: "If a message is received with both a
+ * Transfer-Encoding and a Content-Length header field, the
+ * Transfer-Encoding overrides the Content-Length. ... A sender
+ * MUST remove the received Content-Length field".
+ */
apr_table_unset(r->headers_in, "Content-Length");
}
}
@@ -1557,7 +1581,8 @@ struct ap_vrprintf_data {
char *buff;
};
-static apr_status_t r_flush(apr_vformatter_buff_t *buff)
+/* Flush callback for apr_vformatter; returns -1 on error. */
+static int r_flush(apr_vformatter_buff_t *buff)
{
/* callback function passed to ap_vformatter to be called when
* vformatter needs to write into buff and buff.curpos > buff.endpos */
@@ -1578,7 +1603,7 @@ static apr_status_t r_flush(apr_vformatter_buff_t *buff)
vd->vbuff.curpos = vd->buff;
vd->vbuff.endpos = vd->buff + AP_IOBUFSIZE;
- return APR_SUCCESS;
+ return 0;
}
AP_DECLARE(int) ap_vrprintf(request_rec *r, const char *fmt, va_list va)
diff --git a/server/request.c b/server/request.c
index 1f4d9927..af0a697a 100644
--- a/server/request.c
+++ b/server/request.c
@@ -737,6 +737,7 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r)
apr_size_t buflen;
char *buf;
unsigned int seg, startseg;
+ apr_pool_t *rxpool = NULL;
/* Invariant: from the first time filename_len is set until
* it goes out of scope, filename_len==strlen(r->filename)
@@ -1192,6 +1193,10 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r)
*/
for (; sec_idx < num_sec; ++sec_idx) {
+ int nmatch = 0;
+ int i;
+ ap_regmatch_t *pmatch = NULL;
+
core_dir_config *entry_core;
entry_core = ap_get_core_module_config(sec_ent[sec_idx]);
@@ -1199,10 +1204,29 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r)
continue;
}
- if (ap_regexec(entry_core->r, r->filename, 0, NULL, 0)) {
+ if (entry_core->refs && entry_core->refs->nelts) {
+ if (!rxpool) {
+ apr_pool_create(&rxpool, r->pool);
+ }
+ nmatch = entry_core->refs->nelts;
+ pmatch = apr_palloc(rxpool, nmatch*sizeof(ap_regmatch_t));
+ }
+
+ if (ap_regexec(entry_core->r, r->filename, nmatch, pmatch, 0)) {
continue;
}
+ for (i = 0; i < nmatch; i++) {
+ if (pmatch[i].rm_so >= 0 && pmatch[i].rm_eo >= 0 &&
+ ((const char **)entry_core->refs->elts)[i]) {
+ apr_table_setn(r->subprocess_env,
+ ((const char **)entry_core->refs->elts)[i],
+ apr_pstrndup(r->pool,
+ r->filename + pmatch[i].rm_so,
+ pmatch[i].rm_eo - pmatch[i].rm_so));
+ }
+ }
+
/* If we haven't already continue'd above, we have a match.
*
* Calculate our full-context core opts & override.
@@ -1241,6 +1265,10 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r)
last_walk->merged = now_merged;
}
+ if (rxpool) {
+ apr_pool_destroy(rxpool);
+ }
+
/* Whoops - everything matched in sequence, but either the original
* walk found some additional matches (which we need to truncate), or
* this walk found some additional matches.
@@ -1378,6 +1406,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r)
int matches = cache->walked->nelts;
int cached_matches = matches;
walk_walked_t *last_walk = (walk_walked_t*)cache->walked->elts;
+ apr_pool_t *rxpool = NULL;
cached &= auth_internal_per_conf;
cache->cached = entry_uri;
@@ -1399,16 +1428,48 @@ AP_DECLARE(int) ap_location_walk(request_rec *r)
* not slash terminated, then this uri must be slash
* terminated (or at the end of the string) to match.
*/
- if (entry_core->r
- ? ap_regexec(entry_core->r, r->uri, 0, NULL, 0)
- : (entry_core->d_is_fnmatch
+ if (entry_core->r) {
+
+ int nmatch = 0;
+ int i;
+ ap_regmatch_t *pmatch = NULL;
+
+ if (entry_core->refs && entry_core->refs->nelts) {
+ if (!rxpool) {
+ apr_pool_create(&rxpool, r->pool);
+ }
+ nmatch = entry_core->refs->nelts;
+ pmatch = apr_palloc(rxpool, nmatch*sizeof(ap_regmatch_t));
+ }
+
+ if (ap_regexec(entry_core->r, r->uri, nmatch, pmatch, 0)) {
+ continue;
+ }
+
+ for (i = 0; i < nmatch; i++) {
+ if (pmatch[i].rm_so >= 0 && pmatch[i].rm_eo >= 0 &&
+ ((const char **)entry_core->refs->elts)[i]) {
+ apr_table_setn(r->subprocess_env,
+ ((const char **)entry_core->refs->elts)[i],
+ apr_pstrndup(r->pool,
+ r->uri + pmatch[i].rm_so,
+ pmatch[i].rm_eo - pmatch[i].rm_so));
+ }
+ }
+
+ }
+ else {
+
+ if ((entry_core->d_is_fnmatch
? apr_fnmatch(entry_core->d, cache->cached, APR_FNM_PATHNAME)
: (strncmp(entry_core->d, cache->cached, len)
|| (len > 0
&& entry_core->d[len - 1] != '/'
&& cache->cached[len] != '/'
&& cache->cached[len] != '\0')))) {
- continue;
+ continue;
+ }
+
}
/* If we merged this same section last time, reuse it
@@ -1443,6 +1504,10 @@ AP_DECLARE(int) ap_location_walk(request_rec *r)
last_walk->merged = now_merged;
}
+ if (rxpool) {
+ apr_pool_destroy(rxpool);
+ }
+
/* Whoops - everything matched in sequence, but either the original
* walk found some additional matches (which we need to truncate), or
* this walk found some additional matches.
@@ -1552,6 +1617,7 @@ AP_DECLARE(int) ap_file_walk(request_rec *r)
int matches = cache->walked->nelts;
int cached_matches = matches;
walk_walked_t *last_walk = (walk_walked_t*)cache->walked->elts;
+ apr_pool_t *rxpool = NULL;
cached &= auth_internal_per_conf;
cache->cached = test_file;
@@ -1564,12 +1630,42 @@ AP_DECLARE(int) ap_file_walk(request_rec *r)
core_dir_config *entry_core;
entry_core = ap_get_core_module_config(sec_ent[sec_idx]);
- if (entry_core->r
- ? ap_regexec(entry_core->r, cache->cached , 0, NULL, 0)
- : (entry_core->d_is_fnmatch
- ? apr_fnmatch(entry_core->d, cache->cached, APR_FNM_PATHNAME)
- : strcmp(entry_core->d, cache->cached))) {
- continue;
+ if (entry_core->r) {
+
+ int nmatch = 0;
+ int i;
+ ap_regmatch_t *pmatch = NULL;
+
+ if (entry_core->refs && entry_core->refs->nelts) {
+ if (!rxpool) {
+ apr_pool_create(&rxpool, r->pool);
+ }
+ nmatch = entry_core->refs->nelts;
+ pmatch = apr_palloc(rxpool, nmatch*sizeof(ap_regmatch_t));
+ }
+
+ if (ap_regexec(entry_core->r, cache->cached, nmatch, pmatch, 0)) {
+ continue;
+ }
+
+ for (i = 0; i < nmatch; i++) {
+ if (pmatch[i].rm_so >= 0 && pmatch[i].rm_eo >= 0 &&
+ ((const char **)entry_core->refs->elts)[i]) {
+ apr_table_setn(r->subprocess_env,
+ ((const char **)entry_core->refs->elts)[i],
+ apr_pstrndup(r->pool,
+ cache->cached + pmatch[i].rm_so,
+ pmatch[i].rm_eo - pmatch[i].rm_so));
+ }
+ }
+
+ }
+ else {
+ if ((entry_core->d_is_fnmatch
+ ? apr_fnmatch(entry_core->d, cache->cached, APR_FNM_PATHNAME)
+ : strcmp(entry_core->d, cache->cached))) {
+ continue;
+ }
}
/* If we merged this same section last time, reuse it
@@ -1604,6 +1700,10 @@ AP_DECLARE(int) ap_file_walk(request_rec *r)
last_walk->merged = now_merged;
}
+ if (rxpool) {
+ apr_pool_destroy(rxpool);
+ }
+
/* Whoops - everything matched in sequence, but either the original
* walk found some additional matches (which we need to truncate), or
* this walk found some additional matches.
diff --git a/server/util.c b/server/util.c
index e0ba5c28..2b603000 100644
--- a/server/util.c
+++ b/server/util.c
@@ -115,7 +115,7 @@ AP_DECLARE(char *) ap_field_noparam(apr_pool_t *p, const char *intype)
while ((semi > intype) && apr_isspace(semi[-1])) {
semi--;
}
- return apr_pstrndup(p, intype, semi - intype);
+ return apr_pstrmemdup(p, intype, semi - intype);
}
}
@@ -736,7 +736,7 @@ AP_DECLARE(char *) ap_getword_nulls(apr_pool_t *atrans, const char **line,
return res;
}
- res = apr_pstrndup(atrans, *line, pos - *line);
+ res = apr_pstrmemdup(atrans, *line, pos - *line);
++pos;
@@ -956,13 +956,15 @@ AP_DECLARE(apr_status_t) ap_cfg_getc(char *ch, ap_configfile_t *cfp)
AP_DECLARE(const char *) ap_pcfg_strerror(apr_pool_t *p, ap_configfile_t *cfp,
apr_status_t rc)
{
- char buf[MAX_STRING_LEN];
if (rc == APR_SUCCESS)
return NULL;
- return apr_psprintf(p, "Error reading %s at line %d: %s",
- cfp->name, cfp->line_number,
- rc == APR_ENOSPC ? "Line too long"
- : apr_strerror(rc, buf, sizeof(buf)));
+
+ if (rc == APR_ENOSPC)
+ return apr_psprintf(p, "Error reading %s at line %d: Line too long",
+ cfp->name, cfp->line_number);
+
+ return apr_psprintf(p, "Error reading %s at line %d: %pm",
+ cfp->name, cfp->line_number, &rc);
}
/* Read one line from open ap_configfile_t, strip LF, increase line number */
@@ -1461,7 +1463,6 @@ AP_DECLARE(char *) ap_get_token(apr_pool_t *p, const char **accept_line,
const char *ptr = *accept_line;
const char *tok_start;
char *token;
- int tok_len;
/* Find first non-white byte */
@@ -1482,8 +1483,7 @@ AP_DECLARE(char *) ap_get_token(apr_pool_t *p, const char **accept_line,
break;
}
- tok_len = ptr - tok_start;
- token = apr_pstrndup(p, tok_start, tok_len);
+ token = apr_pstrmemdup(p, tok_start, ptr - tok_start);
/* Advance accept_line pointer to the next non-white byte */
diff --git a/server/util_ebcdic.c b/server/util_ebcdic.c
index 1a8c0ba3..7faae794 100644
--- a/server/util_ebcdic.c
+++ b/server/util_ebcdic.c
@@ -102,7 +102,7 @@ int ap_rvputs_proto_in_ascii(request_rec *r, ...)
if (s == NULL)
break;
len = strlen(s);
- ascii_s = apr_pstrndup(r->pool, s, len);
+ ascii_s = apr_pstrmemdup(r->pool, s, len);
ap_xlate_proto_to_ascii(ascii_s, len);
if (ap_rputs(ascii_s, r) < 0)
return -1;
diff --git a/server/util_pcre.c b/server/util_pcre.c
index 1e83cad0..4d2adef2 100644
--- a/server/util_pcre.c
+++ b/server/util_pcre.c
@@ -45,6 +45,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "httpd.h"
#include "apr_strings.h"
+#include "apr_tables.h"
#include "pcre.h"
#define APR_WANT_STRFUNC
@@ -124,7 +125,7 @@ AP_DECLARE(int) ap_regcomp(ap_regex_t * preg, const char *pattern, int cflags)
const char *errorptr;
int erroffset;
int errcode = 0;
- int options = 0;
+ int options = PCRE_DUPNAMES;
if ((cflags & AP_REG_ICASE) != 0)
options |= PCRE_CASELESS;
@@ -256,4 +257,43 @@ AP_DECLARE(int) ap_regexec_len(const ap_regex_t *preg, const char *buff,
}
}
+AP_DECLARE(int) ap_regname(const ap_regex_t *preg,
+ apr_array_header_t *names, const char *prefix,
+ int upper)
+{
+ int namecount;
+ int nameentrysize;
+ int i;
+ char *nametable;
+
+ pcre_fullinfo((const pcre *)preg->re_pcre, NULL,
+ PCRE_INFO_NAMECOUNT, &namecount);
+ pcre_fullinfo((const pcre *)preg->re_pcre, NULL,
+ PCRE_INFO_NAMEENTRYSIZE, &nameentrysize);
+ pcre_fullinfo((const pcre *)preg->re_pcre, NULL,
+ PCRE_INFO_NAMETABLE, &nametable);
+
+ for (i = 0; i < namecount; i++) {
+ const char *offset = nametable + i * nameentrysize;
+ int capture = ((offset[0] << 8) + offset[1]);
+ while (names->nelts <= capture) {
+ apr_array_push(names);
+ }
+ if (upper || prefix) {
+ char *name = ((char **) names->elts)[capture] =
+ prefix ? apr_pstrcat(names->pool, prefix, offset + 2,
+ NULL) :
+ apr_pstrdup(names->pool, offset + 2);
+ if (upper) {
+ ap_str_toupper(name);
+ }
+ }
+ else {
+ ((const char **)names->elts)[capture] = offset + 2;
+ }
+ }
+
+ return namecount;
+}
+
/* End of pcreposix.c */
diff --git a/server/util_regex.c b/server/util_regex.c
index 73eccec7..81eac530 100644
--- a/server/util_regex.c
+++ b/server/util_regex.c
@@ -162,7 +162,6 @@ AP_DECLARE(int) ap_rxplus_exec(apr_pool_t *pool, ap_rxplus_t *rx,
remainder = pattern + startl + oldl;
if (rx->flags & AP_REG_MULTI) {
/* recurse to do any further matches */
- char *subs;
ret += ap_rxplus_exec(pool, rx, remainder, &subs);
if (ret > 1) {
/* a further substitution happened */
@@ -206,5 +205,5 @@ AP_DECLARE(char*) ap_rxplus_pmatch(apr_pool_t *pool, ap_rxplus_t *rx, int n)
int len;
const char *match;
ap_rxplus_match(rx, n, &len, &match);
- return (match != NULL) ? apr_pstrndup(pool, match, len) : NULL;
+ return apr_pstrndup(pool, match, len);
}