Mercurial > hg > nginx
comparison src/http/modules/perl/nginx.xs @ 7526:8125552a10ca
Perl: handling of allocation errors.
Previously, allocation errors in nginx.xs were more or less ignored,
potentially resulting in incorrect code execution in specific low-memory
conditions. This is changed to use ctx->error bit and croak(), similarly
to how output errors are now handled.
Note that this is mostly a cosmetic change, as Perl itself exits on memory
allocation errors, and hence nginx with Perl is hardly usable in low-memory
conditions.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Fri, 12 Jul 2019 13:56:23 +0300 |
parents | 575480d3fd01 |
children | 02cd116ebe2a |
comparison
equal
deleted
inserted
replaced
7525:575480d3fd01 | 7526:8125552a10ca |
---|---|
141 sv = ST(1); | 141 sv = ST(1); |
142 | 142 |
143 if (ngx_http_perl_sv2str(aTHX_ r, &r->headers_out.content_type, sv) | 143 if (ngx_http_perl_sv2str(aTHX_ r, &r->headers_out.content_type, sv) |
144 != NGX_OK) | 144 != NGX_OK) |
145 { | 145 { |
146 XSRETURN_EMPTY; | 146 ctx->error = 1; |
147 croak("ngx_http_perl_sv2str() failed"); | |
147 } | 148 } |
148 | 149 |
149 r->headers_out.content_type_len = r->headers_out.content_type.len; | 150 r->headers_out.content_type_len = r->headers_out.content_type.len; |
150 | 151 |
151 } else { | 152 } else { |
152 if (ngx_http_set_content_type(r) != NGX_OK) { | 153 if (ngx_http_set_content_type(r) != NGX_OK) { |
153 XSRETURN_EMPTY; | 154 ctx->error = 1; |
155 croak("ngx_http_set_content_type() failed"); | |
154 } | 156 } |
155 } | 157 } |
156 | 158 |
157 r->disable_not_modified = 1; | 159 r->disable_not_modified = 1; |
158 | 160 |
268 | 270 |
269 /* look up hashed headers */ | 271 /* look up hashed headers */ |
270 | 272 |
271 lowcase_key = ngx_pnalloc(r->pool, len); | 273 lowcase_key = ngx_pnalloc(r->pool, len); |
272 if (lowcase_key == NULL) { | 274 if (lowcase_key == NULL) { |
273 XSRETURN_UNDEF; | 275 ctx->error = 1; |
276 croak("ngx_pnalloc() failed"); | |
274 } | 277 } |
275 | 278 |
276 hash = ngx_hash_strlow(lowcase_key, p, len); | 279 hash = ngx_hash_strlow(lowcase_key, p, len); |
277 | 280 |
278 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); | 281 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); |
328 size += ph[i]->value.len + sizeof("; ") - 1; | 331 size += ph[i]->value.len + sizeof("; ") - 1; |
329 } | 332 } |
330 | 333 |
331 value = ngx_pnalloc(r->pool, size); | 334 value = ngx_pnalloc(r->pool, size); |
332 if (value == NULL) { | 335 if (value == NULL) { |
333 XSRETURN_UNDEF; | 336 ctx->error = 1; |
337 croak("ngx_pnalloc() failed"); | |
334 } | 338 } |
335 | 339 |
336 p = value; | 340 p = value; |
337 | 341 |
338 for (i = 0; /* void */ ; i++) { | 342 for (i = 0; /* void */ ; i++) { |
463 len += buf->last - buf->pos; | 467 len += buf->last - buf->pos; |
464 } | 468 } |
465 | 469 |
466 p = ngx_pnalloc(r->pool, len); | 470 p = ngx_pnalloc(r->pool, len); |
467 if (p == NULL) { | 471 if (p == NULL) { |
468 XSRETURN_UNDEF; | 472 ctx->error = 1; |
473 croak("ngx_pnalloc() failed"); | |
469 } | 474 } |
470 | 475 |
471 data = p; | 476 data = p; |
472 cl = r->request_body->bufs; | 477 cl = r->request_body->bufs; |
473 | 478 |
545 key = ST(1); | 550 key = ST(1); |
546 value = ST(2); | 551 value = ST(2); |
547 | 552 |
548 header = ngx_list_push(&r->headers_out.headers); | 553 header = ngx_list_push(&r->headers_out.headers); |
549 if (header == NULL) { | 554 if (header == NULL) { |
550 XSRETURN_EMPTY; | 555 ctx->error = 1; |
556 croak("ngx_list_push() failed"); | |
551 } | 557 } |
552 | 558 |
553 header->hash = 1; | 559 header->hash = 1; |
554 | 560 |
555 if (ngx_http_perl_sv2str(aTHX_ r, &header->key, key) != NGX_OK) { | 561 if (ngx_http_perl_sv2str(aTHX_ r, &header->key, key) != NGX_OK) { |
556 header->hash = 0; | 562 header->hash = 0; |
557 XSRETURN_EMPTY; | 563 ctx->error = 1; |
564 croak("ngx_http_perl_sv2str() failed"); | |
558 } | 565 } |
559 | 566 |
560 if (ngx_http_perl_sv2str(aTHX_ r, &header->value, value) != NGX_OK) { | 567 if (ngx_http_perl_sv2str(aTHX_ r, &header->value, value) != NGX_OK) { |
561 header->hash = 0; | 568 header->hash = 0; |
562 XSRETURN_EMPTY; | 569 ctx->error = 1; |
570 croak("ngx_http_perl_sv2str() failed"); | |
563 } | 571 } |
564 | 572 |
565 if (header->key.len == sizeof("Content-Length") - 1 | 573 if (header->key.len == sizeof("Content-Length") - 1 |
566 && ngx_strncasecmp(header->key.data, (u_char *) "Content-Length", | 574 && ngx_strncasecmp(header->key.data, (u_char *) "Content-Length", |
567 sizeof("Content-Length") - 1) == 0) | 575 sizeof("Content-Length") - 1) == 0) |
592 if (ctx->filename.data) { | 600 if (ctx->filename.data) { |
593 goto done; | 601 goto done; |
594 } | 602 } |
595 | 603 |
596 if (ngx_http_map_uri_to_path(r, &ctx->filename, &root, 0) == NULL) { | 604 if (ngx_http_map_uri_to_path(r, &ctx->filename, &root, 0) == NULL) { |
597 XSRETURN_UNDEF; | 605 ctx->error = 1; |
606 croak("ngx_http_map_uri_to_path() failed"); | |
598 } | 607 } |
599 | 608 |
600 ctx->filename.len--; | 609 ctx->filename.len--; |
601 sv_setpv(PL_statname, (char *) ctx->filename.data); | 610 sv_setpv(PL_statname, (char *) ctx->filename.data); |
602 | 611 |
648 XSRETURN_EMPTY; | 657 XSRETURN_EMPTY; |
649 } | 658 } |
650 | 659 |
651 b = ngx_calloc_buf(r->pool); | 660 b = ngx_calloc_buf(r->pool); |
652 if (b == NULL) { | 661 if (b == NULL) { |
653 XSRETURN_EMPTY; | 662 ctx->error = 1; |
663 croak("ngx_calloc_buf() failed"); | |
654 } | 664 } |
655 | 665 |
656 b->memory = 1; | 666 b->memory = 1; |
657 b->pos = p; | 667 b->pos = p; |
658 b->last = p + len; | 668 b->last = p + len; |
688 XSRETURN_EMPTY; | 698 XSRETURN_EMPTY; |
689 } | 699 } |
690 | 700 |
691 b = ngx_create_temp_buf(r->pool, size); | 701 b = ngx_create_temp_buf(r->pool, size); |
692 if (b == NULL) { | 702 if (b == NULL) { |
693 XSRETURN_EMPTY; | 703 ctx->error = 1; |
704 croak("ngx_create_temp_buf() failed"); | |
694 } | 705 } |
695 | 706 |
696 for (i = 1; i < items; i++) { | 707 for (i = 1; i < items; i++) { |
697 sv = ST(i); | 708 sv = ST(i); |
698 | 709 |
744 offset = items < 3 ? -1 : SvIV(ST(2)); | 755 offset = items < 3 ? -1 : SvIV(ST(2)); |
745 bytes = items < 4 ? 0 : SvIV(ST(3)); | 756 bytes = items < 4 ? 0 : SvIV(ST(3)); |
746 | 757 |
747 b = ngx_calloc_buf(r->pool); | 758 b = ngx_calloc_buf(r->pool); |
748 if (b == NULL) { | 759 if (b == NULL) { |
749 XSRETURN_EMPTY; | 760 ctx->error = 1; |
761 croak("ngx_calloc_buf() failed"); | |
750 } | 762 } |
751 | 763 |
752 b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t)); | 764 b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t)); |
753 if (b->file == NULL) { | 765 if (b->file == NULL) { |
754 XSRETURN_EMPTY; | 766 ctx->error = 1; |
767 croak("ngx_pcalloc() failed"); | |
755 } | 768 } |
756 | 769 |
757 path.len = ngx_strlen(filename); | 770 path.len = ngx_strlen(filename); |
758 | 771 |
759 path.data = ngx_pnalloc(r->pool, path.len + 1); | 772 path.data = ngx_pnalloc(r->pool, path.len + 1); |
760 if (path.data == NULL) { | 773 if (path.data == NULL) { |
761 XSRETURN_EMPTY; | 774 ctx->error = 1; |
775 croak("ngx_pnalloc() failed"); | |
762 } | 776 } |
763 | 777 |
764 (void) ngx_cpystrn(path.data, (u_char *) filename, path.len + 1); | 778 (void) ngx_cpystrn(path.data, (u_char *) filename, path.len + 1); |
765 | 779 |
766 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | 780 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); |
773 of.min_uses = clcf->open_file_cache_min_uses; | 787 of.min_uses = clcf->open_file_cache_min_uses; |
774 of.errors = clcf->open_file_cache_errors; | 788 of.errors = clcf->open_file_cache_errors; |
775 of.events = clcf->open_file_cache_events; | 789 of.events = clcf->open_file_cache_events; |
776 | 790 |
777 if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) { | 791 if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) { |
778 XSRETURN_EMPTY; | 792 ctx->error = 1; |
793 croak("ngx_http_set_disable_symlinks() failed"); | |
779 } | 794 } |
780 | 795 |
781 if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool) | 796 if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool) |
782 != NGX_OK) | 797 != NGX_OK) |
783 { | 798 { |
784 if (of.err == 0) { | 799 if (of.err == 0) { |
785 XSRETURN_EMPTY; | 800 ctx->error = 1; |
801 croak("ngx_open_cached_file() failed"); | |
786 } | 802 } |
787 | 803 |
788 ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, | 804 ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, |
789 "%s \"%s\" failed", of.failed, filename); | 805 "%s \"%s\" failed", of.failed, filename); |
790 XSRETURN_EMPTY; | 806 |
807 ctx->error = 1; | |
808 croak("ngx_open_cached_file() failed"); | |
791 } | 809 } |
792 | 810 |
793 if (offset == -1) { | 811 if (offset == -1) { |
794 offset = 0; | 812 offset = 0; |
795 } | 813 } |
830 croak("flush(): called after error"); | 848 croak("flush(): called after error"); |
831 } | 849 } |
832 | 850 |
833 b = ngx_calloc_buf(r->pool); | 851 b = ngx_calloc_buf(r->pool); |
834 if (b == NULL) { | 852 if (b == NULL) { |
835 XSRETURN_EMPTY; | 853 ctx->error = 1; |
854 croak("ngx_calloc_buf() failed"); | |
836 } | 855 } |
837 | 856 |
838 b->flush = 1; | 857 b->flush = 1; |
839 | 858 |
840 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "$r->flush"); | 859 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "$r->flush"); |
861 ngx_http_perl_set_request(r, ctx); | 880 ngx_http_perl_set_request(r, ctx); |
862 | 881 |
863 uri = ST(1); | 882 uri = ST(1); |
864 | 883 |
865 if (ngx_http_perl_sv2str(aTHX_ r, &ctx->redirect_uri, uri) != NGX_OK) { | 884 if (ngx_http_perl_sv2str(aTHX_ r, &ctx->redirect_uri, uri) != NGX_OK) { |
866 XSRETURN_EMPTY; | 885 ctx->error = 1; |
886 croak("ngx_http_perl_sv2str() failed"); | |
867 } | 887 } |
868 | 888 |
869 for (i = 0; i < ctx->redirect_uri.len; i++) { | 889 for (i = 0; i < ctx->redirect_uri.len; i++) { |
870 if (ctx->redirect_uri.data[i] == '?') { | 890 if (ctx->redirect_uri.data[i] == '?') { |
871 | 891 |
908 | 928 |
909 src = (u_char *) SvPV(text, len); | 929 src = (u_char *) SvPV(text, len); |
910 | 930 |
911 p = ngx_pnalloc(r->pool, len + 1); | 931 p = ngx_pnalloc(r->pool, len + 1); |
912 if (p == NULL) { | 932 if (p == NULL) { |
913 XSRETURN_UNDEF; | 933 ctx->error = 1; |
934 croak("ngx_pnalloc() failed"); | |
914 } | 935 } |
915 | 936 |
916 dst = p; | 937 dst = p; |
917 | 938 |
918 type = items < 3 ? 0 : SvIV(ST(2)); | 939 type = items < 3 ? 0 : SvIV(ST(2)); |
957 if (SvROK(value) && SvTYPE(SvRV(value)) == SVt_PV) { | 978 if (SvROK(value) && SvTYPE(SvRV(value)) == SVt_PV) { |
958 value = SvRV(value); | 979 value = SvRV(value); |
959 } | 980 } |
960 | 981 |
961 if (ngx_http_perl_sv2str(aTHX_ r, &val, value) != NGX_OK) { | 982 if (ngx_http_perl_sv2str(aTHX_ r, &val, value) != NGX_OK) { |
962 XSRETURN_UNDEF; | 983 ctx->error = 1; |
984 croak("ngx_http_perl_sv2str() failed"); | |
963 } | 985 } |
964 } | 986 } |
965 | 987 |
966 p = (u_char *) SvPV(name, len); | 988 p = (u_char *) SvPV(name, len); |
967 | 989 |
968 lowcase = ngx_pnalloc(r->pool, len); | 990 lowcase = ngx_pnalloc(r->pool, len); |
969 if (lowcase == NULL) { | 991 if (lowcase == NULL) { |
970 XSRETURN_UNDEF; | 992 ctx->error = 1; |
993 croak("ngx_pnalloc() failed"); | |
971 } | 994 } |
972 | 995 |
973 hash = ngx_hash_strlow(lowcase, p, len); | 996 hash = ngx_hash_strlow(lowcase, p, len); |
974 | 997 |
975 var.len = len; | 998 var.len = len; |
985 } | 1008 } |
986 #endif | 1009 #endif |
987 | 1010 |
988 vv = ngx_http_get_variable(r, &var, hash); | 1011 vv = ngx_http_get_variable(r, &var, hash); |
989 if (vv == NULL) { | 1012 if (vv == NULL) { |
990 XSRETURN_UNDEF; | 1013 ctx->error = 1; |
1014 croak("ngx_http_get_variable() failed"); | |
991 } | 1015 } |
992 | 1016 |
993 if (vv->not_found) { | 1017 if (vv->not_found) { |
994 | 1018 |
995 if (ctx->variables) { | 1019 if (ctx->variables) { |
1018 if (value) { | 1042 if (value) { |
1019 if (ctx->variables == NULL) { | 1043 if (ctx->variables == NULL) { |
1020 ctx->variables = ngx_array_create(r->pool, 1, | 1044 ctx->variables = ngx_array_create(r->pool, 1, |
1021 sizeof(ngx_http_perl_var_t)); | 1045 sizeof(ngx_http_perl_var_t)); |
1022 if (ctx->variables == NULL) { | 1046 if (ctx->variables == NULL) { |
1023 XSRETURN_UNDEF; | 1047 ctx->error = 1; |
1048 croak("ngx_array_create() failed"); | |
1024 } | 1049 } |
1025 } | 1050 } |
1026 | 1051 |
1027 v = ngx_array_push(ctx->variables); | 1052 v = ngx_array_push(ctx->variables); |
1028 if (v == NULL) { | 1053 if (v == NULL) { |
1029 XSRETURN_UNDEF; | 1054 ctx->error = 1; |
1055 croak("ngx_array_push() failed"); | |
1030 } | 1056 } |
1031 | 1057 |
1032 v->hash = hash; | 1058 v->hash = hash; |
1033 v->name.len = len; | 1059 v->name.len = len; |
1034 v->name.data = lowcase; | 1060 v->name.data = lowcase; |