[nginx] Sub filter: fixed matching after a partial match.
Maxim Dounin
mdounin at mdounin.ru
Thu Jul 25 11:58:41 UTC 2013
details: http://hg.nginx.org/nginx/rev/102d7117ffb8
branches:
changeset: 5288:102d7117ffb8
user: Maxim Dounin <mdounin at mdounin.ru>
date: Thu Jul 25 14:54:53 2013 +0400
description:
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.
diffstat:
src/http/modules/ngx_http_sub_filter_module.c | 100 +++++++++++++++++--------
1 files changed, 69 insertions(+), 31 deletions(-)
diffs (157 lines):
diff --git a/src/http/modules/ngx_http_sub_filter_module.c b/src/http/modules/ngx_http_sub_filter_module.c
--- a/src/http/modules/ngx_http_sub_filter_module.c
+++ b/src/http/modules/ngx_http_sub_filter_module.c
@@ -261,36 +261,36 @@ ngx_http_sub_body_filter(ngx_http_reques
return rc;
}
- if (ctx->copy_start != ctx->copy_end) {
+ if (ctx->saved.len) {
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"saved: \"%V\"", &ctx->saved);
- if (ctx->saved.len) {
+ cl = ngx_chain_get_free_buf(r->pool, &ctx->free);
+ if (cl == NULL) {
+ return NGX_ERROR;
+ }
- cl = ngx_chain_get_free_buf(r->pool, &ctx->free);
- if (cl == NULL) {
- return NGX_ERROR;
- }
+ b = cl->buf;
- b = cl->buf;
+ ngx_memzero(b, sizeof(ngx_buf_t));
- ngx_memzero(b, sizeof(ngx_buf_t));
+ b->pos = ngx_pnalloc(r->pool, ctx->saved.len);
+ if (b->pos == NULL) {
+ return NGX_ERROR;
+ }
- 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;
- 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->last_out = cl;
- ctx->last_out = &cl->next;
+ ctx->saved.len = 0;
+ }
- ctx->saved.len = 0;
- }
+ if (ctx->copy_start != ctx->copy_end) {
cl = ngx_chain_get_free_buf(r->pool, &ctx->free);
if (cl == NULL) {
@@ -325,6 +325,11 @@ ngx_http_sub_body_filter(ngx_http_reques
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) {
continue;
}
@@ -502,7 +507,7 @@ static ngx_int_t
ngx_http_sub_parse(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx)
{
u_char *p, *last, *copy_end, ch, match;
- size_t looked;
+ size_t looked, i;
ngx_http_sub_state_e state;
if (ctx->once) {
@@ -573,13 +578,11 @@ ngx_http_sub_parse(ngx_http_request_t *r
looked++;
if (looked == ctx->match.len) {
- if ((size_t) (p - ctx->pos) < looked) {
- ctx->saved.len = 0;
- }
ctx->state = sub_start_state;
ctx->pos = p + 1;
ctx->looked.len = 0;
+ ctx->saved.len = 0;
ctx->copy_end = copy_end;
if (ctx->copy_start == NULL && copy_end) {
@@ -589,18 +592,53 @@ ngx_http_sub_parse(ngx_http_request_t *r
return NGX_OK;
}
- } else if (ch == ctx->match.data[0]) {
- copy_end = p;
- ctx->looked.data[0] = *p;
- looked = 1;
+ } else {
+ /*
+ * check if there is another partial match in previously
+ * matched substring to catch cases like "aab" in "aaab"
+ */
- } else {
- copy_end = p;
- looked = 0;
- state = sub_start_state;
+ 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->pos = p;
ctx->looked.len = looked;
More information about the nginx-devel
mailing list