limit mod_sed memory use

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1901506 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Eric Covener
2022-06-01 12:40:09 +00:00
parent 2586986078
commit 65b8fb947b
3 changed files with 119 additions and 46 deletions

View File

@ -1 +1 @@
10394 10396

View File

@ -358,6 +358,7 @@ static apr_status_t sed_response_filter(ap_filter_t *f,
status = sed_eval_buffer(&ctx->eval, buf, bytes, ctx); 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(10394) "error evaluating sed on output");
break; break;
} }
} }
@ -463,8 +464,10 @@ static apr_status_t sed_request_filter(ap_filter_t *f,
if (apr_bucket_read(b, &buf, &bytes, APR_BLOCK_READ) if (apr_bucket_read(b, &buf, &bytes, APR_BLOCK_READ)
== APR_SUCCESS) { == APR_SUCCESS) {
status = sed_eval_buffer(&ctx->eval, buf, bytes, ctx); 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; return status;
}
flush_output_buffer(ctx); flush_output_buffer(ctx);
} }
} }

View File

@ -87,18 +87,20 @@ static void eval_errf(sed_eval_t *eval, const char *fmt, ...)
} }
#define INIT_BUF_SIZE 1024 #define INIT_BUF_SIZE 1024
#define MAX_BUF_SIZE 1024*8192
/* /*
* grow_buffer * grow_buffer
*/ */
static void grow_buffer(apr_pool_t *pool, char **buffer, static apr_status_t grow_buffer(apr_pool_t *pool, char **buffer,
char **spend, apr_size_t *cursize, char **spend, apr_size_t *cursize,
apr_size_t newsize) apr_size_t newsize)
{ {
char* newbuffer = NULL; char* newbuffer = NULL;
apr_size_t spendsize = 0; apr_size_t spendsize = 0;
if (*cursize >= newsize) if (*cursize >= newsize) {
return; return APR_SUCCESS;
}
/* Avoid number of times realloc is called. It could cause huge memory /* Avoid number of times realloc is called. It could cause huge memory
* requirement if line size is huge e.g 2 MB */ * requirement if line size is huge e.g 2 MB */
if (newsize < *cursize * 2) { if (newsize < *cursize * 2) {
@ -107,6 +109,9 @@ static void grow_buffer(apr_pool_t *pool, char **buffer,
/* Align it to 4 KB boundary */ /* Align it to 4 KB boundary */
newsize = (newsize + ((1 << 12) - 1)) & ~((1 << 12) - 1); newsize = (newsize + ((1 << 12) - 1)) & ~((1 << 12) - 1);
if (newsize > MAX_BUF_SIZE) {
return APR_ENOMEM;
}
newbuffer = apr_pcalloc(pool, newsize); newbuffer = apr_pcalloc(pool, newsize);
if (*spend && *buffer && (*cursize > 0)) { if (*spend && *buffer && (*cursize > 0)) {
spendsize = *spend - *buffer; spendsize = *spend - *buffer;
@ -119,63 +124,77 @@ static void grow_buffer(apr_pool_t *pool, char **buffer,
if (spend != buffer) { if (spend != buffer) {
*spend = *buffer + spendsize; *spend = *buffer + spendsize;
} }
return APR_SUCCESS;
} }
/* /*
* grow_line_buffer * grow_line_buffer
*/ */
static void grow_line_buffer(sed_eval_t *eval, apr_size_t 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); &eval->lsize, newsize);
} }
/* /*
* grow_hold_buffer * grow_hold_buffer
*/ */
static void grow_hold_buffer(sed_eval_t *eval, apr_size_t 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); &eval->hsize, newsize);
} }
/* /*
* grow_gen_buffer * grow_gen_buffer
*/ */
static void grow_gen_buffer(sed_eval_t *eval, apr_size_t newsize, static apr_status_t grow_gen_buffer(sed_eval_t *eval, apr_size_t newsize,
char **gspend) char **gspend)
{ {
apr_status_t rc = 0;
if (gspend == NULL) { if (gspend == NULL) {
gspend = &eval->genbuf; gspend = &eval->genbuf;
} }
grow_buffer(eval->pool, &eval->genbuf, gspend, rc = grow_buffer(eval->pool, &eval->genbuf, gspend,
&eval->gsize, newsize); &eval->gsize, newsize);
eval->lcomend = &eval->genbuf[71]; if (rc == APR_SUCCESS) {
eval->lcomend = &eval->genbuf[71];
}
return rc;
} }
/* /*
* appendmem_to_linebuf * appendmem_to_linebuf
*/ */
static void appendmem_to_linebuf(sed_eval_t *eval, const char* sz, apr_size_t len) static apr_status_t appendmem_to_linebuf(sed_eval_t *eval, const char* sz, apr_size_t len)
{ {
apr_status_t rc = 0;
apr_size_t reqsize = (eval->lspend - eval->linebuf) + len; apr_size_t reqsize = (eval->lspend - eval->linebuf) + len;
if (eval->lsize < reqsize) { 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); memcpy(eval->lspend, sz, len);
eval->lspend += len; eval->lspend += len;
return APR_SUCCESS;
} }
/* /*
* append_to_linebuf * 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) step_vars_storage *step_vars)
{ {
apr_size_t len = strlen(sz); apr_size_t len = strlen(sz);
char *old_linebuf = eval->linebuf; char *old_linebuf = eval->linebuf;
apr_status_t rc = 0;
/* Copy string including null character */ /* 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 */ --eval->lspend; /* lspend will now point to NULL character */
/* Sync step_vars after a possible linebuf expansion */ /* Sync step_vars after a possible linebuf expansion */
if (step_vars && old_linebuf != eval->linebuf) { if (step_vars && old_linebuf != eval->linebuf) {
@ -189,68 +208,84 @@ static void append_to_linebuf(sed_eval_t *eval, const char* sz,
step_vars->locs = step_vars->locs - old_linebuf + eval->linebuf; step_vars->locs = step_vars->locs - old_linebuf + eval->linebuf;
} }
} }
return APR_SUCCESS;
} }
/* /*
* copy_to_linebuf * 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) step_vars_storage *step_vars)
{ {
eval->lspend = eval->linebuf; eval->lspend = eval->linebuf;
append_to_linebuf(eval, sz, step_vars); return append_to_linebuf(eval, sz, step_vars);
} }
/* /*
* append_to_holdbuf * 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)
{ {
apr_size_t len = strlen(sz); apr_size_t len = strlen(sz);
apr_size_t reqsize = (eval->hspend - eval->holdbuf) + len + 1; apr_size_t reqsize = (eval->hspend - eval->holdbuf) + len + 1;
apr_status_t rc = 0;
if (eval->hsize <= reqsize) { 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); memcpy(eval->hspend, sz, len + 1);
/* hspend will now point to NULL character */ /* hspend will now point to NULL character */
eval->hspend += len; eval->hspend += len;
return APR_SUCCESS;
} }
/* /*
* copy_to_holdbuf * 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; eval->hspend = eval->holdbuf;
append_to_holdbuf(eval, sz); return append_to_holdbuf(eval, sz);
} }
/* /*
* append_to_genbuf * 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)
{ {
apr_size_t len = strlen(sz); apr_size_t len = strlen(sz);
apr_size_t reqsize = (*gspend - eval->genbuf) + len + 1; apr_size_t reqsize = (*gspend - eval->genbuf) + len + 1;
apr_status_t rc = 0;
if (eval->gsize < reqsize) { 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); memcpy(*gspend, sz, len + 1);
/* *gspend will now point to NULL character */ /* *gspend will now point to NULL character */
*gspend += len; *gspend += len;
return APR_SUCCESS;
} }
/* /*
* copy_to_genbuf * 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)
{ {
apr_size_t len = strlen(sz); apr_size_t len = strlen(sz);
apr_size_t reqsize = len + 1; apr_size_t reqsize = len + 1;
apr_status_t rc = APR_SUCCESS;;
if (eval->gsize < reqsize) { 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); memcpy(eval->genbuf, sz, len + 1);
return rc;
} }
/* /*
@ -397,6 +432,7 @@ apr_status_t sed_eval_buffer(sed_eval_t *eval, const char *buf, apr_size_t bufsz
} }
while (bufsz) { while (bufsz) {
apr_status_t rc = 0;
char *n; char *n;
apr_size_t llen; apr_size_t llen;
@ -411,7 +447,10 @@ apr_status_t sed_eval_buffer(sed_eval_t *eval, const char *buf, apr_size_t bufsz
break; break;
} }
appendmem_to_linebuf(eval, buf, llen + 1); rc = appendmem_to_linebuf(eval, buf, llen + 1);
if (rc != APR_SUCCESS) {
return rc;
}
--eval->lspend; --eval->lspend;
/* replace new line character with NULL */ /* replace new line character with NULL */
*eval->lspend = '\0'; *eval->lspend = '\0';
@ -426,7 +465,10 @@ apr_status_t sed_eval_buffer(sed_eval_t *eval, const char *buf, apr_size_t bufsz
/* Save the leftovers for later */ /* Save the leftovers for later */
if (bufsz) { 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; return APR_SUCCESS;
@ -448,6 +490,7 @@ apr_status_t sed_finalize_eval(sed_eval_t *eval, void *fout)
/* Process leftovers */ /* Process leftovers */
if (eval->lspend > eval->linebuf) { if (eval->lspend > eval->linebuf) {
apr_status_t rv; apr_status_t rv;
apr_status_t rc = 0;
if (eval->lreadyflag) { if (eval->lreadyflag) {
eval->lreadyflag = 0; eval->lreadyflag = 0;
@ -457,7 +500,10 @@ apr_status_t sed_finalize_eval(sed_eval_t *eval, void *fout)
* buffer is not a newline. * buffer is not a newline.
*/ */
/* Assure space for NULL */ /* Assure space for NULL */
append_to_linebuf(eval, "", NULL); rc = append_to_linebuf(eval, "", NULL);
if (rc != APR_SUCCESS) {
return rc;
}
} }
*eval->lspend = '\0'; *eval->lspend = '\0';
@ -655,11 +701,15 @@ static apr_status_t dosub(sed_eval_t *eval, char *rhsbuf, int n,
sp = eval->genbuf; sp = eval->genbuf;
rp = rhsbuf; rp = rhsbuf;
sp = place(eval, sp, lp, step_vars->loc1); sp = place(eval, sp, lp, step_vars->loc1);
if (sp == NULL) {
return APR_EGENERAL;
}
while ((c = *rp++) != 0) { while ((c = *rp++) != 0) {
if (c == '&') { if (c == '&') {
sp = place(eval, sp, step_vars->loc1, step_vars->loc2); sp = place(eval, sp, step_vars->loc1, step_vars->loc2);
if (sp == NULL) if (sp == NULL) {
return APR_EGENERAL; return APR_EGENERAL;
}
} }
else if (c == '\\') { else if (c == '\\') {
c = *rp++; c = *rp++;
@ -675,13 +725,19 @@ static apr_status_t dosub(sed_eval_t *eval, char *rhsbuf, int n,
*sp++ = c; *sp++ = c;
if (sp >= eval->genbuf + eval->gsize) { if (sp >= eval->genbuf + eval->gsize) {
/* expand genbuf and set the sp appropriately */ /* 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; lp = step_vars->loc2;
step_vars->loc2 = sp - eval->genbuf + eval->linebuf; step_vars->loc2 = sp - eval->genbuf + eval->linebuf;
append_to_genbuf(eval, lp, &sp); rv = append_to_genbuf(eval, lp, &sp);
copy_to_linebuf(eval, eval->genbuf, step_vars); if (rv != APR_SUCCESS) {
return rv;
}
rv = copy_to_linebuf(eval, eval->genbuf, step_vars);
return rv; return rv;
} }
@ -695,7 +751,10 @@ static char *place(sed_eval_t *eval, char *asp, char *al1, char *al2)
apr_size_t reqsize = (sp - eval->genbuf) + n + 1; apr_size_t reqsize = (sp - eval->genbuf) + n + 1;
if (eval->gsize < reqsize) { 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); memcpy(sp, al1, n);
return sp + n; return sp + n;
@ -750,7 +809,8 @@ static apr_status_t command(sed_eval_t *eval, sed_reptr_t *ipc,
} }
p1++; p1++;
copy_to_linebuf(eval, p1, step_vars); rv = copy_to_linebuf(eval, p1, step_vars);
if (rv != APR_SUCCESS) return rv;
eval->jflag++; eval->jflag++;
break; break;
@ -760,21 +820,27 @@ static apr_status_t command(sed_eval_t *eval, sed_reptr_t *ipc,
break; break;
case GCOM: case GCOM:
copy_to_linebuf(eval, eval->holdbuf, step_vars); rv = copy_to_linebuf(eval, eval->holdbuf, step_vars);
if (rv != APR_SUCCESS) return rv;
break; break;
case CGCOM: case CGCOM:
append_to_linebuf(eval, "\n", step_vars); rv = append_to_linebuf(eval, "\n", step_vars);
append_to_linebuf(eval, eval->holdbuf, step_vars); if (rv != APR_SUCCESS) return rv;
rv = append_to_linebuf(eval, eval->holdbuf, step_vars);
if (rv != APR_SUCCESS) return rv;
break; break;
case HCOM: case HCOM:
copy_to_holdbuf(eval, eval->linebuf); rv = copy_to_holdbuf(eval, eval->linebuf);
if (rv != APR_SUCCESS) return rv;
break; break;
case CHCOM: case CHCOM:
append_to_holdbuf(eval, "\n"); rv = append_to_holdbuf(eval, "\n");
append_to_holdbuf(eval, eval->linebuf); if (rv != APR_SUCCESS) return rv;
rv = append_to_holdbuf(eval, eval->linebuf);
if (rv != APR_SUCCESS) return rv;
break; break;
case ICOM: case ICOM:
@ -896,7 +962,8 @@ static apr_status_t command(sed_eval_t *eval, sed_reptr_t *ipc,
if (rv != APR_SUCCESS) if (rv != APR_SUCCESS)
return rv; return rv;
} }
append_to_linebuf(eval, "\n", step_vars); rv = append_to_linebuf(eval, "\n", step_vars);
if (rv != APR_SUCCESS) return rv;
eval->pending = ipc->next; eval->pending = ipc->next;
break; break;
@ -970,9 +1037,12 @@ static apr_status_t command(sed_eval_t *eval, sed_reptr_t *ipc,
break; break;
case XCOM: case XCOM:
copy_to_genbuf(eval, eval->linebuf); rv = copy_to_genbuf(eval, eval->linebuf);
copy_to_linebuf(eval, eval->holdbuf, step_vars); if (rv != APR_SUCCESS) return rv;
copy_to_holdbuf(eval, eval->genbuf); 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; break;
case YCOM: case YCOM: