Mercurial > hg > nginx
comparison src/http/modules/ngx_http_sub_filter_module.c @ 5288:102d7117ffb8
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.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 25 Jul 2013 14:54:53 +0400 |
parents | 2dbc5e38b65d |
children | 9e9c1310d17c |
comparison
equal
deleted
inserted
replaced
5287:2dbc5e38b65d | 5288:102d7117ffb8 |
---|---|
259 | 259 |
260 if (rc == NGX_ERROR) { | 260 if (rc == NGX_ERROR) { |
261 return rc; | 261 return rc; |
262 } | 262 } |
263 | 263 |
264 if (ctx->copy_start != ctx->copy_end) { | 264 if (ctx->saved.len) { |
265 | 265 |
266 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 266 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
267 "saved: \"%V\"", &ctx->saved); | 267 "saved: \"%V\"", &ctx->saved); |
268 | 268 |
269 if (ctx->saved.len) { | 269 cl = ngx_chain_get_free_buf(r->pool, &ctx->free); |
270 | 270 if (cl == NULL) { |
271 cl = ngx_chain_get_free_buf(r->pool, &ctx->free); | 271 return NGX_ERROR; |
272 if (cl == NULL) { | 272 } |
273 return NGX_ERROR; | 273 |
274 } | 274 b = cl->buf; |
275 | 275 |
276 b = cl->buf; | 276 ngx_memzero(b, sizeof(ngx_buf_t)); |
277 | 277 |
278 ngx_memzero(b, sizeof(ngx_buf_t)); | 278 b->pos = ngx_pnalloc(r->pool, ctx->saved.len); |
279 | 279 if (b->pos == NULL) { |
280 b->pos = ngx_pnalloc(r->pool, ctx->saved.len); | 280 return NGX_ERROR; |
281 if (b->pos == NULL) { | 281 } |
282 return NGX_ERROR; | 282 |
283 } | 283 ngx_memcpy(b->pos, ctx->saved.data, ctx->saved.len); |
284 | 284 b->last = b->pos + ctx->saved.len; |
285 ngx_memcpy(b->pos, ctx->saved.data, ctx->saved.len); | 285 b->memory = 1; |
286 b->last = b->pos + ctx->saved.len; | 286 |
287 b->memory = 1; | 287 *ctx->last_out = cl; |
288 | 288 ctx->last_out = &cl->next; |
289 *ctx->last_out = cl; | 289 |
290 ctx->last_out = &cl->next; | 290 ctx->saved.len = 0; |
291 | 291 } |
292 ctx->saved.len = 0; | 292 |
293 } | 293 if (ctx->copy_start != ctx->copy_end) { |
294 | 294 |
295 cl = ngx_chain_get_free_buf(r->pool, &ctx->free); | 295 cl = ngx_chain_get_free_buf(r->pool, &ctx->free); |
296 if (cl == NULL) { | 296 if (cl == NULL) { |
297 return NGX_ERROR; | 297 return NGX_ERROR; |
298 } | 298 } |
321 ctx->copy_end = ctx->pos; | 321 ctx->copy_end = ctx->pos; |
322 | 322 |
323 } else { | 323 } else { |
324 ctx->copy_start = NULL; | 324 ctx->copy_start = NULL; |
325 ctx->copy_end = NULL; | 325 ctx->copy_end = NULL; |
326 } | |
327 | |
328 if (ctx->looked.len > (size_t) (ctx->pos - ctx->buf->pos)) { | |
329 ctx->saved.len = ctx->looked.len - (ctx->pos - ctx->buf->pos); | |
330 ngx_memcpy(ctx->saved.data, ctx->looked.data, ctx->saved.len); | |
326 } | 331 } |
327 | 332 |
328 if (rc == NGX_AGAIN) { | 333 if (rc == NGX_AGAIN) { |
329 continue; | 334 continue; |
330 } | 335 } |
500 | 505 |
501 static ngx_int_t | 506 static ngx_int_t |
502 ngx_http_sub_parse(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx) | 507 ngx_http_sub_parse(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx) |
503 { | 508 { |
504 u_char *p, *last, *copy_end, ch, match; | 509 u_char *p, *last, *copy_end, ch, match; |
505 size_t looked; | 510 size_t looked, i; |
506 ngx_http_sub_state_e state; | 511 ngx_http_sub_state_e state; |
507 | 512 |
508 if (ctx->once) { | 513 if (ctx->once) { |
509 ctx->copy_start = ctx->pos; | 514 ctx->copy_start = ctx->pos; |
510 ctx->copy_end = ctx->buf->last; | 515 ctx->copy_end = ctx->buf->last; |
571 if (ch == ctx->match.data[looked]) { | 576 if (ch == ctx->match.data[looked]) { |
572 ctx->looked.data[looked] = *p; | 577 ctx->looked.data[looked] = *p; |
573 looked++; | 578 looked++; |
574 | 579 |
575 if (looked == ctx->match.len) { | 580 if (looked == ctx->match.len) { |
576 if ((size_t) (p - ctx->pos) < looked) { | |
577 ctx->saved.len = 0; | |
578 } | |
579 | 581 |
580 ctx->state = sub_start_state; | 582 ctx->state = sub_start_state; |
581 ctx->pos = p + 1; | 583 ctx->pos = p + 1; |
582 ctx->looked.len = 0; | 584 ctx->looked.len = 0; |
585 ctx->saved.len = 0; | |
583 ctx->copy_end = copy_end; | 586 ctx->copy_end = copy_end; |
584 | 587 |
585 if (ctx->copy_start == NULL && copy_end) { | 588 if (ctx->copy_start == NULL && copy_end) { |
586 ctx->copy_start = ctx->buf->pos; | 589 ctx->copy_start = ctx->buf->pos; |
587 } | 590 } |
588 | 591 |
589 return NGX_OK; | 592 return NGX_OK; |
590 } | 593 } |
591 | 594 |
592 } else if (ch == ctx->match.data[0]) { | |
593 copy_end = p; | |
594 ctx->looked.data[0] = *p; | |
595 looked = 1; | |
596 | |
597 } else { | 595 } else { |
598 copy_end = p; | 596 /* |
599 looked = 0; | 597 * check if there is another partial match in previously |
600 state = sub_start_state; | 598 * matched substring to catch cases like "aab" in "aaab" |
601 } | 599 */ |
602 } | 600 |
601 ctx->looked.data[looked] = *p; | |
602 looked++; | |
603 | |
604 for (i = 1; i < looked; i++) { | |
605 if (ngx_strncasecmp(ctx->looked.data + i, | |
606 ctx->match.data, looked - i) | |
607 == 0) | |
608 { | |
609 break; | |
610 } | |
611 } | |
612 | |
613 if (i < looked) { | |
614 if (ctx->saved.len > i) { | |
615 ctx->saved.len = i; | |
616 } | |
617 | |
618 if ((size_t) (p + 1 - ctx->buf->pos) >= looked - i) { | |
619 copy_end = p + 1 - (looked - i); | |
620 } | |
621 | |
622 ngx_memmove(ctx->looked.data, ctx->looked.data + i, looked - i); | |
623 looked = looked - i; | |
624 | |
625 } else { | |
626 copy_end = p; | |
627 looked = 0; | |
628 state = sub_start_state; | |
629 } | |
630 | |
631 if (ctx->saved.len) { | |
632 p++; | |
633 goto out; | |
634 } | |
635 } | |
636 } | |
637 | |
638 ctx->saved.len = 0; | |
639 | |
640 out: | |
603 | 641 |
604 ctx->state = state; | 642 ctx->state = state; |
605 ctx->pos = p; | 643 ctx->pos = p; |
606 ctx->looked.len = looked; | 644 ctx->looked.len = looked; |
607 | 645 |