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;