Welcome! Log In Create A New Profile

Advanced

[nginx] Perl: reworked perl module to pass ctx instead of request.

Maxim Dounin
July 12, 2019 10:54AM
details: https://hg.nginx.org/nginx/rev/deebe988cbd7
branches:
changeset: 7524:deebe988cbd7
user: Maxim Dounin <mdounin@mdounin.ru>
date: Fri Jul 12 11:29:22 2019 +0300
description:
Perl: reworked perl module to pass ctx instead of request.

This ensures that correct ctx is always available, including after
filter finalization. In particular, this fixes a segmentation fault
with the following configuration:

location / {
image_filter test;

perl 'sub {
my $r = shift;
$r->send_http_header();
$r->print("foo\n");
$r->print("bar\n");
}';
}

This also seems to be the only way to correctly handle filter finalization
in various complex cases, for example, when embedded perl is used both
in the original handler and in an error page called after filter
finalization.

diffstat:

src/http/modules/perl/nginx.xs | 180 ++++++++++++++------------
src/http/modules/perl/ngx_http_perl_module.c | 26 ++-
src/http/modules/perl/ngx_http_perl_module.h | 2 +
3 files changed, 114 insertions(+), 94 deletions(-)

diffs (552 lines):

diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs
--- a/src/http/modules/perl/nginx.xs
+++ b/src/http/modules/perl/nginx.xs
@@ -15,8 +15,10 @@
#include "XSUB.h"


-#define ngx_http_perl_set_request(r) \
- r = INT2PTR(ngx_http_request_t *, SvIV((SV *) SvRV(ST(0))))
+#define ngx_http_perl_set_request(r, ctx) \
+ \
+ ctx = INT2PTR(ngx_http_perl_ctx_t *, SvIV((SV *) SvRV(ST(0)))); \
+ r = ctx->request


