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