Mercurial > hg > nginx-quic
comparison src/http/modules/perl/nginx.xs @ 7525:575480d3fd01
Perl: propagate errors.
When an error happens, the ctx->error bit is now set, and croak()
is called to terminate further processing. The ctx->error bit is
checked in ngx_http_perl_call_handler() to cancel further processing,
and is also checked in various output functions - to make sure these won't
be called if croak() was handled by an eval{} in perl code.
In particular, this ensures that output chain won't be called after
errors, as filters might not expect this to happen. This fixes some
segmentation faults under low memory conditions. Also this stops
request processing after filter finalization or request body reading
errors.
For cases where an HTTP error status can be additionally returned (for
example, 416 (Requested Range Not Satisfiable) from the range filter),
the ctx->status field is also added.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Fri, 12 Jul 2019 13:56:21 +0300 |
parents | deebe988cbd7 |
children | 8125552a10ca |
comparison
equal
deleted
inserted
replaced
7524:deebe988cbd7 | 7525:575480d3fd01 |
---|---|
123 CODE: | 123 CODE: |
124 | 124 |
125 ngx_http_request_t *r; | 125 ngx_http_request_t *r; |
126 ngx_http_perl_ctx_t *ctx; | 126 ngx_http_perl_ctx_t *ctx; |
127 SV *sv; | 127 SV *sv; |
128 | 128 ngx_int_t rc; |
129 ngx_http_perl_set_request(r, ctx); | 129 |
130 ngx_http_perl_set_request(r, ctx); | |
131 | |
132 if (ctx->error) { | |
133 croak("send_http_header(): called after error"); | |
134 } | |
130 | 135 |
131 if (r->headers_out.status == 0) { | 136 if (r->headers_out.status == 0) { |
132 r->headers_out.status = NGX_HTTP_OK; | 137 r->headers_out.status = NGX_HTTP_OK; |
133 } | 138 } |
134 | 139 |
149 } | 154 } |
150 } | 155 } |
151 | 156 |
152 r->disable_not_modified = 1; | 157 r->disable_not_modified = 1; |
153 | 158 |
154 (void) ngx_http_send_header(r); | 159 rc = ngx_http_send_header(r); |
160 | |
161 if (rc == NGX_ERROR || rc > NGX_OK) { | |
162 ctx->error = 1; | |
163 ctx->status = rc; | |
164 croak("ngx_http_send_header() failed"); | |
165 } | |
155 | 166 |
156 | 167 |
157 void | 168 void |
158 header_only(r) | 169 header_only(r) |
159 CODE: | 170 CODE: |
379 CODE: | 390 CODE: |
380 | 391 |
381 dXSTARG; | 392 dXSTARG; |
382 ngx_http_request_t *r; | 393 ngx_http_request_t *r; |
383 ngx_http_perl_ctx_t *ctx; | 394 ngx_http_perl_ctx_t *ctx; |
395 ngx_int_t rc; | |
384 | 396 |
385 ngx_http_perl_set_request(r, ctx); | 397 ngx_http_perl_set_request(r, ctx); |
386 | 398 |
387 if (r->headers_in.content_length_n <= 0 && !r->headers_in.chunked) { | 399 if (r->headers_in.content_length_n <= 0 && !r->headers_in.chunked) { |
388 XSRETURN_UNDEF; | 400 XSRETURN_UNDEF; |
396 | 408 |
397 if (r->request_body_in_file_only) { | 409 if (r->request_body_in_file_only) { |
398 r->request_body_file_log_level = 0; | 410 r->request_body_file_log_level = 0; |
399 } | 411 } |
400 | 412 |
401 ngx_http_read_client_request_body(r, ngx_http_perl_handle_request); | 413 rc = ngx_http_read_client_request_body(r, ngx_http_perl_handle_request); |
414 | |
415 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { | |
416 ctx->error = 1; | |
417 ctx->status = rc; | |
418 ctx->next = NULL; | |
419 croak("ngx_http_read_client_request_body() failed"); | |
420 } | |
402 | 421 |
403 sv_upgrade(TARG, SVt_IV); | 422 sv_upgrade(TARG, SVt_IV); |
404 sv_setiv(TARG, 1); | 423 sv_setiv(TARG, 1); |
405 | 424 |
406 ST(0) = TARG; | 425 ST(0) = TARG; |
492 discard_request_body(r) | 511 discard_request_body(r) |
493 CODE: | 512 CODE: |
494 | 513 |
495 ngx_http_request_t *r; | 514 ngx_http_request_t *r; |
496 ngx_http_perl_ctx_t *ctx; | 515 ngx_http_perl_ctx_t *ctx; |
497 | 516 ngx_int_t rc; |
498 ngx_http_perl_set_request(r, ctx); | 517 |
499 | 518 ngx_http_perl_set_request(r, ctx); |
500 ngx_http_discard_request_body(r); | 519 |
520 rc = ngx_http_discard_request_body(r); | |
521 | |
522 if (rc != NGX_OK) { | |
523 ctx->error = 1; | |
524 ctx->status = rc; | |
525 croak("ngx_http_discard_request_body() failed"); | |
526 } | |
501 | 527 |
502 | 528 |
503 void | 529 void |
504 header_out(r, key, value) | 530 header_out(r, key, value) |
505 CODE: | 531 CODE: |
509 SV *key; | 535 SV *key; |
510 SV *value; | 536 SV *value; |
511 ngx_table_elt_t *header; | 537 ngx_table_elt_t *header; |
512 | 538 |
513 ngx_http_perl_set_request(r, ctx); | 539 ngx_http_perl_set_request(r, ctx); |
540 | |
541 if (ctx->error) { | |
542 croak("header_out(): called after error"); | |
543 } | |
514 | 544 |
515 key = ST(1); | 545 key = ST(1); |
516 value = ST(2); | 546 value = ST(2); |
517 | 547 |
518 header = ngx_list_push(&r->headers_out.headers); | 548 header = ngx_list_push(&r->headers_out.headers); |
586 SV *sv; | 616 SV *sv; |
587 int i; | 617 int i; |
588 u_char *p; | 618 u_char *p; |
589 size_t size; | 619 size_t size; |
590 STRLEN len; | 620 STRLEN len; |
621 ngx_int_t rc; | |
591 ngx_buf_t *b; | 622 ngx_buf_t *b; |
592 | 623 |
593 ngx_http_perl_set_request(r, ctx); | 624 ngx_http_perl_set_request(r, ctx); |
625 | |
626 if (ctx->error) { | |
627 croak("print(): called after error"); | |
628 } | |
594 | 629 |
595 if (items == 2) { | 630 if (items == 2) { |
596 | 631 |
597 /* | 632 /* |
598 * do zero copy for prolate single read-only SV: | 633 * do zero copy for prolate single read-only SV: |
669 b->last = ngx_cpymem(b->last, p, len); | 704 b->last = ngx_cpymem(b->last, p, len); |
670 } | 705 } |
671 | 706 |
672 out: | 707 out: |
673 | 708 |
674 (void) ngx_http_perl_output(r, ctx, b); | 709 rc = ngx_http_perl_output(r, ctx, b); |
710 | |
711 if (rc == NGX_ERROR) { | |
712 ctx->error = 1; | |
713 croak("ngx_http_perl_output() failed"); | |
714 } | |
675 | 715 |
676 | 716 |
677 void | 717 void |
678 sendfile(r, filename, offset = -1, bytes = 0) | 718 sendfile(r, filename, offset = -1, bytes = 0) |
679 CODE: | 719 CODE: |
681 ngx_http_request_t *r; | 721 ngx_http_request_t *r; |
682 ngx_http_perl_ctx_t *ctx; | 722 ngx_http_perl_ctx_t *ctx; |
683 char *filename; | 723 char *filename; |
684 off_t offset; | 724 off_t offset; |
685 size_t bytes; | 725 size_t bytes; |
726 ngx_int_t rc; | |
686 ngx_str_t path; | 727 ngx_str_t path; |
687 ngx_buf_t *b; | 728 ngx_buf_t *b; |
688 ngx_open_file_info_t of; | 729 ngx_open_file_info_t of; |
689 ngx_http_core_loc_conf_t *clcf; | 730 ngx_http_core_loc_conf_t *clcf; |
690 | 731 |
691 ngx_http_perl_set_request(r, ctx); | 732 ngx_http_perl_set_request(r, ctx); |
733 | |
734 if (ctx->error) { | |
735 croak("sendfile(): called after error"); | |
736 } | |
692 | 737 |
693 filename = SvPV_nolen(ST(1)); | 738 filename = SvPV_nolen(ST(1)); |
694 | 739 |
695 if (filename == NULL) { | 740 if (filename == NULL) { |
696 croak("sendfile(): NULL filename"); | 741 croak("sendfile(): NULL filename"); |
760 | 805 |
761 b->file->fd = of.fd; | 806 b->file->fd = of.fd; |
762 b->file->log = r->connection->log; | 807 b->file->log = r->connection->log; |
763 b->file->directio = of.is_directio; | 808 b->file->directio = of.is_directio; |
764 | 809 |
765 (void) ngx_http_perl_output(r, ctx, b); | 810 rc = ngx_http_perl_output(r, ctx, b); |
811 | |
812 if (rc == NGX_ERROR) { | |
813 ctx->error = 1; | |
814 croak("ngx_http_perl_output() failed"); | |
815 } | |
766 | 816 |
767 | 817 |
768 void | 818 void |
769 flush(r) | 819 flush(r) |
770 CODE: | 820 CODE: |
771 | 821 |
772 ngx_http_request_t *r; | 822 ngx_http_request_t *r; |
773 ngx_http_perl_ctx_t *ctx; | 823 ngx_http_perl_ctx_t *ctx; |
824 ngx_int_t rc; | |
774 ngx_buf_t *b; | 825 ngx_buf_t *b; |
775 | 826 |
776 ngx_http_perl_set_request(r, ctx); | 827 ngx_http_perl_set_request(r, ctx); |
828 | |
829 if (ctx->error) { | |
830 croak("flush(): called after error"); | |
831 } | |
777 | 832 |
778 b = ngx_calloc_buf(r->pool); | 833 b = ngx_calloc_buf(r->pool); |
779 if (b == NULL) { | 834 if (b == NULL) { |
780 XSRETURN_EMPTY; | 835 XSRETURN_EMPTY; |
781 } | 836 } |
782 | 837 |
783 b->flush = 1; | 838 b->flush = 1; |
784 | 839 |
785 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "$r->flush"); | 840 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "$r->flush"); |
786 | 841 |
787 (void) ngx_http_perl_output(r, ctx, b); | 842 rc = ngx_http_perl_output(r, ctx, b); |
843 | |
844 if (rc == NGX_ERROR) { | |
845 ctx->error = 1; | |
846 croak("ngx_http_perl_output() failed"); | |
847 } | |
788 | 848 |
789 XSRETURN_EMPTY; | 849 XSRETURN_EMPTY; |
790 | 850 |
791 | 851 |
792 void | 852 void |