#define ngx_http_perl_set_targ(p, len) \
@@ -64,14 +66,12 @@ ngx_http_perl_sv2str(pTHX_ ngx_http_requ


static ngx_int_t
-ngx_http_perl_output(ngx_http_request_t *r, ngx_buf_t *b)
+ngx_http_perl_output(ngx_http_request_t *r, ngx_http_perl_ctx_t *ctx,
+ ngx_buf_t *b)
{
- ngx_chain_t out;
+ ngx_chain_t out;
#if (NGX_HTTP_SSI)
- ngx_chain_t *cl;
- ngx_http_perl_ctx_t *ctx;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
+ ngx_chain_t *cl;

if (ctx->ssi) {
cl = ngx_alloc_chain_link(r->pool);
@@ -105,9 +105,10 @@ void
status(r, code)
CODE:

- ngx_http_request_t *r;
+ ngx_http_request_t *r;
+ ngx_http_perl_ctx_t *ctx;

- ngx_http_perl_set_request(r);
+ ngx_http_perl_set_request(r, ctx);

r->headers_out.status = SvIV(ST(1));

@@ -121,10 +122,11 @@ void
send_http_header(r, ...)
CODE:

- ngx_http_request_t *r;
- SV *sv;
+ ngx_http_request_t *r;
+ ngx_http_perl_ctx_t *ctx;
+ SV *sv;

- ngx_http_perl_set_request(r);
+ ngx_http_perl_set_request(r, ctx);

if (r->headers_out.status == 0) {
r->headers_out.status = NGX_HTTP_OK;
@@ -157,9 +159,10 @@ header_only(r)
CODE:

dXSTARG;
- ngx_http_request_t *r;
+ ngx_http_request_t *r;
+ ngx_http_perl_ctx_t *ctx;

- ngx_http_perl_set_request(r);
+ ngx_http_perl_set_request(r, ctx);

sv_upgrade(TARG, SVt_IV);
sv_setiv(TARG, r->header_only);
@@ -172,9 +175,10 @@ uri(r)
CODE:

dXSTARG;
- ngx_http_request_t *r;
+ ngx_http_request_t *r;
+ ngx_http_perl_ctx_t *ctx;

- ngx_http_perl_set_request(r);
+ ngx_http_perl_set_request(r, ctx);
ngx_http_perl_set_targ(r->uri.data, r->uri.len);

ST(0) = TARG;
@@ -185,9 +189,10 @@ args(r)
CODE:

dXSTARG;
- ngx_http_request_t *r;
+ ngx_http_request_t *r;
+ ngx_http_perl_ctx_t *ctx;

- ngx_http_perl_set_request(r);
+ ngx_http_perl_set_request(r, ctx);
ngx_http_perl_set_targ(r->args.data, r->args.len);

ST(0) = TARG;
@@ -198,9 +203,10 @@ request_method(r)
CODE:

dXSTARG;
- ngx_http_request_t *r;
+ ngx_http_request_t *r;
+ ngx_http_perl_ctx_t *ctx;

- ngx_http_perl_set_request(r);
+ ngx_http_perl_set_request(r, ctx);
ngx_http_perl_set_targ(r->method_name.data, r->method_name.len);

ST(0) = TARG;
@@ -211,9 +217,10 @@ remote_addr(r)
CODE:

dXSTARG;
- ngx_http_request_t *r;
+ ngx_http_request_t *r;
+ ngx_http_perl_ctx_t *ctx;

- ngx_http_perl_set_request(r);
+ ngx_http_perl_set_request(r, ctx);
ngx_http_perl_set_targ(r->connection->addr_text.data,
r->connection->addr_text.len);

@@ -226,6 +233,7 @@ header_in(r, key)

dXSTARG;
ngx_http_request_t *r;
+ ngx_http_perl_ctx_t *ctx;
SV *key;
u_char *p, *lowcase_key, *value, sep;
STRLEN len;
@@ -237,7 +245,7 @@ header_in(r, key)
ngx_http_header_t *hh;
ngx_http_core_main_conf_t *cmcf;

- ngx_http_perl_set_request(r);
+ ngx_http_perl_set_request(r, ctx);

key = ST(1);

@@ -374,13 +382,12 @@ has_request_body(r, next)
ngx_http_request_t *r;
ngx_http_perl_ctx_t *ctx;

- ngx_http_perl_set_request(r);
+ ngx_http_perl_set_request(r, ctx);

if (r->headers_in.content_length_n <= 0 && !r->headers_in.chunked) {
XSRETURN_UNDEF;
}

- ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
ctx->next = SvRV(ST(1));

r->request_body_in_single_buf = 1;
@@ -404,13 +411,14 @@ request_body(r)
CODE:

dXSTARG;
- ngx_http_request_t *r;
- u_char *p, *data;
- size_t len;
- ngx_buf_t *buf;
- ngx_chain_t *cl;
+ ngx_http_request_t *r;
+ ngx_http_perl_ctx_t *ctx;
+ u_char *p, *data;
+ size_t len;
+ ngx_buf_t *buf;
+ ngx_chain_t *cl;

- ngx_http_perl_set_request(r);
+ ngx_http_perl_set_request(r, ctx);

if (r->request_body == NULL
|| r->request_body->temp_file
@@ -465,9 +473,10 @@ request_body_file(r)
CODE:

dXSTARG;
- ngx_http_request_t *r;
+ ngx_http_request_t *r;
+ ngx_http_perl_ctx_t *ctx;

- ngx_http_perl_set_request(r);
+ ngx_http_perl_set_request(r, ctx);

if (r->request_body == NULL || r->request_body->temp_file == NULL) {
XSRETURN_UNDEF;
@@ -483,9 +492,10 @@ void
discard_request_body(r)
CODE:

- ngx_http_request_t *r;
+ ngx_http_request_t *r;
+ ngx_http_perl_ctx_t *ctx;

- ngx_http_perl_set_request(r);
+ ngx_http_perl_set_request(r, ctx);

ngx_http_discard_request_body(r);

@@ -494,12 +504,13 @@ void
header_out(r, key, value)
CODE:

- ngx_http_request_t *r;
- SV *key;
- SV *value;
- ngx_table_elt_t *header;
+ ngx_http_request_t *r;
+ ngx_http_perl_ctx_t *ctx;
+ SV *key;
+ SV *value;
+ ngx_table_elt_t *header;

- ngx_http_perl_set_request(r);
+ ngx_http_perl_set_request(r, ctx);

key = ST(1);
value = ST(2);
@@ -542,13 +553,12 @@ filename(r)
CODE:

dXSTARG;
- size_t root;
ngx_http_request_t *r;
ngx_http_perl_ctx_t *ctx;
+ size_t root;

- ngx_http_perl_set_request(r);
+ ngx_http_perl_set_request(r, ctx);

- ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
if (ctx->filename.data) {
goto done;
}
@@ -571,15 +581,16 @@ void
print(r, ...)
CODE:

- ngx_http_request_t *r;
- SV *sv;
- int i;
- u_char *p;
- size_t size;
- STRLEN len;
- ngx_buf_t *b;
+ ngx_http_request_t *r;
+ ngx_http_perl_ctx_t *ctx;
+ SV *sv;
+ int i;
+ u_char *p;
+ size_t size;
+ STRLEN len;
+ ngx_buf_t *b;

- ngx_http_perl_set_request(r);
+ ngx_http_perl_set_request(r, ctx);

if (items == 2) {

@@ -660,7 +671,7 @@ print(r, ...)

out:

- (void) ngx_http_perl_output(r, b);
+ (void) ngx_http_perl_output(r, ctx, b);


void
@@ -668,6 +679,7 @@ sendfile(r, filename, offset = -1, bytes
CODE:

ngx_http_request_t *r;
+ ngx_http_perl_ctx_t *ctx;
char *filename;
off_t offset;
size_t bytes;
@@ -676,7 +688,7 @@ sendfile(r, filename, offset = -1, bytes
ngx_open_file_info_t of;
ngx_http_core_loc_conf_t *clcf;

- ngx_http_perl_set_request(r);
+ ngx_http_perl_set_request(r, ctx);

filename = SvPV_nolen(ST(1));

@@ -750,17 +762,18 @@ sendfile(r, filename, offset = -1, bytes
b->file->log = r->connection->log;
b->file->directio = of.is_directio;

- (void) ngx_http_perl_output(r, b);
+ (void) ngx_http_perl_output(r, ctx, b);


void
flush(r)
CODE:

- ngx_http_request_t *r;
- ngx_buf_t *b;
+ ngx_http_request_t *r;
+ ngx_http_perl_ctx_t *ctx;
+ ngx_buf_t *b;

- ngx_http_perl_set_request(r);
+ ngx_http_perl_set_request(r, ctx);

b = ngx_calloc_buf(r->pool);
if (b == NULL) {
@@ -771,7 +784,7 @@ flush(r)

ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "$r->flush");

- (void) ngx_http_perl_output(r, b);
+ (void) ngx_http_perl_output(r, ctx, b);

XSRETURN_EMPTY;

@@ -781,16 +794,14 @@ internal_redirect(r, uri)
CODE:

ngx_http_request_t *r;
+ ngx_http_perl_ctx_t *ctx;
SV *uri;
ngx_uint_t i;
- ngx_http_perl_ctx_t *ctx;

- ngx_http_perl_set_request(r);
+ ngx_http_perl_set_request(r, ctx);

uri = ST(1);

- ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
-
if (ngx_http_perl_sv2str(aTHX_ r, &ctx->redirect_uri, uri) != NGX_OK) {
XSRETURN_EMPTY;
}
@@ -811,9 +822,10 @@ void
allow_ranges(r)
CODE:

- ngx_http_request_t *r;
+ ngx_http_request_t *r;
+ ngx_http_perl_ctx_t *ctx;

- ngx_http_perl_set_request(r);
+ ngx_http_perl_set_request(r, ctx);

r->allow_ranges = 1;

@@ -823,13 +835,14 @@ unescape(r, text, type = 0)
CODE:

dXSTARG;
- ngx_http_request_t *r;
- SV *text;
- int type;
- u_char *p, *dst, *src;
- STRLEN len;
+ ngx_http_request_t *r;
+ ngx_http_perl_ctx_t *ctx;
+ SV *text;
+ int type;
+ u_char *p, *dst, *src;
+ STRLEN len;

- ngx_http_perl_set_request(r);
+ ngx_http_perl_set_request(r, ctx);

text = ST(1);

@@ -858,16 +871,16 @@ variable(r, name, value = NULL)

dXSTARG;
ngx_http_request_t *r;
+ ngx_http_perl_ctx_t *ctx;
SV *name, *value;
u_char *p, *lowcase;
STRLEN len;
ngx_str_t var, val;
ngx_uint_t i, hash;
ngx_http_perl_var_t *v;
- ngx_http_perl_ctx_t *ctx;
ngx_http_variable_value_t *vv;

- ngx_http_perl_set_request(r);
+ ngx_http_perl_set_request(r, ctx);

name = ST(1);

@@ -919,8 +932,6 @@ variable(r, name, value = NULL)

if (vv->not_found) {

- ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
-
if (ctx->variables) {

v = ctx->variables->elts;
@@ -991,18 +1002,16 @@ sleep(r, sleep, next)
CODE:

ngx_http_request_t *r;
+ ngx_http_perl_ctx_t *ctx;
ngx_msec_t sleep;
- ngx_http_perl_ctx_t *ctx;

- ngx_http_perl_set_request(r);
+ ngx_http_perl_set_request(r, ctx);

sleep = (ngx_msec_t) SvIV(ST(1));

ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"perl sleep: %M", sleep);

- ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
-
ctx->next = SvRV(ST(2));

r->connection->write->delayed = 1;
@@ -1016,13 +1025,14 @@ void
log_error(r, err, msg)
CODE:

- ngx_http_request_t *r;
- SV *err, *msg;
- u_char *p;
- STRLEN len;
- ngx_err_t e;
+ ngx_http_request_t *r;
+ ngx_http_perl_ctx_t *ctx;
+ SV *err, *msg;
+ u_char *p;
+ STRLEN len;
+ ngx_err_t e;

- ngx_http_perl_set_request(r);
+ ngx_http_perl_set_request(r, ctx);

err = ST(1);

diff --git a/src/http/modules/perl/ngx_http_perl_module.c b/src/http/modules/perl/ngx_http_perl_module.c
--- a/src/http/modules/perl/ngx_http_perl_module.c
+++ b/src/http/modules/perl/ngx_http_perl_module.c
@@ -43,7 +43,8 @@ static PerlInterpreter *ngx_http_perl_cr
static ngx_int_t ngx_http_perl_run_requires(pTHX_ ngx_array_t *requires,
ngx_log_t *log);
static ngx_int_t ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r,
- HV *nginx, SV *sub, SV **args, ngx_str_t *handler, ngx_str_t *rv);
+ ngx_http_perl_ctx_t *ctx, HV *nginx, SV *sub, SV **args,
+ ngx_str_t *handler, ngx_str_t *rv);
static void ngx_http_perl_eval_anon_sub(pTHX_ ngx_str_t *handler, SV **sv);

static ngx_int_t ngx_http_perl_preconfiguration(ngx_conf_t *cf);
@@ -199,6 +200,8 @@ ngx_http_perl_handle_request(ngx_http_re
}

ngx_http_set_ctx(r, ctx, ngx_http_perl_module);
+
+ ctx->request = r;
}

pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module);
@@ -220,8 +223,8 @@ ngx_http_perl_handle_request(ngx_http_re
ctx->next = NULL;
}

- rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, sub, NULL, handler,
- NULL);
+ rc = ngx_http_perl_call_handler(aTHX_ r, ctx, pmcf->nginx, sub, NULL,
+ handler, NULL);

}

@@ -309,6 +312,8 @@ ngx_http_perl_variable(ngx_http_request_
}

ngx_http_set_ctx(r, ctx, ngx_http_perl_module);
+
+ ctx->request = r;
}

pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module);
@@ -321,7 +326,7 @@ ngx_http_perl_variable(ngx_http_request_
PERL_SET_CONTEXT(pmcf->perl);
PERL_SET_INTERP(pmcf->perl);

- rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, pv->sub, NULL,
+ rc = ngx_http_perl_call_handler(aTHX_ r, ctx, pmcf->nginx, pv->sub, NULL,
&pv->handler, &value);

}
@@ -372,6 +377,8 @@ ngx_http_perl_ssi(ngx_http_request_t *r,
}

ngx_http_set_ctx(r, ctx, ngx_http_perl_module);
+
+ ctx->request = r;
}

pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module);
@@ -430,8 +437,8 @@ ngx_http_perl_ssi(ngx_http_request_t *r,
asv = NULL;
}

- rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, sv, asv, handler,
- NULL);
+ rc = ngx_http_perl_call_handler(aTHX_ r, ctx, pmcf->nginx, sv, asv,
+ handler, NULL);

