mirror of
https://github.com/nginx/nginx.git
synced 2025-06-07 17:52:38 +08:00
Sub filter: fixed matching after a partial match.
After a failed partial match we now check if there is another partial match in previously matched substring to fix cases like "aab" in "aaab". The ctx->saved string is now always sent if it's present on return from the ngx_http_sub_parse() function (and reset accordingly). This allows to release parts of previously matched data.
This commit is contained in:
parent
ce7a5a0537
commit
1936a67647
@ -261,37 +261,37 @@ ngx_http_sub_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->copy_start != ctx->copy_end) {
|
if (ctx->saved.len) {
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
"saved: \"%V\"", &ctx->saved);
|
"saved: \"%V\"", &ctx->saved);
|
||||||
|
|
||||||
if (ctx->saved.len) {
|
cl = ngx_chain_get_free_buf(r->pool, &ctx->free);
|
||||||
|
if (cl == NULL) {
|
||||||
cl = ngx_chain_get_free_buf(r->pool, &ctx->free);
|
return NGX_ERROR;
|
||||||
if (cl == NULL) {
|
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
b = cl->buf;
|
|
||||||
|
|
||||||
ngx_memzero(b, sizeof(ngx_buf_t));
|
|
||||||
|
|
||||||
b->pos = ngx_pnalloc(r->pool, ctx->saved.len);
|
|
||||||
if (b->pos == NULL) {
|
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngx_memcpy(b->pos, ctx->saved.data, ctx->saved.len);
|
|
||||||
b->last = b->pos + ctx->saved.len;
|
|
||||||
b->memory = 1;
|
|
||||||
|
|
||||||
*ctx->last_out = cl;
|
|
||||||
ctx->last_out = &cl->next;
|
|
||||||
|
|
||||||
ctx->saved.len = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b = cl->buf;
|
||||||
|
|
||||||
|
ngx_memzero(b, sizeof(ngx_buf_t));
|
||||||
|
|
||||||
|
b->pos = ngx_pnalloc(r->pool, ctx->saved.len);
|
||||||
|
if (b->pos == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_memcpy(b->pos, ctx->saved.data, ctx->saved.len);
|
||||||
|
b->last = b->pos + ctx->saved.len;
|
||||||
|
b->memory = 1;
|
||||||
|
|
||||||
|
*ctx->last_out = cl;
|
||||||
|
ctx->last_out = &cl->next;
|
||||||
|
|
||||||
|
ctx->saved.len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->copy_start != ctx->copy_end) {
|
||||||
|
|
||||||
cl = ngx_chain_get_free_buf(r->pool, &ctx->free);
|
cl = ngx_chain_get_free_buf(r->pool, &ctx->free);
|
||||||
if (cl == NULL) {
|
if (cl == NULL) {
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
@ -325,6 +325,11 @@ ngx_http_sub_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||||||
ctx->copy_end = NULL;
|
ctx->copy_end = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ctx->looked.len > (size_t) (ctx->pos - ctx->buf->pos)) {
|
||||||
|
ctx->saved.len = ctx->looked.len - (ctx->pos - ctx->buf->pos);
|
||||||
|
ngx_memcpy(ctx->saved.data, ctx->looked.data, ctx->saved.len);
|
||||||
|
}
|
||||||
|
|
||||||
if (rc == NGX_AGAIN) {
|
if (rc == NGX_AGAIN) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -502,7 +507,7 @@ static ngx_int_t
|
|||||||
ngx_http_sub_parse(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx)
|
ngx_http_sub_parse(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
u_char *p, *last, *copy_end, ch, match;
|
u_char *p, *last, *copy_end, ch, match;
|
||||||
size_t looked;
|
size_t looked, i;
|
||||||
ngx_http_sub_state_e state;
|
ngx_http_sub_state_e state;
|
||||||
|
|
||||||
if (ctx->once) {
|
if (ctx->once) {
|
||||||
@ -573,13 +578,11 @@ ngx_http_sub_parse(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx)
|
|||||||
looked++;
|
looked++;
|
||||||
|
|
||||||
if (looked == ctx->match.len) {
|
if (looked == ctx->match.len) {
|
||||||
if ((size_t) (p - ctx->pos) < looked) {
|
|
||||||
ctx->saved.len = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->state = sub_start_state;
|
ctx->state = sub_start_state;
|
||||||
ctx->pos = p + 1;
|
ctx->pos = p + 1;
|
||||||
ctx->looked.len = 0;
|
ctx->looked.len = 0;
|
||||||
|
ctx->saved.len = 0;
|
||||||
ctx->copy_end = copy_end;
|
ctx->copy_end = copy_end;
|
||||||
|
|
||||||
if (ctx->copy_start == NULL && copy_end) {
|
if (ctx->copy_start == NULL && copy_end) {
|
||||||
@ -589,18 +592,53 @@ ngx_http_sub_parse(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx)
|
|||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (ch == ctx->match.data[0]) {
|
|
||||||
copy_end = p;
|
|
||||||
ctx->looked.data[0] = *p;
|
|
||||||
looked = 1;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
copy_end = p;
|
/*
|
||||||
looked = 0;
|
* check if there is another partial match in previously
|
||||||
state = sub_start_state;
|
* matched substring to catch cases like "aab" in "aaab"
|
||||||
|
*/
|
||||||
|
|
||||||
|
ctx->looked.data[looked] = *p;
|
||||||
|
looked++;
|
||||||
|
|
||||||
|
for (i = 1; i < looked; i++) {
|
||||||
|
if (ngx_strncasecmp(ctx->looked.data + i,
|
||||||
|
ctx->match.data, looked - i)
|
||||||
|
== 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < looked) {
|
||||||
|
if (ctx->saved.len > i) {
|
||||||
|
ctx->saved.len = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((size_t) (p + 1 - ctx->buf->pos) >= looked - i) {
|
||||||
|
copy_end = p + 1 - (looked - i);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_memmove(ctx->looked.data, ctx->looked.data + i, looked - i);
|
||||||
|
looked = looked - i;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
copy_end = p;
|
||||||
|
looked = 0;
|
||||||
|
state = sub_start_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->saved.len) {
|
||||||
|
p++;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx->saved.len = 0;
|
||||||
|
|
||||||
|
out:
|
||||||
|
|
||||||
ctx->state = state;
|
ctx->state = state;
|
||||||
ctx->pos = p;
|
ctx->pos = p;
|
||||||
ctx->looked.len = looked;
|
ctx->looked.len = looked;
|
||||||
|
Loading…
Reference in New Issue
Block a user