summaryrefslogtreecommitdiffstats
path: root/modules/filters
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-25 04:41:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-25 04:41:28 +0000
commitb1a1c1d95059e2fefd7b5671eb110ab690409a84 (patch)
tree97ecfcc9425e2d09d2cd669594d626a616f324a3 /modules/filters
parentReleasing progress-linux version 2.4.38-3+deb10u10progress5u1. (diff)
downloadapache2-b1a1c1d95059e2fefd7b5671eb110ab690409a84.tar.xz
apache2-b1a1c1d95059e2fefd7b5671eb110ab690409a84.zip
Merging upstream version 2.4.59.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'modules/filters')
-rw-r--r--modules/filters/libsed.h12
-rw-r--r--modules/filters/mod_brotli.c15
-rw-r--r--modules/filters/mod_charset_lite.c4
-rw-r--r--modules/filters/mod_data.c4
-rw-r--r--modules/filters/mod_deflate.c349
-rw-r--r--modules/filters/mod_ext_filter.c6
-rw-r--r--modules/filters/mod_include.c41
-rw-r--r--modules/filters/mod_proxy_html.c31
-rw-r--r--modules/filters/mod_reflector.c11
-rw-r--r--modules/filters/mod_reqtimeout.c237
-rw-r--r--modules/filters/mod_request.c28
-rw-r--r--modules/filters/mod_sed.c116
-rw-r--r--modules/filters/mod_substitute.c9
-rw-r--r--modules/filters/mod_xml2enc.c47
-rw-r--r--modules/filters/regexp.h4
-rw-r--r--modules/filters/sed1.c207
16 files changed, 656 insertions, 465 deletions
diff --git a/modules/filters/libsed.h b/modules/filters/libsed.h
index 76cbc0c..0256b1e 100644
--- a/modules/filters/libsed.h
+++ b/modules/filters/libsed.h
@@ -60,7 +60,7 @@ struct sed_label_s {
};
typedef apr_status_t (sed_err_fn_t)(void *data, const char *error);
-typedef apr_status_t (sed_write_fn_t)(void *ctx, char *buf, int sz);
+typedef apr_status_t (sed_write_fn_t)(void *ctx, char *buf, apr_size_t sz);
typedef struct sed_commands_s sed_commands_t;
#define NWFILES 11 /* 10 plus one for standard output */
@@ -69,7 +69,7 @@ struct sed_commands_s {
sed_err_fn_t *errfn;
void *data;
- unsigned lsize;
+ apr_size_t lsize;
char *linebuf;
char *lbend;
const char *saveq;
@@ -116,15 +116,15 @@ struct sed_eval_s {
apr_int64_t lnum;
void *fout;
- unsigned lsize;
+ apr_size_t lsize;
char *linebuf;
char *lspend;
- unsigned hsize;
+ apr_size_t hsize;
char *holdbuf;
char *hspend;
- unsigned gsize;
+ apr_size_t gsize;
char *genbuf;
char *lcomend;
@@ -160,7 +160,7 @@ apr_status_t sed_init_eval(sed_eval_t *eval, sed_commands_t *commands,
sed_err_fn_t *errfn, void *data,
sed_write_fn_t *writefn, apr_pool_t *p);
apr_status_t sed_reset_eval(sed_eval_t *eval, sed_commands_t *commands, sed_err_fn_t *errfn, void *data);
-apr_status_t sed_eval_buffer(sed_eval_t *eval, const char *buf, int bufsz, void *fout);
+apr_status_t sed_eval_buffer(sed_eval_t *eval, const char *buf, apr_size_t bufsz, void *fout);
apr_status_t sed_eval_file(sed_eval_t *eval, apr_file_t *fin, void *fout);
apr_status_t sed_finalize_eval(sed_eval_t *eval, void *f);
void sed_destroy_eval(sed_eval_t *eval);
diff --git a/modules/filters/mod_brotli.c b/modules/filters/mod_brotli.c
index 56717e7..0f7d770 100644
--- a/modules/filters/mod_brotli.c
+++ b/modules/filters/mod_brotli.c
@@ -344,6 +344,7 @@ static apr_status_t compress_filter(ap_filter_t *f, apr_bucket_brigade *bb)
const char *encoding;
const char *token;
const char *accepts;
+ const char *q = NULL;
/* Only work on main request, not subrequests, that are not
* a 204 response with no content, and are not tagged with the
@@ -411,7 +412,19 @@ static apr_status_t compress_filter(ap_filter_t *f, apr_bucket_brigade *bb)
token = (*accepts) ? ap_get_token(r->pool, &accepts, 0) : NULL;
}
- if (!token || token[0] == '\0') {
+ /* Find the qvalue, if provided */
+ if (*accepts) {
+ while (*accepts == ';') {
+ ++accepts;
+ }
+ q = ap_get_token(r->pool, &accepts, 1);
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
+ "token: '%s' - q: '%s'", token ? token : "NULL", q);
+ }
+
+ /* No acceptable token found or q=0 */
+ if (!token || token[0] == '\0' ||
+ (q && strlen(q) >= 3 && strncmp("q=0.000", q, strlen(q)) == 0)) {
ap_remove_output_filter(f);
return ap_pass_brigade(f->next, bb);
}
diff --git a/modules/filters/mod_charset_lite.c b/modules/filters/mod_charset_lite.c
index ed76f61..e3d1ce9 100644
--- a/modules/filters/mod_charset_lite.c
+++ b/modules/filters/mod_charset_lite.c
@@ -790,7 +790,7 @@ static apr_status_t xlate_out_filter(ap_filter_t *f, apr_bucket_brigade *bb)
if (!ctx->noop && ctx->xlate == NULL) {
const char *mime_type = f->r->content_type;
- if (mime_type && (strncasecmp(mime_type, "text/", 5) == 0 ||
+ if (mime_type && (ap_cstr_casecmpn(mime_type, "text/", 5) == 0 ||
#if APR_CHARSET_EBCDIC
/* On an EBCDIC machine, be willing to translate mod_autoindex-
* generated output. Otherwise, it doesn't look too cool.
@@ -806,7 +806,7 @@ static apr_status_t xlate_out_filter(ap_filter_t *f, apr_bucket_brigade *bb)
*/
strcmp(mime_type, DIR_MAGIC_TYPE) == 0 ||
#endif
- strncasecmp(mime_type, "message/", 8) == 0 ||
+ ap_cstr_casecmpn(mime_type, "message/", 8) == 0 ||
dc->force_xlate == FX_FORCE)) {
rv = apr_xlate_open(&ctx->xlate,
diff --git a/modules/filters/mod_data.c b/modules/filters/mod_data.c
index d083d32..ddadd1b 100644
--- a/modules/filters/mod_data.c
+++ b/modules/filters/mod_data.c
@@ -107,8 +107,8 @@ static apr_status_t data_out_filter(ap_filter_t *f, apr_bucket_brigade *bb)
if (content_length) {
apr_off_t len, clen;
apr_brigade_length(ctx->bb, 1, &len);
- clen = apr_atoi64(content_length);
- if (clen >= 0 && clen < APR_INT32_MAX) {
+ if (ap_parse_strict_length(&clen, content_length)
+ && clen < APR_INT32_MAX) {
ap_set_content_length(r, len +
apr_base64_encode_len((int)clen) - 1);
}
diff --git a/modules/filters/mod_deflate.c b/modules/filters/mod_deflate.c
index d60b2de..5a541e7 100644
--- a/modules/filters/mod_deflate.c
+++ b/modules/filters/mod_deflate.c
@@ -43,10 +43,11 @@
#include "apr_general.h"
#include "util_filter.h"
#include "apr_buckets.h"
+#include "http_protocol.h"
#include "http_request.h"
+#include "http_ssl.h"
#define APR_WANT_STRFUNC
#include "apr_want.h"
-#include "mod_ssl.h"
#include "zlib.h"
@@ -56,15 +57,20 @@ module AP_MODULE_DECLARE_DATA deflate_module;
#define AP_INFLATE_RATIO_LIMIT 200
#define AP_INFLATE_RATIO_BURST 3
+#define AP_DEFLATE_ETAG_ADDSUFFIX 0
+#define AP_DEFLATE_ETAG_NOCHANGE 1
+#define AP_DEFLATE_ETAG_REMOVE 2
+
typedef struct deflate_filter_config_t
{
int windowSize;
int memlevel;
int compressionlevel;
- apr_size_t bufferSize;
+ int bufferSize;
const char *note_ratio_name;
const char *note_input_name;
const char *note_output_name;
+ int etag_opt;
} deflate_filter_config;
typedef struct deflate_dirconf_t {
@@ -94,8 +100,6 @@ static const char deflate_magic[2] = { '\037', '\213' };
#define DEFAULT_MEMLEVEL 9
#define DEFAULT_BUFFERSIZE 8096
-static APR_OPTIONAL_FN_TYPE(ssl_var_lookup) *mod_deflate_ssl_var = NULL;
-
/* Check whether a request is gzipped, so we can un-gzip it.
* If a request has multiple encodings, we need the gzip
* to be the outermost non-identity encoding.
@@ -118,8 +122,8 @@ static int check_gzip(request_rec *r, apr_table_t *hdrs1, apr_table_t *hdrs2)
if (encoding && *encoding) {
/* check the usual/simple case first */
- if (!strcasecmp(encoding, "gzip")
- || !strcasecmp(encoding, "x-gzip")) {
+ if (!ap_cstr_casecmp(encoding, "gzip")
+ || !ap_cstr_casecmp(encoding, "x-gzip")) {
found = 1;
if (hdrs) {
apr_table_unset(hdrs, "Content-Encoding");
@@ -137,8 +141,8 @@ static int check_gzip(request_rec *r, apr_table_t *hdrs1, apr_table_t *hdrs2)
for(;;) {
char *token = ap_strrchr(new_encoding, ',');
if (!token) { /* gzip:identity or other:identity */
- if (!strcasecmp(new_encoding, "gzip")
- || !strcasecmp(new_encoding, "x-gzip")) {
+ if (!ap_cstr_casecmp(new_encoding, "gzip")
+ || !ap_cstr_casecmp(new_encoding, "x-gzip")) {
found = 1;
if (hdrs) {
apr_table_unset(hdrs, "Content-Encoding");
@@ -150,8 +154,8 @@ static int check_gzip(request_rec *r, apr_table_t *hdrs1, apr_table_t *hdrs2)
break; /* seen all tokens */
}
for (ptr=token+1; apr_isspace(*ptr); ++ptr);
- if (!strcasecmp(ptr, "gzip")
- || !strcasecmp(ptr, "x-gzip")) {
+ if (!ap_cstr_casecmp(ptr, "gzip")
+ || !ap_cstr_casecmp(ptr, "x-gzip")) {
*token = '\0';
if (hdrs) {
apr_table_setn(hdrs, "Content-Encoding", new_encoding);
@@ -161,7 +165,7 @@ static int check_gzip(request_rec *r, apr_table_t *hdrs1, apr_table_t *hdrs2)
}
found = 1;
}
- else if (!ptr[0] || !strcasecmp(ptr, "identity")) {
+ else if (!ptr[0] || !ap_cstr_casecmp(ptr, "identity")) {
*token = '\0';
continue; /* strip the token and find the next one */
}
@@ -250,7 +254,7 @@ static const char *deflate_set_buffer_size(cmd_parms *cmd, void *dummy,
return "DeflateBufferSize should be positive";
}
- c->bufferSize = (apr_size_t)n;
+ c->bufferSize = n;
return NULL;
}
@@ -296,6 +300,29 @@ static const char *deflate_set_memlevel(cmd_parms *cmd, void *dummy,
return NULL;
}
+static const char *deflate_set_etag(cmd_parms *cmd, void *dummy,
+ const char *arg)
+{
+ deflate_filter_config *c = ap_get_module_config(cmd->server->module_config,
+ &deflate_module);
+
+ if (!strcasecmp(arg, "NoChange")) {
+ c->etag_opt = AP_DEFLATE_ETAG_NOCHANGE;
+ }
+ else if (!strcasecmp(arg, "AddSuffix")) {
+ c->etag_opt = AP_DEFLATE_ETAG_ADDSUFFIX;
+ }
+ else if (!strcasecmp(arg, "Remove")) {
+ c->etag_opt = AP_DEFLATE_ETAG_REMOVE;
+ }
+ else {
+ return "DeflateAlterETAG accepts only 'NoChange', 'AddSuffix', and 'Remove'";
+ }
+
+ return NULL;
+}
+
+
static const char *deflate_set_compressionlevel(cmd_parms *cmd, void *dummy,
const char *arg)
{
@@ -389,35 +416,40 @@ typedef struct deflate_ctx_t
/* Do update ctx->crc, see comment in flush_libz_buffer */
#define UPDATE_CRC 1
+static void consume_buffer(deflate_ctx *ctx, deflate_filter_config *c,
+ int len, int crc, apr_bucket_brigade *bb)
+{
+ apr_bucket *b;
+
+ /*
+ * Do we need to update ctx->crc? Usually this is the case for
+ * inflate action where we need to do a crc on the output, whereas
+ * in the deflate case we need to do a crc on the input
+ */
+ if (crc) {
+ ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);
+ }
+
+ b = apr_bucket_heap_create((char *)ctx->buffer, len, NULL,
+ bb->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, b);
+
+ ctx->stream.next_out = ctx->buffer;
+ ctx->stream.avail_out = c->bufferSize;
+}
+
static int flush_libz_buffer(deflate_ctx *ctx, deflate_filter_config *c,
- struct apr_bucket_alloc_t *bucket_alloc,
int (*libz_func)(z_streamp, int), int flush,
int crc)
{
int zRC = Z_OK;
int done = 0;
- unsigned int deflate_len;
- apr_bucket *b;
+ int deflate_len;
for (;;) {
deflate_len = c->bufferSize - ctx->stream.avail_out;
-
- if (deflate_len != 0) {
- /*
- * Do we need to update ctx->crc? Usually this is the case for
- * inflate action where we need to do a crc on the output, whereas
- * in the deflate case we need to do a crc on the input
- */
- if (crc) {
- ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer,
- deflate_len);
- }
- b = apr_bucket_heap_create((char *)ctx->buffer,
- deflate_len, NULL,
- bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(ctx->bb, b);
- ctx->stream.next_out = ctx->buffer;
- ctx->stream.avail_out = c->bufferSize;
+ if (deflate_len > 0) {
+ consume_buffer(ctx, c, deflate_len, crc, ctx->bb);
}
if (done)
@@ -465,11 +497,16 @@ static apr_status_t deflate_ctx_cleanup(void *data)
* value inside the double-quotes if an ETag has already been set
* and its value already contains double-quotes. PR 39727
*/
-static void deflate_check_etag(request_rec *r, const char *transform)
+static void deflate_check_etag(request_rec *r, const char *transform, int etag_opt)
{
const char *etag = apr_table_get(r->headers_out, "ETag");
apr_size_t etaglen;
+ if (etag_opt == AP_DEFLATE_ETAG_REMOVE) {
+ apr_table_unset(r->headers_out, "ETag");
+ return;
+ }
+
if ((etag && ((etaglen = strlen(etag)) > 2))) {
if (etag[etaglen - 1] == '"') {
apr_size_t transformlen = strlen(transform);
@@ -514,10 +551,8 @@ static int check_ratio(request_rec *r, deflate_ctx *ctx,
static int have_ssl_compression(request_rec *r)
{
const char *comp;
- if (mod_deflate_ssl_var == NULL)
- return 0;
- comp = mod_deflate_ssl_var(r->pool, r->server, r->connection, r,
- "SSL_COMPRESS_METHOD");
+ comp = ap_ssl_var_lookup(r->pool, r->server, r->connection, r,
+ "SSL_COMPRESS_METHOD");
if (comp == NULL || *comp == '\0' || strcmp(comp, "NULL") == 0)
return 0;
return 1;
@@ -530,6 +565,7 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,
request_rec *r = f->r;
deflate_ctx *ctx = f->ctx;
int zRC;
+ apr_status_t rv;
apr_size_t len = 0, blen;
const char *data;
deflate_filter_config *c;
@@ -586,9 +622,14 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,
continue;
}
- rc = apr_bucket_read(e, &data, &blen, APR_BLOCK_READ);
- if (rc != APR_SUCCESS)
- return rc;
+ if (e->length == (apr_size_t)-1) {
+ rc = apr_bucket_read(e, &data, &blen, APR_BLOCK_READ);
+ if (rc != APR_SUCCESS)
+ return rc;
+ }
+ else {
+ blen = e->length;
+ }
len += blen;
/* 50 is for Content-Encoding and Vary headers and ETag suffix */
if (len > sizeof(gzip_header) + VALIDATION_SIZE + 50)
@@ -699,6 +740,8 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,
*/
if (!apr_table_get(r->subprocess_env, "force-gzip")) {
const char *accepts;
+ const char *q = NULL;
+
/* if they don't have the line, then they can't play */
accepts = apr_table_get(r->headers_in, "Accept-Encoding");
if (accepts == NULL) {
@@ -707,7 +750,7 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,
}
token = ap_get_token(r->pool, &accepts, 0);
- while (token && token[0] && strcasecmp(token, "gzip")) {
+ while (token && token[0] && ap_cstr_casecmp(token, "gzip")) {
/* skip parameters, XXX: ;q=foo evaluation? */
while (*accepts == ';') {
++accepts;
@@ -721,10 +764,21 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,
token = (*accepts) ? ap_get_token(r->pool, &accepts, 0) : NULL;
}
- /* No acceptable token found. */
- if (token == NULL || token[0] == '\0') {
+ /* Find the qvalue, if provided */
+ if (*accepts) {
+ while (*accepts == ';') {
+ ++accepts;
+ }
+ q = ap_get_token(r->pool, &accepts, 1);
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
+ "token: '%s' - q: '%s'", token ? token : "NULL", q);
+ }
+
+ /* No acceptable token found or q=0 */
+ if (!token || token[0] == '\0' ||
+ (q && strlen(q) >= 3 && strncmp("q=0.000", q, strlen(q)) == 0)) {
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
- "Not compressing (no Accept-Encoding: gzip)");
+ "Not compressing (no Accept-Encoding: gzip or q=0)");
ap_remove_output_filter(f);
return ap_pass_brigade(f->next, bb);
}
@@ -781,7 +835,7 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,
*/
/* If the entire Content-Encoding is "identity", we can replace it. */
- if (!encoding || !strcasecmp(encoding, "identity")) {
+ if (!encoding || !ap_cstr_casecmp(encoding, "identity")) {
apr_table_setn(r->headers_out, "Content-Encoding", "gzip");
}
else {
@@ -794,7 +848,9 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,
}
apr_table_unset(r->headers_out, "Content-Length");
apr_table_unset(r->headers_out, "Content-MD5");
- deflate_check_etag(r, "gzip");
+ if (c->etag_opt != AP_DEFLATE_ETAG_NOCHANGE) {
+ deflate_check_etag(r, "gzip", c->etag_opt);
+ }
/* For a 304 response, only change the headers */
if (r->status == HTTP_NOT_MODIFIED) {
@@ -841,8 +897,7 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,
ctx->stream.avail_in = 0; /* should be zero already anyway */
/* flush the remaining data from the zlib buffers */
- flush_libz_buffer(ctx, c, f->c->bucket_alloc, deflate, Z_FINISH,
- NO_UPDATE_CRC);
+ flush_libz_buffer(ctx, c, deflate, Z_FINISH, NO_UPDATE_CRC);
buf = apr_palloc(r->pool, VALIDATION_SIZE);
putLong((unsigned char *)&buf[0], ctx->crc);
@@ -852,8 +907,10 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,
f->c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(ctx->bb, b);
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01384)
- "Zlib: Compressed %ld to %ld : URL %s",
- ctx->stream.total_in, ctx->stream.total_out, r->uri);
+ "Zlib: Compressed %" APR_UINT64_T_FMT
+ " to %" APR_UINT64_T_FMT " : URL %s",
+ (apr_uint64_t)ctx->stream.total_in,
+ (apr_uint64_t)ctx->stream.total_out, r->uri);
/* leave notes for logging */
if (c->note_input_name) {
@@ -866,7 +923,7 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,
if (c->note_output_name) {
apr_table_setn(r->notes, c->note_output_name,
- (ctx->stream.total_in > 0)
+ (ctx->stream.total_out > 0)
? apr_off_t_toa(r->pool,
ctx->stream.total_out)
: "-");
@@ -883,6 +940,10 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,
}
deflateEnd(&ctx->stream);
+
+ /* We've ended the libz stream, so remove ourselves. */
+ ap_remove_output_filter(f);
+
/* No need for cleanup any longer */
apr_pool_cleanup_kill(r->pool, ctx, deflate_ctx_cleanup);
@@ -893,15 +954,15 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,
/* Okay, we've seen the EOS.
* Time to pass it along down the chain.
*/
- return ap_pass_brigade(f->next, ctx->bb);
+ rv = ap_pass_brigade(f->next, ctx->bb);
+ apr_brigade_cleanup(ctx->bb);
+ return rv;
}
if (APR_BUCKET_IS_FLUSH(e)) {
- apr_status_t rv;
-
/* flush the remaining data from the zlib buffers */
- zRC = flush_libz_buffer(ctx, c, f->c->bucket_alloc, deflate,
- Z_SYNC_FLUSH, NO_UPDATE_CRC);
+ zRC = flush_libz_buffer(ctx, c, deflate, Z_SYNC_FLUSH,
+ NO_UPDATE_CRC);
if (zRC != Z_OK) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01385)
"Zlib error %d flushing zlib output buffer (%s)",
@@ -913,6 +974,7 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,
APR_BUCKET_REMOVE(e);
APR_BRIGADE_INSERT_TAIL(ctx->bb, e);
rv = ap_pass_brigade(f->next, ctx->bb);
+ apr_brigade_cleanup(ctx->bb);
if (rv != APR_SUCCESS) {
return rv;
}
@@ -930,7 +992,12 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,
}
/* read */
- apr_bucket_read(e, &data, &len, APR_BLOCK_READ);
+ rv = apr_bucket_read(e, &data, &len, APR_BLOCK_READ);
+ if (rv) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(10298)
+ "failed reading from %s bucket", e->type->name);
+ return rv;
+ }
if (!len) {
apr_bucket_delete(e);
continue;
@@ -947,21 +1014,15 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,
ctx->stream.next_in = (unsigned char *)data; /* We just lost const-ness,
* but we'll just have to
* trust zlib */
- ctx->stream.avail_in = len;
+ ctx->stream.avail_in = (int)len;
while (ctx->stream.avail_in != 0) {
if (ctx->stream.avail_out == 0) {
- apr_status_t rv;
-
- ctx->stream.next_out = ctx->buffer;
- len = c->bufferSize - ctx->stream.avail_out;
+ consume_buffer(ctx, c, c->bufferSize, NO_UPDATE_CRC, ctx->bb);
- b = apr_bucket_heap_create((char *)ctx->buffer, len,
- NULL, f->c->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(ctx->bb, b);
- ctx->stream.avail_out = c->bufferSize;
/* Send what we have right now to the next filter. */
rv = ap_pass_brigade(f->next, ctx->bb);
+ apr_brigade_cleanup(ctx->bb);
if (rv != APR_SUCCESS) {
return rv;
}
@@ -1258,44 +1319,40 @@ static apr_status_t deflate_in_filter(ap_filter_t *f,
if (APR_BUCKET_IS_FLUSH(bkt)) {
apr_bucket *tmp_b;
- ctx->inflate_total += ctx->stream.avail_out;
- zRC = inflate(&(ctx->stream), Z_SYNC_FLUSH);
- ctx->inflate_total -= ctx->stream.avail_out;
- if (zRC != Z_OK) {
- inflateEnd(&ctx->stream);
- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01391)
- "Zlib error %d inflating data (%s)", zRC,
- ctx->stream.msg);
- return APR_EGENERAL;
- }
+ if (!ctx->done) {
+ ctx->inflate_total += ctx->stream.avail_out;
+ zRC = inflate(&(ctx->stream), Z_SYNC_FLUSH);
+ ctx->inflate_total -= ctx->stream.avail_out;
+ if (zRC != Z_OK) {
+ inflateEnd(&ctx->stream);
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01391)
+ "Zlib error %d inflating data (%s)", zRC,
+ ctx->stream.msg);
+ return APR_EGENERAL;
+ }
- if (inflate_limit && ctx->inflate_total > inflate_limit) {
- inflateEnd(&ctx->stream);
- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(02647)
- "Inflated content length of %" APR_OFF_T_FMT
- " is larger than the configured limit"
- " of %" APR_OFF_T_FMT,
- ctx->inflate_total, inflate_limit);
- return APR_ENOSPC;
- }
-
- if (!check_ratio(r, ctx, dc)) {
- inflateEnd(&ctx->stream);
- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(02805)
- "Inflated content ratio is larger than the "
- "configured limit %i by %i time(s)",
- dc->ratio_limit, dc->ratio_burst);
- return APR_EINVAL;
- }
+ if (inflate_limit && ctx->inflate_total > inflate_limit) {
+ inflateEnd(&ctx->stream);
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(02647)
+ "Inflated content length of %" APR_OFF_T_FMT
+ " is larger than the configured limit"
+ " of %" APR_OFF_T_FMT,
+ ctx->inflate_total, inflate_limit);
+ return APR_ENOSPC;
+ }
- len = c->bufferSize - ctx->stream.avail_out;
- ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);
- tmp_b = apr_bucket_heap_create((char *)ctx->buffer, len,
- NULL, f->c->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(ctx->proc_bb, tmp_b);
+ if (!check_ratio(r, ctx, dc)) {
+ inflateEnd(&ctx->stream);
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(02805)
+ "Inflated content ratio is larger than the "
+ "configured limit %i by %i time(s)",
+ dc->ratio_limit, dc->ratio_burst);
+ return APR_EINVAL;
+ }
- ctx->stream.next_out = ctx->buffer;
- ctx->stream.avail_out = c->bufferSize;
+ consume_buffer(ctx, c, c->bufferSize - ctx->stream.avail_out,
+ UPDATE_CRC, ctx->proc_bb);
+ }
/* Flush everything so far in the returning brigade, but continue
* reading should EOS/more follow (don't lose them).
@@ -1338,21 +1395,11 @@ static apr_status_t deflate_in_filter(ap_filter_t *f,
ctx->stream.next_in = (unsigned char *)data;
ctx->stream.avail_in = (int)len;
- zRC = Z_OK;
-
if (!ctx->validation_buffer) {
while (ctx->stream.avail_in != 0) {
if (ctx->stream.avail_out == 0) {
- apr_bucket *tmp_heap;
-
- ctx->stream.next_out = ctx->buffer;
- len = c->bufferSize - ctx->stream.avail_out;
-
- ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);
- tmp_heap = apr_bucket_heap_create((char *)ctx->buffer, len,
- NULL, f->c->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(ctx->proc_bb, tmp_heap);
- ctx->stream.avail_out = c->bufferSize;
+ consume_buffer(ctx, c, c->bufferSize, UPDATE_CRC,
+ ctx->proc_bb);
}
ctx->inflate_total += ctx->stream.avail_out;
@@ -1395,7 +1442,6 @@ static apr_status_t deflate_in_filter(ap_filter_t *f,
}
if (ctx->validation_buffer) {
- apr_bucket *tmp_heap;
apr_size_t avail, valid;
unsigned char *buf = ctx->validation_buffer;
@@ -1419,17 +1465,13 @@ static apr_status_t deflate_in_filter(ap_filter_t *f,
ctx->validation_buffer_length += valid;
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01393)
- "Zlib: Inflated %ld to %ld : URL %s",
- ctx->stream.total_in, ctx->stream.total_out,
- r->uri);
+ "Zlib: Inflated %" APR_UINT64_T_FMT
+ " to %" APR_UINT64_T_FMT " : URL %s",
+ (apr_uint64_t)ctx->stream.total_in,
+ (apr_uint64_t)ctx->stream.total_out, r->uri);
- len = c->bufferSize - ctx->stream.avail_out;
-
- ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);
- tmp_heap = apr_bucket_heap_create((char *)ctx->buffer, len,
- NULL, f->c->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(ctx->proc_bb, tmp_heap);
- ctx->stream.avail_out = c->bufferSize;
+ consume_buffer(ctx, c, c->bufferSize - ctx->stream.avail_out,
+ UPDATE_CRC, ctx->proc_bb);
{
unsigned long compCRC, compLen;
@@ -1445,9 +1487,10 @@ static apr_status_t deflate_in_filter(ap_filter_t *f,
if ((ctx->stream.total_out & 0xFFFFFFFF) != compLen) {
inflateEnd(&ctx->stream);
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01395)
- "Zlib: Length %ld of inflated data does "
- "not match expected value %ld",
- ctx->stream.total_out, compLen);
+ "Zlib: Length %" APR_UINT64_T_FMT
+ " of inflated data does not match"
+ " expected value %ld",
+ (apr_uint64_t)ctx->stream.total_out, compLen);
return APR_EGENERAL;
}
}
@@ -1474,16 +1517,8 @@ static apr_status_t deflate_in_filter(ap_filter_t *f,
if (block == APR_BLOCK_READ &&
APR_BRIGADE_EMPTY(ctx->proc_bb) &&
ctx->stream.avail_out < c->bufferSize) {
- apr_bucket *tmp_heap;
- apr_size_t len;
- ctx->stream.next_out = ctx->buffer;
- len = c->bufferSize - ctx->stream.avail_out;
-
- ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);
- tmp_heap = apr_bucket_heap_create((char *)ctx->buffer, len,
- NULL, f->c->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(ctx->proc_bb, tmp_heap);
- ctx->stream.avail_out = c->bufferSize;
+ consume_buffer(ctx, c, c->bufferSize - ctx->stream.avail_out,
+ UPDATE_CRC, ctx->proc_bb);
}
if (!APR_BRIGADE_EMPTY(ctx->proc_bb)) {
@@ -1549,7 +1584,9 @@ static apr_status_t inflate_out_filter(ap_filter_t *f,
*/
apr_table_unset(r->headers_out, "Content-Length");
apr_table_unset(r->headers_out, "Content-MD5");
- deflate_check_etag(r, "gunzip");
+ if (c->etag_opt != AP_DEFLATE_ETAG_NOCHANGE) {
+ deflate_check_etag(r, "gunzip", c->etag_opt);
+ }
/* For a 304 response, only change the headers */
if (r->status == HTTP_NOT_MODIFIED) {
@@ -1597,7 +1634,6 @@ static apr_status_t inflate_out_filter(ap_filter_t *f,
while (!APR_BRIGADE_EMPTY(bb))
{
const char *data;
- apr_bucket *b;
apr_size_t len;
e = APR_BRIGADE_FIRST(bb);
@@ -1619,11 +1655,12 @@ static apr_status_t inflate_out_filter(ap_filter_t *f,
* fails, whereas in the deflate case you can empty a filled output
* buffer and call it again until no more output can be created.
*/
- flush_libz_buffer(ctx, c, f->c->bucket_alloc, inflate, Z_SYNC_FLUSH,
- UPDATE_CRC);
+ flush_libz_buffer(ctx, c, inflate, Z_SYNC_FLUSH, UPDATE_CRC);
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01398)
- "Zlib: Inflated %ld to %ld : URL %s",
- ctx->stream.total_in, ctx->stream.total_out, r->uri);
+ "Zlib: Inflated %" APR_UINT64_T_FMT
+ " to %" APR_UINT64_T_FMT " : URL %s",
+ (apr_uint64_t)ctx->stream.total_in,
+ (apr_uint64_t)ctx->stream.total_out, r->uri);
if (ctx->validation_buffer_length == VALIDATION_SIZE) {
unsigned long compCRC, compLen;
@@ -1660,15 +1697,14 @@ static apr_status_t inflate_out_filter(ap_filter_t *f,
* Okay, we've seen the EOS.
* Time to pass it along down the chain.
*/
- return ap_pass_brigade(f->next, ctx->bb);
+ rv = ap_pass_brigade(f->next, ctx->bb);
+ apr_brigade_cleanup(ctx->bb);
+ return rv;
}
if (APR_BUCKET_IS_FLUSH(e)) {
- apr_status_t rv;
-
/* flush the remaining data from the zlib buffers */
- zRC = flush_libz_buffer(ctx, c, f->c->bucket_alloc, inflate,
- Z_SYNC_FLUSH, UPDATE_CRC);
+ zRC = flush_libz_buffer(ctx, c, inflate, Z_SYNC_FLUSH, UPDATE_CRC);
if (zRC == Z_STREAM_END) {
if (ctx->validation_buffer == NULL) {
ctx->validation_buffer = apr_pcalloc(f->r->pool,
@@ -1686,6 +1722,7 @@ static apr_status_t inflate_out_filter(ap_filter_t *f,
APR_BUCKET_REMOVE(e);
APR_BRIGADE_INSERT_TAIL(ctx->bb, e);
rv = ap_pass_brigade(f->next, ctx->bb);
+ apr_brigade_cleanup(ctx->bb);
if (rv != APR_SUCCESS) {
return rv;
}
@@ -1802,16 +1839,11 @@ static apr_status_t inflate_out_filter(ap_filter_t *f,
while (ctx->stream.avail_in != 0) {
if (ctx->stream.avail_out == 0) {
- ctx->stream.next_out = ctx->buffer;
- len = c->bufferSize - ctx->stream.avail_out;
-
- ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);
- b = apr_bucket_heap_create((char *)ctx->buffer, len,
- NULL, f->c->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(ctx->bb, b);
- ctx->stream.avail_out = c->bufferSize;
+ consume_buffer(ctx, c, c->bufferSize, UPDATE_CRC, ctx->bb);
+
/* Send what we have right now to the next filter. */
rv = ap_pass_brigade(f->next, ctx->bb);
+ apr_brigade_cleanup(ctx->bb);
if (rv != APR_SUCCESS) {
return rv;
}
@@ -1826,6 +1858,7 @@ static apr_status_t inflate_out_filter(ap_filter_t *f,
return APR_EGENERAL;
}
+ /* Don't check length limits on inflate_out */
if (!check_ratio(r, ctx, dc)) {
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(02650)
"Inflated content ratio is larger than the "
@@ -1868,7 +1901,6 @@ static apr_status_t inflate_out_filter(ap_filter_t *f,
static int mod_deflate_post_config(apr_pool_t *pconf, apr_pool_t *plog,
apr_pool_t *ptemp, server_rec *s)
{
- mod_deflate_ssl_var = APR_RETRIEVE_OPTIONAL_FN(ssl_var_lookup);
return OK;
}
@@ -1904,6 +1936,9 @@ static const command_rec deflate_filter_cmds[] = {
AP_INIT_TAKE1("DeflateInflateRatioBurst", deflate_set_inflate_ratio_burst, NULL, OR_ALL,
"Set the maximum number of following inflate ratios above limit "
"(default: " APR_STRINGIFY(AP_INFLATE_RATIO_BURST) ")"),
+ AP_INIT_TAKE1("DeflateAlterEtag", deflate_set_etag, NULL, RSRC_CONF,
+ "Set how mod_deflate should modify ETAG response headers: 'AddSuffix' (default), 'NoChange' (2.2.x behavior), 'Remove'"),
+
{NULL}
};
diff --git a/modules/filters/mod_ext_filter.c b/modules/filters/mod_ext_filter.c
index 7aac19d..7afd8dd 100644
--- a/modules/filters/mod_ext_filter.c
+++ b/modules/filters/mod_ext_filter.c
@@ -655,8 +655,7 @@ static apr_status_t drain_available_output(ap_filter_t *f,
if (rv && !APR_STATUS_IS_EAGAIN(rv))
lvl = APLOG_DEBUG;
ap_log_rerror(APLOG_MARK, lvl, rv, r, APLOGNO(01460)
- "apr_file_read(child output), len %" APR_SIZE_T_FMT,
- !rv ? len : -1);
+ "apr_file_read(child output), len %" APR_SIZE_T_FMT, len);
if (rv != APR_SUCCESS) {
return rv;
}
@@ -810,8 +809,7 @@ static int ef_unified_filter(ap_filter_t *f, apr_bucket_brigade *bb)
if (rv && !APR_STATUS_IS_EOF(rv) && !APR_STATUS_IS_EAGAIN(rv))
lvl = APLOG_ERR;
ap_log_rerror(APLOG_MARK, lvl, rv, r, APLOGNO(01466)
- "apr_file_read(child output), len %" APR_SIZE_T_FMT,
- !rv ? len : -1);
+ "apr_file_read(child output), len %" APR_SIZE_T_FMT, len);
if (APR_STATUS_IS_EAGAIN(rv)) {
if (eos) {
/* should not occur, because we have an APR timeout in place */
diff --git a/modules/filters/mod_include.c b/modules/filters/mod_include.c
index a46a944..584d8fb 100644
--- a/modules/filters/mod_include.c
+++ b/modules/filters/mod_include.c
@@ -1967,25 +1967,25 @@ static apr_status_t handle_echo(include_ctx_t *ctx, ap_filter_t *f,
token = apr_strtok(d, ", \t", &last);
while (token) {
- if (!strcasecmp(token, "none")) {
+ if (!ap_cstr_casecmp(token, "none")) {
/* do nothing */
}
- else if (!strcasecmp(token, "url")) {
+ else if (!ap_cstr_casecmp(token, "url")) {
char *buf = apr_pstrdup(ctx->pool, echo_text);
ap_unescape_url(buf);
echo_text = buf;
}
- else if (!strcasecmp(token, "urlencoded")) {
+ else if (!ap_cstr_casecmp(token, "urlencoded")) {
char *buf = apr_pstrdup(ctx->pool, echo_text);
ap_unescape_urlencoded(buf);
echo_text = buf;
}
- else if (!strcasecmp(token, "entity")) {
+ else if (!ap_cstr_casecmp(token, "entity")) {
char *buf = apr_pstrdup(ctx->pool, echo_text);
decodehtml(buf);
echo_text = buf;
}
- else if (!strcasecmp(token, "base64")) {
+ else if (!ap_cstr_casecmp(token, "base64")) {
echo_text = ap_pbase64decode(ctx->dpool, echo_text);
}
else {
@@ -2003,19 +2003,19 @@ static apr_status_t handle_echo(include_ctx_t *ctx, ap_filter_t *f,
token = apr_strtok(e, ", \t", &last);
while (token) {
- if (!strcasecmp(token, "none")) {
+ if (!ap_cstr_casecmp(token, "none")) {
/* do nothing */
}
- else if (!strcasecmp(token, "url")) {
+ else if (!ap_cstr_casecmp(token, "url")) {
echo_text = ap_escape_uri(ctx->dpool, echo_text);
}
- else if (!strcasecmp(token, "urlencoded")) {
+ else if (!ap_cstr_casecmp(token, "urlencoded")) {
echo_text = ap_escape_urlencoded(ctx->dpool, echo_text);
}
- else if (!strcasecmp(token, "entity")) {
+ else if (!ap_cstr_casecmp(token, "entity")) {
echo_text = ap_escape_html2(ctx->dpool, echo_text, 0);
}
- else if (!strcasecmp(token, "base64")) {
+ else if (!ap_cstr_casecmp(token, "base64")) {
char *buf;
buf = ap_pbase64encode(ctx->dpool, (char *)echo_text);
echo_text = buf;
@@ -2605,25 +2605,25 @@ static apr_status_t handle_set(include_ctx_t *ctx, ap_filter_t *f,
token = apr_strtok(d, ", \t", &last);
while (token) {
- if (!strcasecmp(token, "none")) {
+ if (!ap_cstr_casecmp(token, "none")) {
/* do nothing */
}
- else if (!strcasecmp(token, "url")) {
+ else if (!ap_cstr_casecmp(token, "url")) {
char *buf = apr_pstrdup(ctx->pool, parsed_string);
ap_unescape_url(buf);
parsed_string = buf;
}
- else if (!strcasecmp(token, "urlencoded")) {
+ else if (!ap_cstr_casecmp(token, "urlencoded")) {
char *buf = apr_pstrdup(ctx->pool, parsed_string);
ap_unescape_urlencoded(buf);
parsed_string = buf;
}
- else if (!strcasecmp(token, "entity")) {
+ else if (!ap_cstr_casecmp(token, "entity")) {
char *buf = apr_pstrdup(ctx->pool, parsed_string);
decodehtml(buf);
parsed_string = buf;
}
- else if (!strcasecmp(token, "base64")) {
+ else if (!ap_cstr_casecmp(token, "base64")) {
parsed_string = ap_pbase64decode(ctx->dpool, parsed_string);
}
else {
@@ -2641,19 +2641,19 @@ static apr_status_t handle_set(include_ctx_t *ctx, ap_filter_t *f,
token = apr_strtok(e, ", \t", &last);
while (token) {
- if (!strcasecmp(token, "none")) {
+ if (!ap_cstr_casecmp(token, "none")) {
/* do nothing */
}
- else if (!strcasecmp(token, "url")) {
+ else if (!ap_cstr_casecmp(token, "url")) {
parsed_string = ap_escape_uri(ctx->dpool, parsed_string);
}
- else if (!strcasecmp(token, "urlencoded")) {
+ else if (!ap_cstr_casecmp(token, "urlencoded")) {
parsed_string = ap_escape_urlencoded(ctx->dpool, parsed_string);
}
- else if (!strcasecmp(token, "entity")) {
+ else if (!ap_cstr_casecmp(token, "entity")) {
parsed_string = ap_escape_html2(ctx->dpool, parsed_string, 0);
}
- else if (!strcasecmp(token, "base64")) {
+ else if (!ap_cstr_casecmp(token, "base64")) {
char *buf;
buf = ap_pbase64encode(ctx->dpool, (char *)parsed_string);
parsed_string = buf;
@@ -3855,6 +3855,7 @@ static apr_status_t includes_filter(ap_filter_t *f, apr_bucket_brigade *b)
ctx->intern = intern = apr_palloc(r->pool, sizeof(*ctx->intern));
ctx->pool = r->pool;
apr_pool_create(&ctx->dpool, ctx->pool);
+ apr_pool_tag(ctx->dpool, "includes_dpool");
/* runtime data */
intern->tmp_bb = apr_brigade_create(ctx->pool, f->c->bucket_alloc);
diff --git a/modules/filters/mod_proxy_html.c b/modules/filters/mod_proxy_html.c
index ea6bf03..7783da1 100644
--- a/modules/filters/mod_proxy_html.c
+++ b/modules/filters/mod_proxy_html.c
@@ -29,9 +29,28 @@
#define VERBOSEB(x) if (verbose) {x}
#endif
+/* libxml2 includes unicode/[...].h files which uses C++ comments */
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic warning "-Wcomment"
+#elif defined(__GNUC__)
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic warning "-Wcomment"
+#endif
+#endif
+
/* libxml2 */
#include <libxml/HTMLparser.h>
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#elif defined(__GNUC__)
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
+#pragma GCC diagnostic pop
+#endif
+#endif
+
#include "http_protocol.h"
#include "http_config.h"
#include "http_log.h"
@@ -88,7 +107,7 @@ typedef struct {
const char *doctype;
const char *etag;
unsigned int flags;
- size_t bufsz;
+ int bufsz;
apr_hash_t *links;
apr_array_header_t *events;
const char *charset_out;
@@ -660,7 +679,7 @@ static meta *metafix(request_rec *r, const char *buf, apr_size_t len)
while (!apr_isalpha(*++p));
for (q = p; apr_isalnum(*q) || (*q == '-'); ++q);
header = apr_pstrmemdup(r->pool, p, q-p);
- if (strncasecmp(header, "Content-", 8)) {
+ if (ap_cstr_casecmpn(header, "Content-", 8)) {
/* find content=... string */
p = apr_strmatch(seek_content, buf+offs+pmatch[0].rm_so,
pmatch[0].rm_eo - pmatch[0].rm_so);
@@ -677,7 +696,7 @@ static meta *metafix(request_rec *r, const char *buf, apr_size_t len)
if ((*p == '\'') || (*p == '"')) {
delim = *p++;
for (q = p; *q && *q != delim; ++q);
- /* No terminating delimiter found? Skip the boggus directive */
+ /* No terminating delimiter found? Skip the bogus directive */
if (*q != delim)
break;
} else {
@@ -688,7 +707,7 @@ static meta *metafix(request_rec *r, const char *buf, apr_size_t len)
}
}
}
- else if (!strncasecmp(header, "Content-Type", 12)) {
+ else if (!ap_cstr_casecmpn(header, "Content-Type", 12)) {
ret = apr_palloc(r->pool, sizeof(meta));
ret->start = offs+pmatch[0].rm_so;
ret->end = offs+pmatch[0].rm_eo;
@@ -817,8 +836,8 @@ static saxctxt *check_filter_init (ap_filter_t *f)
else if (!f->r->content_type) {
errmsg = "No content-type; bailing out of proxy-html filter";
}
- else if (strncasecmp(f->r->content_type, "text/html", 9) &&
- strncasecmp(f->r->content_type,
+ else if (ap_cstr_casecmpn(f->r->content_type, "text/html", 9) &&
+ ap_cstr_casecmpn(f->r->content_type,
"application/xhtml+xml", 21)) {
errmsg = "Non-HTML content; not inserting proxy-html filter";
}
diff --git a/modules/filters/mod_reflector.c b/modules/filters/mod_reflector.c
index 961092d..5979cb8 100644
--- a/modules/filters/mod_reflector.c
+++ b/modules/filters/mod_reflector.c
@@ -91,11 +91,16 @@ static int reflector_handler(request_rec * r)
/* reflect the content length, if present */
if ((content_length = apr_table_get(r->headers_in, "Content-Length"))) {
- apr_off_t offset;
+ apr_off_t clen;
- apr_strtoff(&offset, content_length, NULL, 10);
- ap_set_content_length(r, offset);
+ if (!ap_parse_strict_length(&clen, content_length)) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10243)
+ "reflector_handler: invalid content-length '%s'",
+ content_length);
+ return HTTP_BAD_REQUEST;
+ }
+ ap_set_content_length(r, clen);
}
/* reflect the content type, if present */
diff --git a/modules/filters/mod_reqtimeout.c b/modules/filters/mod_reqtimeout.c
index 538e9b1..0ebd78a 100644
--- a/modules/filters/mod_reqtimeout.c
+++ b/modules/filters/mod_reqtimeout.c
@@ -29,23 +29,29 @@
module AP_MODULE_DECLARE_DATA reqtimeout_module;
#define UNSET -1
-#define MRT_DEFAULT_HEADER_TIMEOUT 20
-#define MRT_DEFAULT_HEADER_MAX_TIMEOUT 40
-#define MRT_DEFAULT_HEADER_MIN_RATE 500
-#define MRT_DEFAULT_BODY_TIMEOUT 20
-#define MRT_DEFAULT_BODY_MAX_TIMEOUT 0
-#define MRT_DEFAULT_BODY_MIN_RATE 500
+#define MRT_DEFAULT_handshake_TIMEOUT 0 /* disabled */
+#define MRT_DEFAULT_handshake_MAX_TIMEOUT 0
+#define MRT_DEFAULT_handshake_MIN_RATE 0
+#define MRT_DEFAULT_header_TIMEOUT 20
+#define MRT_DEFAULT_header_MAX_TIMEOUT 40
+#define MRT_DEFAULT_header_MIN_RATE 500
+#define MRT_DEFAULT_body_TIMEOUT 20
+#define MRT_DEFAULT_body_MAX_TIMEOUT 0
+#define MRT_DEFAULT_body_MIN_RATE 500
typedef struct
{
- int header_timeout; /* timeout for reading the req hdrs in secs */
- int header_max_timeout; /* max timeout for req hdrs in secs */
- int header_min_rate; /* min rate for reading req hdrs in bytes/s */
- apr_time_t header_rate_factor;
- int body_timeout; /* timeout for reading the req body in secs */
- int body_max_timeout; /* max timeout for req body in secs */
- int body_min_rate; /* min rate for reading req body in bytes/s */
- apr_time_t body_rate_factor;
+ int timeout; /* timeout in secs */
+ int max_timeout; /* max timeout in secs */
+ int min_rate; /* min rate in bytes/s */
+ apr_time_t rate_factor; /* scale factor (#usecs per min_rate) */
+} reqtimeout_stage_t;
+
+typedef struct
+{
+ reqtimeout_stage_t handshake; /* Handshaking (TLS) */
+ reqtimeout_stage_t header; /* Reading the HTTP header */
+ reqtimeout_stage_t body; /* Reading the HTTP body */
} reqtimeout_srv_cfg;
/* this struct is used both as conn_config and as filter context */
@@ -53,17 +59,15 @@ typedef struct
{
apr_time_t timeout_at;
apr_time_t max_timeout_at;
- int min_rate;
- int new_timeout;
- int new_max_timeout;
+ reqtimeout_stage_t cur_stage;
int in_keep_alive;
char *type;
apr_socket_t *socket;
- apr_time_t rate_factor;
apr_bucket_brigade *tmpbb;
} reqtimeout_con_cfg;
static const char *const reqtimeout_filter_name = "reqtimeout";
+static int default_handshake_rate_factor;
static int default_header_rate_factor;
static int default_body_rate_factor;
@@ -75,7 +79,7 @@ static void extend_timeout(reqtimeout_con_cfg *ccfg, apr_bucket_brigade *bb)
if (apr_brigade_length(bb, 0, &len) != APR_SUCCESS || len <= 0)
return;
- new_timeout_at = ccfg->timeout_at + len * ccfg->rate_factor;
+ new_timeout_at = ccfg->timeout_at + len * ccfg->cur_stage.rate_factor;
if (ccfg->max_timeout_at > 0 && new_timeout_at > ccfg->max_timeout_at) {
ccfg->timeout_at = ccfg->max_timeout_at;
}
@@ -190,14 +194,14 @@ static apr_status_t reqtimeout_filter(ap_filter_t *f,
apr_brigade_cleanup(bb);
}
- if (ccfg->new_timeout > 0) {
+ if (ccfg->cur_stage.timeout > 0) {
/* set new timeout */
now = apr_time_now();
- ccfg->timeout_at = now + apr_time_from_sec(ccfg->new_timeout);
- ccfg->new_timeout = 0;
- if (ccfg->new_max_timeout > 0) {
- ccfg->max_timeout_at = now + apr_time_from_sec(ccfg->new_max_timeout);
- ccfg->new_max_timeout = 0;
+ ccfg->timeout_at = now + apr_time_from_sec(ccfg->cur_stage.timeout);
+ ccfg->cur_stage.timeout = 0;
+ if (ccfg->cur_stage.max_timeout > 0) {
+ ccfg->max_timeout_at = now + apr_time_from_sec(ccfg->cur_stage.max_timeout);
+ ccfg->cur_stage.max_timeout = 0;
}
}
else if (ccfg->timeout_at == 0) {
@@ -216,7 +220,7 @@ static apr_status_t reqtimeout_filter(ap_filter_t *f,
if (block == APR_NONBLOCK_READ || mode == AP_MODE_INIT
|| mode == AP_MODE_EATCRLF) {
rv = ap_get_brigade(f->next, bb, mode, block, readbytes);
- if (ccfg->min_rate > 0 && rv == APR_SUCCESS) {
+ if (ccfg->cur_stage.rate_factor && rv == APR_SUCCESS) {
extend_timeout(ccfg, bb);
}
return rv;
@@ -250,7 +254,7 @@ static apr_status_t reqtimeout_filter(ap_filter_t *f,
}
if (!APR_BRIGADE_EMPTY(bb)) {
- if (ccfg->min_rate > 0) {
+ if (ccfg->cur_stage.rate_factor) {
extend_timeout(ccfg, bb);
}
@@ -309,9 +313,9 @@ static apr_status_t reqtimeout_filter(ap_filter_t *f,
rv = ap_get_brigade(f->next, bb, mode, block, readbytes);
/* Don't extend the timeout in speculative mode, wait for
* the real (relevant) bytes to be asked later, within the
- * currently alloted time.
+ * currently allotted time.
*/
- if (ccfg->min_rate > 0 && rv == APR_SUCCESS
+ if (ccfg->cur_stage.rate_factor && rv == APR_SUCCESS
&& mode != AP_MODE_SPECULATIVE) {
extend_timeout(ccfg, bb);
}
@@ -350,6 +354,19 @@ static apr_status_t reqtimeout_eor(ap_filter_t *f, apr_bucket_brigade *bb)
return ap_pass_brigade(f->next, bb);
}
+#define INIT_STAGE(cfg, ccfg, stage) do { \
+ if (cfg->stage.timeout != UNSET) { \
+ ccfg->cur_stage.timeout = cfg->stage.timeout; \
+ ccfg->cur_stage.max_timeout = cfg->stage.max_timeout; \
+ ccfg->cur_stage.rate_factor = cfg->stage.rate_factor; \
+ } \
+ else { \
+ ccfg->cur_stage.timeout = MRT_DEFAULT_##stage##_TIMEOUT; \
+ ccfg->cur_stage.max_timeout = MRT_DEFAULT_##stage##_MAX_TIMEOUT; \
+ ccfg->cur_stage.rate_factor = default_##stage##_rate_factor; \
+ } \
+} while (0)
+
static int reqtimeout_init(conn_rec *c)
{
reqtimeout_con_cfg *ccfg;
@@ -358,7 +375,11 @@ static int reqtimeout_init(conn_rec *c)
cfg = ap_get_module_config(c->base_server->module_config,
&reqtimeout_module);
AP_DEBUG_ASSERT(cfg != NULL);
- if (cfg->header_timeout == 0 && cfg->body_timeout == 0) {
+
+ /* For compatibility, handshake timeout is disabled when UNSET (< 0) */
+ if (cfg->handshake.timeout <= 0
+ && cfg->header.timeout == 0
+ && cfg->body.timeout == 0) {
/* disabled for this vhost */
return DECLINED;
}
@@ -369,6 +390,11 @@ static int reqtimeout_init(conn_rec *c)
ap_set_module_config(c->conn_config, &reqtimeout_module, ccfg);
ap_add_output_filter(reqtimeout_filter_name, ccfg, NULL, c);
ap_add_input_filter(reqtimeout_filter_name, ccfg, NULL, c);
+
+ ccfg->type = "handshake";
+ if (cfg->handshake.timeout > 0) {
+ INIT_STAGE(cfg, ccfg, handshake);
+ }
}
/* we are not handling the connection, we just do initialization */
@@ -393,22 +419,11 @@ static void reqtimeout_before_header(request_rec *r, conn_rec *c)
/* (Re)set the state for this new request, but ccfg->socket and
* ccfg->tmpbb which have the lifetime of the connection.
*/
+ ccfg->type = "header";
ccfg->timeout_at = 0;
ccfg->max_timeout_at = 0;
ccfg->in_keep_alive = (c->keepalives > 0);
- ccfg->type = "header";
- if (cfg->header_timeout != UNSET) {
- ccfg->new_timeout = cfg->header_timeout;
- ccfg->new_max_timeout = cfg->header_max_timeout;
- ccfg->min_rate = cfg->header_min_rate;
- ccfg->rate_factor = cfg->header_rate_factor;
- }
- else {
- ccfg->new_timeout = MRT_DEFAULT_HEADER_TIMEOUT;
- ccfg->new_max_timeout = MRT_DEFAULT_HEADER_MAX_TIMEOUT;
- ccfg->min_rate = MRT_DEFAULT_HEADER_MIN_RATE;
- ccfg->rate_factor = default_header_rate_factor;
- }
+ INIT_STAGE(cfg, ccfg, header);
}
static int reqtimeout_before_body(request_rec *r)
@@ -421,64 +436,61 @@ static int reqtimeout_before_body(request_rec *r)
/* not configured for this connection */
return OK;
}
- cfg = ap_get_module_config(r->connection->base_server->module_config,
- &reqtimeout_module);
+ cfg = ap_get_module_config(r->server->module_config,
+ &reqtimeout_module);
AP_DEBUG_ASSERT(cfg != NULL);
+ ccfg->type = "body";
ccfg->timeout_at = 0;
ccfg->max_timeout_at = 0;
- ccfg->type = "body";
if (r->method_number == M_CONNECT) {
/* disabled for a CONNECT request */
- ccfg->new_timeout = 0;
- }
- else if (cfg->body_timeout != UNSET) {
- ccfg->new_timeout = cfg->body_timeout;
- ccfg->new_max_timeout = cfg->body_max_timeout;
- ccfg->min_rate = cfg->body_min_rate;
- ccfg->rate_factor = cfg->body_rate_factor;
+ ccfg->cur_stage.timeout = 0;
}
else {
- ccfg->new_timeout = MRT_DEFAULT_BODY_TIMEOUT;
- ccfg->new_max_timeout = MRT_DEFAULT_BODY_MAX_TIMEOUT;
- ccfg->min_rate = MRT_DEFAULT_BODY_MIN_RATE;
- ccfg->rate_factor = default_body_rate_factor;
+ INIT_STAGE(cfg, ccfg, body);
}
return OK;
}
+#define UNSET_STAGE(cfg, stage) do { \
+ cfg->stage.timeout = UNSET; \
+ cfg->stage.max_timeout = UNSET; \
+ cfg->stage.min_rate = UNSET; \
+} while (0)
+
static void *reqtimeout_create_srv_config(apr_pool_t *p, server_rec *s)
{
reqtimeout_srv_cfg *cfg = apr_pcalloc(p, sizeof(reqtimeout_srv_cfg));
- cfg->header_timeout = UNSET;
- cfg->header_max_timeout = UNSET;
- cfg->header_min_rate = UNSET;
- cfg->body_timeout = UNSET;
- cfg->body_max_timeout = UNSET;
- cfg->body_min_rate = UNSET;
+ UNSET_STAGE(cfg, handshake);
+ UNSET_STAGE(cfg, header);
+ UNSET_STAGE(cfg, body);
return cfg;
}
-#define MERGE_INT(cfg, b, a, val) cfg->val = (a->val == UNSET) ? b->val : a->val;
+#define MERGE_INT(cfg, base, add, val) \
+ cfg->val = (add->val == UNSET) ? base->val : add->val
+#define MERGE_STAGE(cfg, base, add, stage) do { \
+ MERGE_INT(cfg, base, add, stage.timeout); \
+ MERGE_INT(cfg, base, add, stage.max_timeout); \
+ MERGE_INT(cfg, base, add, stage.min_rate); \
+ cfg->stage.rate_factor = (cfg->stage.min_rate == UNSET) \
+ ? base->stage.rate_factor \
+ : add->stage.rate_factor; \
+} while (0)
+
static void *reqtimeout_merge_srv_config(apr_pool_t *p, void *base_, void *add_)
{
reqtimeout_srv_cfg *base = base_;
reqtimeout_srv_cfg *add = add_;
reqtimeout_srv_cfg *cfg = apr_pcalloc(p, sizeof(reqtimeout_srv_cfg));
- MERGE_INT(cfg, base, add, header_timeout);
- MERGE_INT(cfg, base, add, header_max_timeout);
- MERGE_INT(cfg, base, add, header_min_rate);
- MERGE_INT(cfg, base, add, body_timeout);
- MERGE_INT(cfg, base, add, body_max_timeout);
- MERGE_INT(cfg, base, add, body_min_rate);
-
- cfg->header_rate_factor = (cfg->header_min_rate == UNSET) ?
- base->header_rate_factor : add->header_rate_factor;
- cfg->body_rate_factor = (cfg->body_min_rate == UNSET) ?
- base->body_rate_factor : add->body_rate_factor;
+ MERGE_STAGE(cfg, base, add, handshake);
+ MERGE_STAGE(cfg, base, add, header);
+ MERGE_STAGE(cfg, base, add, body);
+
return cfg;
}
@@ -506,66 +518,59 @@ static const char *set_reqtimeout_param(reqtimeout_srv_cfg *conf,
{
const char *ret = NULL;
char *rate_str = NULL, *initial_str, *max_str = NULL;
- int rate = 0, initial = 0, max = 0;
- enum { PARAM_HEADER, PARAM_BODY } type;
+ reqtimeout_stage_t *stage;
- if (!strcasecmp(key, "header")) {
- type = PARAM_HEADER;
+ if (!strcasecmp(key, "handshake")) {
+ stage = &conf->handshake;
+ }
+ else if (!strcasecmp(key, "header")) {
+ stage = &conf->header;
}
else if (!strcasecmp(key, "body")) {
- type = PARAM_BODY;
+ stage = &conf->body;
}
else {
return "Unknown RequestReadTimeout parameter";
}
+ memset(stage, 0, sizeof(*stage));
+
if ((rate_str = ap_strcasestr(val, ",minrate="))) {
initial_str = apr_pstrndup(p, val, rate_str - val);
rate_str += strlen(",minrate=");
- ret = parse_int(p, rate_str, &rate);
+ ret = parse_int(p, rate_str, &stage->min_rate);
if (ret)
return ret;
- if (rate == 0)
+ if (stage->min_rate == 0)
return "Minimum data rate must be larger than 0";
if ((max_str = strchr(initial_str, '-'))) {
*max_str++ = '\0';
- ret = parse_int(p, max_str, &max);
+ ret = parse_int(p, max_str, &stage->max_timeout);
if (ret)
return ret;
}
- ret = parse_int(p, initial_str, &initial);
+ ret = parse_int(p, initial_str, &stage->timeout);
}
else {
if (ap_strchr_c(val, '-'))
return "Must set MinRate option if using timeout range";
- ret = parse_int(p, val, &initial);
+ ret = parse_int(p, val, &stage->timeout);
}
-
if (ret)
return ret;
- if (max && initial >= max) {
+ if (stage->max_timeout && stage->timeout >= stage->max_timeout) {
return "Maximum timeout must be larger than initial timeout";
}
- if (type == PARAM_HEADER) {
- conf->header_timeout = initial;
- conf->header_max_timeout = max;
- conf->header_min_rate = rate;
- if (rate)
- conf->header_rate_factor = apr_time_from_sec(1) / rate;
- }
- else {
- conf->body_timeout = initial;
- conf->body_max_timeout = max;
- conf->body_min_rate = rate;
- if (rate)
- conf->body_rate_factor = apr_time_from_sec(1) / rate;
+ if (stage->min_rate) {
+ stage->rate_factor = apr_time_from_sec(1) / stage->min_rate;
}
- return ret;
+
+ return NULL;
}
static const char *set_reqtimeouts(cmd_parms *cmd, void *mconfig,
@@ -603,8 +608,7 @@ static void reqtimeout_hooks(apr_pool_t *pool)
{
/*
* mod_ssl is AP_FTYPE_CONNECTION + 5 and mod_reqtimeout needs to
- * be called before mod_ssl. Otherwise repeated reads during the ssl
- * handshake can prevent the timeout from triggering.
+ * be called before mod_ssl for the handshake stage to catch SSL traffic.
*/
ap_register_input_filter(reqtimeout_filter_name, reqtimeout_filter, NULL,
AP_FTYPE_CONNECTION + 8);
@@ -621,28 +625,37 @@ static void reqtimeout_hooks(apr_pool_t *pool)
* mod_reqtimeout needs to be called before ap_process_http_request (which
* is run at APR_HOOK_REALLY_LAST) but after all other protocol modules.
* This ensures that it only influences normal http connections and not
- * e.g. mod_ftp. Also, if mod_reqtimeout used the pre_connection hook, it
- * would be inserted on mod_proxy's backend connections.
+ * e.g. mod_ftp. We still process it first though, for the handshake stage
+ * to work with/before mod_ssl, but since it's disabled by default it won't
+ * influence non-HTTP modules unless configured explicitly. Also, if
+ * mod_reqtimeout used the pre_connection hook, it would be inserted on
+ * mod_proxy's backend connections, and we don't want this.
*/
- ap_hook_process_connection(reqtimeout_init, NULL, NULL, APR_HOOK_LAST);
+ ap_hook_process_connection(reqtimeout_init, NULL, NULL, APR_HOOK_FIRST);
ap_hook_pre_read_request(reqtimeout_before_header, NULL, NULL,
APR_HOOK_MIDDLE);
ap_hook_post_read_request(reqtimeout_before_body, NULL, NULL,
APR_HOOK_MIDDLE);
-#if MRT_DEFAULT_HEADER_MIN_RATE > 0
- default_header_rate_factor = apr_time_from_sec(1) / MRT_DEFAULT_HEADER_MIN_RATE;
+#if MRT_DEFAULT_handshake_MIN_RATE
+ default_handshake_rate_factor = apr_time_from_sec(1) /
+ MRT_DEFAULT_handshake_MIN_RATE;
+#endif
+#if MRT_DEFAULT_header_MIN_RATE
+ default_header_rate_factor = apr_time_from_sec(1) /
+ MRT_DEFAULT_header_MIN_RATE;
#endif
-#if MRT_DEFAULT_BODY_MIN_RATE > 0
- default_body_rate_factor = apr_time_from_sec(1) / MRT_DEFAULT_BODY_MIN_RATE;
+#if MRT_DEFAULT_body_MIN_RATE
+ default_body_rate_factor = apr_time_from_sec(1) /
+ MRT_DEFAULT_body_MIN_RATE;
#endif
}
static const command_rec reqtimeout_cmds[] = {
AP_INIT_RAW_ARGS("RequestReadTimeout", set_reqtimeouts, NULL, RSRC_CONF,
- "Set various timeout parameters for reading request "
- "headers and body"),
+ "Set various timeout parameters for TLS handshake and/or "
+ "reading request headers and body"),
{NULL}
};
diff --git a/modules/filters/mod_request.c b/modules/filters/mod_request.c
index 21db7de..1768edc 100644
--- a/modules/filters/mod_request.c
+++ b/modules/filters/mod_request.c
@@ -73,10 +73,8 @@ static apr_status_t keep_body_filter(ap_filter_t *f, apr_bucket_brigade *b,
apr_bucket *bucket;
apr_off_t len = 0;
-
if (!ctx) {
const char *lenp;
- char *endstr = NULL;
request_dir_conf *dconf = ap_get_module_config(f->r->per_dir_config,
&request_module);
@@ -93,13 +91,12 @@ static apr_status_t keep_body_filter(ap_filter_t *f, apr_bucket_brigade *b,
if (lenp) {
/* Protects against over/underflow, non-digit chars in the
- * string (excluding leading space) (the endstr checks)
- * and a negative number. */
- if (apr_strtoff(&ctx->remaining, lenp, &endstr, 10)
- || endstr == lenp || *endstr || ctx->remaining < 0) {
-
+ * string, leading plus/minus signs, trailing characters and
+ * a negative number.
+ */
+ if (!ap_parse_strict_length(&ctx->remaining, lenp)) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, APLOGNO(01411)
- "Invalid Content-Length");
+ "Invalid Content-Length '%s'", lenp);
ap_remove_input_filter(f);
return bail_out_on_error(b, f, HTTP_REQUEST_ENTITY_TOO_LARGE);
@@ -121,7 +118,6 @@ static apr_status_t keep_body_filter(ap_filter_t *f, apr_bucket_brigade *b,
f->r->kept_body = apr_brigade_create(f->r->pool, f->r->connection->bucket_alloc);
ctx->remaining = dconf->keep_body;
-
}
/* get the brigade from upstream, and read it in to get its length */
@@ -264,8 +260,8 @@ static apr_status_t kept_body_filter(ap_filter_t *f, apr_bucket_brigade *b,
ctx->remaining -= readbytes;
ctx->offset += readbytes;
- return APR_SUCCESS;
+ return APR_SUCCESS;
}
/**
@@ -311,18 +307,18 @@ static void ap_request_insert_filter(request_rec * r)
NULL, r, r->connection);
}
}
-
}
-/**
- * Remove the kept_body and keep body filters from this specific request.
+/*
+ * Remove the kept_body and keep_body filters from this specific request.
*/
-static void ap_request_remove_filter(request_rec * r)
+static void ap_request_remove_filter(request_rec *r)
{
- ap_filter_t * f = r->input_filters;
+ ap_filter_t *f = r->input_filters;
+
while (f) {
if (f->frec->filter_func.in_func == kept_body_filter ||
- f->frec->filter_func.in_func == keep_body_filter) {
+ f->frec->filter_func.in_func == keep_body_filter) {
ap_remove_input_filter(f);
}
f = f->next;
diff --git a/modules/filters/mod_sed.c b/modules/filters/mod_sed.c
index 346c210..12cb04a 100644
--- a/modules/filters/mod_sed.c
+++ b/modules/filters/mod_sed.c
@@ -51,7 +51,7 @@ typedef struct sed_filter_ctxt
apr_bucket_brigade *bbinp;
char *outbuf;
char *curoutbuf;
- int bufsize;
+ apr_size_t bufsize;
apr_pool_t *tpool;
int numbuckets;
} sed_filter_ctxt;
@@ -59,7 +59,7 @@ typedef struct sed_filter_ctxt
module AP_MODULE_DECLARE_DATA sed_module;
/* This function will be call back from libsed functions if there is any error
- * happend during execution of sed scripts
+ * happened during execution of sed scripts
*/
static apr_status_t log_sed_errf(void *data, const char *error)
{
@@ -100,7 +100,7 @@ static void alloc_outbuf(sed_filter_ctxt* ctx)
/* append_bucket
* Allocate a new bucket from buf and sz and append to ctx->bb
*/
-static apr_status_t append_bucket(sed_filter_ctxt* ctx, char* buf, int sz)
+static apr_status_t append_bucket(sed_filter_ctxt* ctx, char* buf, apr_size_t sz)
{
apr_status_t status = APR_SUCCESS;
apr_bucket *b;
@@ -133,7 +133,7 @@ static apr_status_t append_bucket(sed_filter_ctxt* ctx, char* buf, int sz)
*/
static apr_status_t flush_output_buffer(sed_filter_ctxt *ctx)
{
- int size = ctx->curoutbuf - ctx->outbuf;
+ apr_size_t size = ctx->curoutbuf - ctx->outbuf;
char *out;
apr_status_t status = APR_SUCCESS;
if ((ctx->outbuf == NULL) || (size <=0))
@@ -147,12 +147,12 @@ static apr_status_t flush_output_buffer(sed_filter_ctxt *ctx)
/* This is a call back function. When libsed wants to generate the output,
* this function will be invoked.
*/
-static apr_status_t sed_write_output(void *dummy, char *buf, int sz)
+static apr_status_t sed_write_output(void *dummy, char *buf, apr_size_t sz)
{
/* dummy is basically filter context. Context is passed during invocation
* of sed_eval_buffer
*/
- int remainbytes = 0;
+ apr_size_t remainbytes = 0;
apr_status_t status = APR_SUCCESS;
sed_filter_ctxt *ctx = (sed_filter_ctxt *) dummy;
if (ctx->outbuf == NULL) {
@@ -168,21 +168,29 @@ static apr_status_t sed_write_output(void *dummy, char *buf, int sz)
}
/* buffer is now full */
status = append_bucket(ctx, ctx->outbuf, ctx->bufsize);
- /* old buffer is now used so allocate new buffer */
- alloc_outbuf(ctx);
- /* if size is bigger than the allocated buffer directly add to output
- * brigade */
- if ((status == APR_SUCCESS) && (sz >= ctx->bufsize)) {
- char* newbuf = apr_pmemdup(ctx->tpool, buf, sz);
- status = append_bucket(ctx, newbuf, sz);
- /* pool might get clear after append_bucket */
- if (ctx->outbuf == NULL) {
+ if (status == APR_SUCCESS) {
+ /* if size is bigger than the allocated buffer directly add to output
+ * brigade */
+ if (sz >= ctx->bufsize) {
+ char* newbuf = apr_pmemdup(ctx->tpool, buf, sz);
+ status = append_bucket(ctx, newbuf, sz);
+ if (status == APR_SUCCESS) {
+ /* old buffer is now used so allocate new buffer */
+ alloc_outbuf(ctx);
+ }
+ else {
+ clear_ctxpool(ctx);
+ }
+ }
+ else {
+ /* old buffer is now used so allocate new buffer */
alloc_outbuf(ctx);
+ memcpy(ctx->curoutbuf, buf, sz);
+ ctx->curoutbuf += sz;
}
}
else {
- memcpy(ctx->curoutbuf, buf, sz);
- ctx->curoutbuf += sz;
+ clear_ctxpool(ctx);
}
}
else {
@@ -254,6 +262,7 @@ static apr_status_t init_context(ap_filter_t *f, sed_expr_config *sed_cfg, int u
ctx->bufsize = MODSED_OUTBUF_SIZE;
if (usetpool) {
apr_pool_create(&(ctx->tpool), r->pool);
+ apr_pool_tag(ctx->tpool, "sed_tpool");
}
else {
ctx->tpool = r->pool;
@@ -268,7 +277,7 @@ static apr_status_t sed_response_filter(ap_filter_t *f,
apr_bucket_brigade *bb)
{
apr_bucket *b;
- apr_status_t status;
+ apr_status_t status = APR_SUCCESS;
sed_config *cfg = ap_get_module_config(f->r->per_dir_config,
&sed_module);
sed_filter_ctxt *ctx = f->ctx;
@@ -293,9 +302,9 @@ static apr_status_t sed_response_filter(ap_filter_t *f,
return status;
ctx = f->ctx;
apr_table_unset(f->r->headers_out, "Content-Length");
- }
- ctx->bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
+ ctx->bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
+ }
/* Here is the main logic. Iterate through all the buckets, read the
* content of the bucket, call sed_eval_buffer on the data.
@@ -317,63 +326,52 @@ static apr_status_t sed_response_filter(ap_filter_t *f,
* in sed's internal buffer which can't be flushed until new line
* character is arrived.
*/
- for (b = APR_BRIGADE_FIRST(bb); b != APR_BRIGADE_SENTINEL(bb);) {
- const char *buf = NULL;
- apr_size_t bytes = 0;
+ while (!APR_BRIGADE_EMPTY(bb)) {
+ b = APR_BRIGADE_FIRST(bb);
if (APR_BUCKET_IS_EOS(b)) {
- apr_bucket *b1 = APR_BUCKET_NEXT(b);
/* Now clean up the internal sed buffer */
sed_finalize_eval(&ctx->eval, ctx);
status = flush_output_buffer(ctx);
if (status != APR_SUCCESS) {
- clear_ctxpool(ctx);
- return status;
+ break;
}
+ /* Move the eos bucket to ctx->bb brigade */
APR_BUCKET_REMOVE(b);
- /* Insert the eos bucket to ctx->bb brigade */
APR_BRIGADE_INSERT_TAIL(ctx->bb, b);
- b = b1;
}
else if (APR_BUCKET_IS_FLUSH(b)) {
- apr_bucket *b1 = APR_BUCKET_NEXT(b);
- APR_BUCKET_REMOVE(b);
status = flush_output_buffer(ctx);
if (status != APR_SUCCESS) {
- clear_ctxpool(ctx);
- return status;
+ break;
}
+ /* Move the flush bucket to ctx->bb brigade */
+ APR_BUCKET_REMOVE(b);
APR_BRIGADE_INSERT_TAIL(ctx->bb, b);
- b = b1;
}
- else if (APR_BUCKET_IS_METADATA(b)) {
- b = APR_BUCKET_NEXT(b);
- }
- else if (apr_bucket_read(b, &buf, &bytes, APR_BLOCK_READ)
- == APR_SUCCESS) {
- apr_bucket *b1 = APR_BUCKET_NEXT(b);
- status = sed_eval_buffer(&ctx->eval, buf, bytes, ctx);
- if (status != APR_SUCCESS) {
- clear_ctxpool(ctx);
- return status;
+ else {
+ if (!APR_BUCKET_IS_METADATA(b)) {
+ const char *buf = NULL;
+ apr_size_t bytes = 0;
+
+ status = apr_bucket_read(b, &buf, &bytes, APR_BLOCK_READ);
+ if (status == APR_SUCCESS) {
+ status = sed_eval_buffer(&ctx->eval, buf, bytes, ctx);
+ }
+ if (status != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, status, f->r, APLOGNO(10394) "error evaluating sed on output");
+ break;
+ }
}
- APR_BUCKET_REMOVE(b);
apr_bucket_delete(b);
- b = b1;
- }
- else {
- apr_bucket *b1 = APR_BUCKET_NEXT(b);
- APR_BUCKET_REMOVE(b);
- b = b1;
}
}
- apr_brigade_cleanup(bb);
- status = flush_output_buffer(ctx);
- if (status != APR_SUCCESS) {
- clear_ctxpool(ctx);
- return status;
+ if (status == APR_SUCCESS) {
+ status = flush_output_buffer(ctx);
}
if (!APR_BRIGADE_EMPTY(ctx->bb)) {
- status = ap_pass_brigade(f->next, ctx->bb);
+ if (status == APR_SUCCESS) {
+ status = ap_pass_brigade(f->next, ctx->bb);
+ }
apr_brigade_cleanup(ctx->bb);
}
clear_ctxpool(ctx);
@@ -424,7 +422,7 @@ static apr_status_t sed_request_filter(ap_filter_t *f,
* the buckets in bbinp and read the data from buckets and invoke
* sed_eval_buffer on the data. libsed will generate its output using
* sed_write_output which will add data in ctx->bb. Do it until it have
- * atleast one bucket in ctx->bb. At the end of data eos bucket
+ * at least one bucket in ctx->bb. At the end of data eos bucket
* should be there.
*
* Once eos bucket is seen, then invoke sed_finalize_eval to clear the
@@ -466,8 +464,10 @@ static apr_status_t sed_request_filter(ap_filter_t *f,
if (apr_bucket_read(b, &buf, &bytes, APR_BLOCK_READ)
== APR_SUCCESS) {
status = sed_eval_buffer(&ctx->eval, buf, bytes, ctx);
- if (status != APR_SUCCESS)
+ if (status != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, status, f->r, APLOGNO(10395) "error evaluating sed on input");
return status;
+ }
flush_output_buffer(ctx);
}
}
diff --git a/modules/filters/mod_substitute.c b/modules/filters/mod_substitute.c
index b7d5296..d454bf3 100644
--- a/modules/filters/mod_substitute.c
+++ b/modules/filters/mod_substitute.c
@@ -306,7 +306,7 @@ static apr_status_t do_pattmatch(ap_filter_t *f, apr_bucket *inb,
}
else {
apr_size_t repl_len;
- /* acount for string before the match */
+ /* account for string before the match */
if (space_left <= regm[0].rm_so)
return APR_ENOMEM;
space_left -= regm[0].rm_so;
@@ -402,6 +402,7 @@ static apr_status_t substitute_filter(ap_filter_t *f, apr_bucket_brigade *bb)
ctx->passbb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
/* Create our temporary pool only once */
apr_pool_create(&(ctx->tpool), f->r->pool);
+ apr_pool_tag(ctx->tpool, "substitute_tpool");
apr_table_unset(f->r->headers_out, "Content-Length");
}
@@ -667,8 +668,10 @@ static const char *set_pattern(cmd_parms *cmd, void *cfg, const char *line)
/* first see if we can compile the regex */
if (!is_pattern) {
- r = ap_pregcomp(cmd->pool, from, AP_REG_EXTENDED |
- (ignore_case ? AP_REG_ICASE : 0));
+ int flags = AP_REG_NO_DEFAULT
+ | (ap_regcomp_get_default_cflags() & AP_REG_DOLLAR_ENDONLY)
+ | (ignore_case ? AP_REG_ICASE : 0);
+ r = ap_pregcomp(cmd->pool, from, flags);
if (!r)
return "Substitute could not compile regex";
}
diff --git a/modules/filters/mod_xml2enc.c b/modules/filters/mod_xml2enc.c
index 05a4e9a..eb05c18 100644
--- a/modules/filters/mod_xml2enc.c
+++ b/modules/filters/mod_xml2enc.c
@@ -23,9 +23,28 @@
#include <ctype.h>
+/* libxml2 includes unicode/[...].h files which uses C++ comments */
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic warning "-Wcomment"
+#elif defined(__GNUC__)
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic warning "-Wcomment"
+#endif
+#endif
+
/* libxml2 */
#include <libxml/encoding.h>
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#elif defined(__GNUC__)
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
+#pragma GCC diagnostic pop
+#endif
+#endif
+
#include "http_protocol.h"
#include "http_config.h"
#include "http_log.h"
@@ -51,7 +70,7 @@ module AP_MODULE_DECLARE_DATA xml2enc_module;
(((enc)!=XML_CHAR_ENCODING_NONE)&&((enc)!=XML_CHAR_ENCODING_ERROR))
/*
- * XXX: Check all those ap_assert()s ans replace those that should not happen
+ * XXX: Check all those ap_assert()s and replace those that should not happen
* XXX: with AP_DEBUG_ASSERT and those that may happen with proper error
* XXX: handling.
*/
@@ -187,11 +206,11 @@ static void sniff_encoding(request_rec* r, xml2ctx* ctx)
}
}
}
-
+
/* to sniff, first we look for BOM */
if (ctx->xml2enc == XML_CHAR_ENCODING_NONE) {
- ctx->xml2enc = xmlDetectCharEncoding((const xmlChar*)ctx->buf,
- ctx->bytes);
+ ctx->xml2enc = xmlDetectCharEncoding((const unsigned char*)ctx->buf,
+ ctx->bytes);
if (HAVE_ENCODING(ctx->xml2enc)) {
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(01432)
"Got charset from XML rules.") ;
@@ -304,7 +323,7 @@ static apr_status_t xml2enc_ffunc(ap_filter_t* f, apr_bucket_brigade* bb)
apr_bucket* bstart;
apr_size_t insz = 0;
int pending_meta = 0;
- char *ctype;
+ char *mtype;
char *p;
if (!ctx || !f->r->content_type) {
@@ -313,13 +332,17 @@ static apr_status_t xml2enc_ffunc(ap_filter_t* f, apr_bucket_brigade* bb)
return ap_pass_brigade(f->next, bb) ;
}
- ctype = apr_pstrdup(f->r->pool, f->r->content_type);
- for (p = ctype; *p; ++p)
- if (isupper(*p))
- *p = tolower(*p);
-
- /* only act if starts-with "text/" or contains "xml" */
- if (strncmp(ctype, "text/", 5) && !strstr(ctype, "xml")) {
+ /* Extract the media type, ignoring parameters in content-type. */
+ mtype = apr_pstrdup(f->r->pool, f->r->content_type);
+ if ((p = ap_strchr(mtype, ';')) != NULL) *p = '\0';
+ ap_str_tolower(mtype);
+
+ /* Accept text/ types, plus any XML media type per RFC 7303. */
+ if (!(strncmp(mtype, "text/", 5) == 0
+ || strcmp(mtype, "application/xml") == 0
+ || (strlen(mtype) > 7 /* minimum 'a/b+xml' length */
+ && (p = strstr(mtype, "+xml")) != NULL
+ && strlen(p) == 4 /* ensures +xml is a suffix */))) {
ap_remove_output_filter(f);
return ap_pass_brigade(f->next, bb) ;
}
diff --git a/modules/filters/regexp.h b/modules/filters/regexp.h
index 6af8912..dc4993a 100644
--- a/modules/filters/regexp.h
+++ b/modules/filters/regexp.h
@@ -93,8 +93,8 @@ extern void command_errf(sed_commands_t *commands, const char *fmt, ...)
#define SEDERR_COMES "cannot open %s"
#define SEDERR_CCMES "cannot create %s"
#define SEDERR_TMLNMES "too many line numbers"
-#define SEDERR_TMAMES "too many appends after line %lld"
-#define SEDERR_TMRMES "too many reads after line %lld"
+#define SEDERR_TMAMES "too many appends after line %" APR_INT64_T_FMT
+#define SEDERR_TMRMES "too many reads after line %" APR_INT64_T_FMT
#define SEDERR_DOORNG "``\\digit'' out of range: %s"
#define SEDERR_EDMOSUB "ending delimiter missing on substitution: %s"
#define SEDERR_EDMOSTR "ending delimiter missing on string: %s"
diff --git a/modules/filters/sed1.c b/modules/filters/sed1.c
index be03506..047f49b 100644
--- a/modules/filters/sed1.c
+++ b/modules/filters/sed1.c
@@ -71,7 +71,7 @@ static apr_status_t dosub(sed_eval_t *eval, char *rhsbuf, int n,
static char *place(sed_eval_t *eval, char *asp, char *al1, char *al2);
static apr_status_t command(sed_eval_t *eval, sed_reptr_t *ipc,
step_vars_storage *step_vars);
-static apr_status_t wline(sed_eval_t *eval, char *buf, int sz);
+static apr_status_t wline(sed_eval_t *eval, char *buf, apr_size_t sz);
static apr_status_t arout(sed_eval_t *eval);
static void eval_errf(sed_eval_t *eval, const char *fmt, ...)
@@ -87,18 +87,20 @@ static void eval_errf(sed_eval_t *eval, const char *fmt, ...)
}
#define INIT_BUF_SIZE 1024
+#define MAX_BUF_SIZE 1024*8192
/*
* grow_buffer
*/
-static void grow_buffer(apr_pool_t *pool, char **buffer,
- char **spend, unsigned int *cursize,
- unsigned int newsize)
+static apr_status_t grow_buffer(apr_pool_t *pool, char **buffer,
+ char **spend, apr_size_t *cursize,
+ apr_size_t newsize)
{
char* newbuffer = NULL;
- int spendsize = 0;
- if (*cursize >= newsize)
- return;
+ apr_size_t spendsize = 0;
+ if (*cursize >= newsize) {
+ return APR_SUCCESS;
+ }
/* Avoid number of times realloc is called. It could cause huge memory
* requirement if line size is huge e.g 2 MB */
if (newsize < *cursize * 2) {
@@ -107,6 +109,9 @@ static void grow_buffer(apr_pool_t *pool, char **buffer,
/* Align it to 4 KB boundary */
newsize = (newsize + ((1 << 12) - 1)) & ~((1 << 12) - 1);
+ if (newsize > MAX_BUF_SIZE) {
+ return APR_ENOMEM;
+ }
newbuffer = apr_pcalloc(pool, newsize);
if (*spend && *buffer && (*cursize > 0)) {
spendsize = *spend - *buffer;
@@ -119,123 +124,168 @@ static void grow_buffer(apr_pool_t *pool, char **buffer,
if (spend != buffer) {
*spend = *buffer + spendsize;
}
+ return APR_SUCCESS;
}
/*
* grow_line_buffer
*/
-static void grow_line_buffer(sed_eval_t *eval, int newsize)
+static apr_status_t grow_line_buffer(sed_eval_t *eval, apr_size_t newsize)
{
- grow_buffer(eval->pool, &eval->linebuf, &eval->lspend,
+ return grow_buffer(eval->pool, &eval->linebuf, &eval->lspend,
&eval->lsize, newsize);
}
/*
* grow_hold_buffer
*/
-static void grow_hold_buffer(sed_eval_t *eval, int newsize)
+static apr_status_t grow_hold_buffer(sed_eval_t *eval, apr_size_t newsize)
{
- grow_buffer(eval->pool, &eval->holdbuf, &eval->hspend,
+ return grow_buffer(eval->pool, &eval->holdbuf, &eval->hspend,
&eval->hsize, newsize);
}
/*
* grow_gen_buffer
*/
-static void grow_gen_buffer(sed_eval_t *eval, int newsize,
+static apr_status_t grow_gen_buffer(sed_eval_t *eval, apr_size_t newsize,
char **gspend)
{
+ apr_status_t rc = 0;
if (gspend == NULL) {
gspend = &eval->genbuf;
}
- grow_buffer(eval->pool, &eval->genbuf, gspend,
- &eval->gsize, newsize);
- eval->lcomend = &eval->genbuf[71];
+ rc = grow_buffer(eval->pool, &eval->genbuf, gspend,
+ &eval->gsize, newsize);
+ if (rc == APR_SUCCESS) {
+ eval->lcomend = &eval->genbuf[71];
+ }
+ return rc;
}
/*
* appendmem_to_linebuf
*/
-static void appendmem_to_linebuf(sed_eval_t *eval, const char* sz, int len)
+static apr_status_t appendmem_to_linebuf(sed_eval_t *eval, const char* sz, apr_size_t len)
{
- unsigned int reqsize = (eval->lspend - eval->linebuf) + len;
+ apr_status_t rc = 0;
+ apr_size_t reqsize = (eval->lspend - eval->linebuf) + len;
if (eval->lsize < reqsize) {
- grow_line_buffer(eval, reqsize);
+ rc = grow_line_buffer(eval, reqsize);
+ if (rc != APR_SUCCESS) {
+ return rc;
+ }
}
memcpy(eval->lspend, sz, len);
eval->lspend += len;
+ return APR_SUCCESS;
}
/*
* append_to_linebuf
*/
-static void append_to_linebuf(sed_eval_t *eval, const char* sz)
+static apr_status_t append_to_linebuf(sed_eval_t *eval, const char* sz,
+ step_vars_storage *step_vars)
{
- int len = strlen(sz);
+ apr_size_t len = strlen(sz);
+ char *old_linebuf = eval->linebuf;
+ apr_status_t rc = 0;
/* Copy string including null character */
- appendmem_to_linebuf(eval, sz, len + 1);
+ rc = appendmem_to_linebuf(eval, sz, len + 1);
+ if (rc != APR_SUCCESS) {
+ return rc;
+ }
--eval->lspend; /* lspend will now point to NULL character */
+ /* Sync step_vars after a possible linebuf expansion */
+ if (step_vars && old_linebuf != eval->linebuf) {
+ if (step_vars->loc1) {
+ step_vars->loc1 = step_vars->loc1 - old_linebuf + eval->linebuf;
+ }
+ if (step_vars->loc2) {
+ step_vars->loc2 = step_vars->loc2 - old_linebuf + eval->linebuf;
+ }
+ if (step_vars->locs) {
+ step_vars->locs = step_vars->locs - old_linebuf + eval->linebuf;
+ }
+ }
+ return APR_SUCCESS;
}
/*
* copy_to_linebuf
*/
-static void copy_to_linebuf(sed_eval_t *eval, const char* sz)
+static apr_status_t copy_to_linebuf(sed_eval_t *eval, const char* sz,
+ step_vars_storage *step_vars)
{
eval->lspend = eval->linebuf;
- append_to_linebuf(eval, sz);
+ return append_to_linebuf(eval, sz, step_vars);
}
/*
* append_to_holdbuf
*/
-static void append_to_holdbuf(sed_eval_t *eval, const char* sz)
+static apr_status_t append_to_holdbuf(sed_eval_t *eval, const char* sz)
{
- int len = strlen(sz);
- unsigned int reqsize = (eval->hspend - eval->holdbuf) + len + 1;
+ apr_size_t len = strlen(sz);
+ apr_size_t reqsize = (eval->hspend - eval->holdbuf) + len + 1;
+ apr_status_t rc = 0;
if (eval->hsize <= reqsize) {
- grow_hold_buffer(eval, reqsize);
+ rc = grow_hold_buffer(eval, reqsize);
+ if (rc != APR_SUCCESS) {
+ return rc;
+ }
}
memcpy(eval->hspend, sz, len + 1);
/* hspend will now point to NULL character */
eval->hspend += len;
+ return APR_SUCCESS;
}
/*
* copy_to_holdbuf
*/
-static void copy_to_holdbuf(sed_eval_t *eval, const char* sz)
+static apr_status_t copy_to_holdbuf(sed_eval_t *eval, const char* sz)
{
eval->hspend = eval->holdbuf;
- append_to_holdbuf(eval, sz);
+ return append_to_holdbuf(eval, sz);
}
/*
* append_to_genbuf
*/
-static void append_to_genbuf(sed_eval_t *eval, const char* sz, char **gspend)
+static apr_status_t append_to_genbuf(sed_eval_t *eval, const char* sz, char **gspend)
{
- int len = strlen(sz);
- unsigned int reqsize = (*gspend - eval->genbuf) + len + 1;
+ apr_size_t len = strlen(sz);
+ apr_size_t reqsize = (*gspend - eval->genbuf) + len + 1;
+ apr_status_t rc = 0;
if (eval->gsize < reqsize) {
- grow_gen_buffer(eval, reqsize, gspend);
+ rc = grow_gen_buffer(eval, reqsize, gspend);
+ if (rc != APR_SUCCESS) {
+ return rc;
+ }
}
memcpy(*gspend, sz, len + 1);
/* *gspend will now point to NULL character */
*gspend += len;
+ return APR_SUCCESS;
}
/*
* copy_to_genbuf
*/
-static void copy_to_genbuf(sed_eval_t *eval, const char* sz)
+static apr_status_t copy_to_genbuf(sed_eval_t *eval, const char* sz)
{
- int len = strlen(sz);
- unsigned int reqsize = len + 1;
+ apr_size_t len = strlen(sz);
+ apr_size_t reqsize = len + 1;
+ apr_status_t rc = APR_SUCCESS;;
if (eval->gsize < reqsize) {
- grow_gen_buffer(eval, reqsize, NULL);
+ rc = grow_gen_buffer(eval, reqsize, NULL);
+ if (rc != APR_SUCCESS) {
+ return rc;
+ }
}
memcpy(eval->genbuf, sz, len + 1);
+ return rc;
}
/*
@@ -353,7 +403,7 @@ apr_status_t sed_eval_file(sed_eval_t *eval, apr_file_t *fin, void *fout)
/*
* sed_eval_buffer
*/
-apr_status_t sed_eval_buffer(sed_eval_t *eval, const char *buf, int bufsz, void *fout)
+apr_status_t sed_eval_buffer(sed_eval_t *eval, const char *buf, apr_size_t bufsz, void *fout)
{
apr_status_t rv;
@@ -382,8 +432,9 @@ apr_status_t sed_eval_buffer(sed_eval_t *eval, const char *buf, int bufsz, void
}
while (bufsz) {
+ apr_status_t rc = 0;
char *n;
- int llen;
+ apr_size_t llen;
n = memchr(buf, '\n', bufsz);
if (n == NULL)
@@ -396,7 +447,10 @@ apr_status_t sed_eval_buffer(sed_eval_t *eval, const char *buf, int bufsz, void
break;
}
- appendmem_to_linebuf(eval, buf, llen + 1);
+ rc = appendmem_to_linebuf(eval, buf, llen + 1);
+ if (rc != APR_SUCCESS) {
+ return rc;
+ }
--eval->lspend;
/* replace new line character with NULL */
*eval->lspend = '\0';
@@ -411,7 +465,10 @@ apr_status_t sed_eval_buffer(sed_eval_t *eval, const char *buf, int bufsz, void
/* Save the leftovers for later */
if (bufsz) {
- appendmem_to_linebuf(eval, buf, bufsz);
+ apr_status_t rc = appendmem_to_linebuf(eval, buf, bufsz);
+ if (rc != APR_SUCCESS) {
+ return rc;
+ }
}
return APR_SUCCESS;
@@ -433,6 +490,7 @@ apr_status_t sed_finalize_eval(sed_eval_t *eval, void *fout)
/* Process leftovers */
if (eval->lspend > eval->linebuf) {
apr_status_t rv;
+ apr_status_t rc = 0;
if (eval->lreadyflag) {
eval->lreadyflag = 0;
@@ -442,7 +500,10 @@ apr_status_t sed_finalize_eval(sed_eval_t *eval, void *fout)
* buffer is not a newline.
*/
/* Assure space for NULL */
- append_to_linebuf(eval, "");
+ rc = append_to_linebuf(eval, "", NULL);
+ if (rc != APR_SUCCESS) {
+ return rc;
+ }
}
*eval->lspend = '\0';
@@ -640,11 +701,15 @@ static apr_status_t dosub(sed_eval_t *eval, char *rhsbuf, int n,
sp = eval->genbuf;
rp = rhsbuf;
sp = place(eval, sp, lp, step_vars->loc1);
+ if (sp == NULL) {
+ return APR_EGENERAL;
+ }
while ((c = *rp++) != 0) {
if (c == '&') {
sp = place(eval, sp, step_vars->loc1, step_vars->loc2);
- if (sp == NULL)
+ if (sp == NULL) {
return APR_EGENERAL;
+ }
}
else if (c == '\\') {
c = *rp++;
@@ -660,13 +725,19 @@ static apr_status_t dosub(sed_eval_t *eval, char *rhsbuf, int n,
*sp++ = c;
if (sp >= eval->genbuf + eval->gsize) {
/* expand genbuf and set the sp appropriately */
- grow_gen_buffer(eval, eval->gsize + 1024, &sp);
+ rv = grow_gen_buffer(eval, eval->gsize + 1024, &sp);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
}
}
lp = step_vars->loc2;
step_vars->loc2 = sp - eval->genbuf + eval->linebuf;
- append_to_genbuf(eval, lp, &sp);
- copy_to_linebuf(eval, eval->genbuf);
+ rv = append_to_genbuf(eval, lp, &sp);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ rv = copy_to_linebuf(eval, eval->genbuf, step_vars);
return rv;
}
@@ -676,11 +747,14 @@ static apr_status_t dosub(sed_eval_t *eval, char *rhsbuf, int n,
static char *place(sed_eval_t *eval, char *asp, char *al1, char *al2)
{
char *sp = asp;
- int n = al2 - al1;
- unsigned int reqsize = (sp - eval->genbuf) + n + 1;
+ apr_size_t n = al2 - al1;
+ apr_size_t reqsize = (sp - eval->genbuf) + n + 1;
if (eval->gsize < reqsize) {
- grow_gen_buffer(eval, reqsize, &sp);
+ apr_status_t rc = grow_gen_buffer(eval, reqsize, &sp);
+ if (rc != APR_SUCCESS) {
+ return NULL;
+ }
}
memcpy(sp, al1, n);
return sp + n;
@@ -735,7 +809,8 @@ static apr_status_t command(sed_eval_t *eval, sed_reptr_t *ipc,
}
p1++;
- copy_to_linebuf(eval, p1);
+ rv = copy_to_linebuf(eval, p1, step_vars);
+ if (rv != APR_SUCCESS) return rv;
eval->jflag++;
break;
@@ -745,21 +820,27 @@ static apr_status_t command(sed_eval_t *eval, sed_reptr_t *ipc,
break;
case GCOM:
- copy_to_linebuf(eval, eval->holdbuf);
+ rv = copy_to_linebuf(eval, eval->holdbuf, step_vars);
+ if (rv != APR_SUCCESS) return rv;
break;
case CGCOM:
- append_to_linebuf(eval, "\n");
- append_to_linebuf(eval, eval->holdbuf);
+ rv = append_to_linebuf(eval, "\n", step_vars);
+ if (rv != APR_SUCCESS) return rv;
+ rv = append_to_linebuf(eval, eval->holdbuf, step_vars);
+ if (rv != APR_SUCCESS) return rv;
break;
case HCOM:
- copy_to_holdbuf(eval, eval->linebuf);
+ rv = copy_to_holdbuf(eval, eval->linebuf);
+ if (rv != APR_SUCCESS) return rv;
break;
case CHCOM:
- append_to_holdbuf(eval, "\n");
- append_to_holdbuf(eval, eval->linebuf);
+ rv = append_to_holdbuf(eval, "\n");
+ if (rv != APR_SUCCESS) return rv;
+ rv = append_to_holdbuf(eval, eval->linebuf);
+ if (rv != APR_SUCCESS) return rv;
break;
case ICOM:
@@ -881,7 +962,8 @@ static apr_status_t command(sed_eval_t *eval, sed_reptr_t *ipc,
if (rv != APR_SUCCESS)
return rv;
}
- append_to_linebuf(eval, "\n");
+ rv = append_to_linebuf(eval, "\n", step_vars);
+ if (rv != APR_SUCCESS) return rv;
eval->pending = ipc->next;
break;
@@ -955,9 +1037,12 @@ static apr_status_t command(sed_eval_t *eval, sed_reptr_t *ipc,
break;
case XCOM:
- copy_to_genbuf(eval, eval->linebuf);
- copy_to_linebuf(eval, eval->holdbuf);
- copy_to_holdbuf(eval, eval->genbuf);
+ rv = copy_to_genbuf(eval, eval->linebuf);
+ if (rv != APR_SUCCESS) return rv;
+ rv = copy_to_linebuf(eval, eval->holdbuf, step_vars);
+ if (rv != APR_SUCCESS) return rv;
+ rv = copy_to_holdbuf(eval, eval->genbuf);
+ if (rv != APR_SUCCESS) return rv;
break;
case YCOM:
@@ -1013,7 +1098,7 @@ static apr_status_t arout(sed_eval_t *eval)
/*
* wline
*/
-static apr_status_t wline(sed_eval_t *eval, char *buf, int sz)
+static apr_status_t wline(sed_eval_t *eval, char *buf, apr_size_t sz)
{
apr_status_t rv = APR_SUCCESS;
rv = eval->writefn(eval->fout, buf, sz);