SvREFCNT_dec(sv);

@@ -667,8 +674,9 @@ ngx_http_perl_run_requires(pTHX_ ngx_arr


static ngx_int_t
-ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r, HV *nginx, SV *sub,
- SV **args, ngx_str_t *handler, ngx_str_t *rv)
+ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r,
+ ngx_http_perl_ctx_t *ctx, HV *nginx, SV *sub, SV **args,
+ ngx_str_t *handler, ngx_str_t *rv)
{
SV *sv;
int n, status;
@@ -687,7 +695,7 @@ ngx_http_perl_call_handler(pTHX_ ngx_htt

PUSHMARK(sp);

- sv = sv_2mortal(sv_bless(newRV_noinc(newSViv(PTR2IV(r))), nginx));
+ sv = sv_2mortal(sv_bless(newRV_noinc(newSViv(PTR2IV(ctx))), nginx));
XPUSHs(sv);

if (args) {
diff --git a/src/http/modules/perl/ngx_http_perl_module.h b/src/http/modules/perl/ngx_http_perl_module.h
--- a/src/http/modules/perl/ngx_http_perl_module.h
+++ b/src/http/modules/perl/ngx_http_perl_module.h
@@ -21,6 +21,8 @@
typedef ngx_http_request_t *nginx;

typedef struct {
+ ngx_http_request_t *request;
+
ngx_str_t filename;
ngx_str_t redirect_uri;
ngx_str_t redirect_args;
_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel
Subject Author Views Posted

[nginx] Perl: reworked perl module to pass ctx instead of request.

Maxim Dounin 167 July 12, 2019 10:54AM



Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 207
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready