[PATCH 3 of 4] Tests: more tests with variables which change between accesses
Maxim Dounin
mdounin at mdounin.ru
Mon Jun 8 17:46:41 UTC 2026
# HG changeset patch
# User Maxim Dounin <mdounin at mdounin.ru>
# Date 1780936532 -10800
# Mon Jun 08 19:35:32 2026 +0300
# Node ID e2ccdc5e3d031950a1a833b372791812902cc365
# Parent 4af2fea518e2389a44c483ace19f7b4e645989a7
Tests: more tests with variables which change between accesses.
These tests are designed to test all cases where script evaluation is
done directly by a module (proxy, grpc, fastcgi, scgi, uwsgi, try_files,
index), rather than thru standard functions (ngx_http_script_run(),
ngx_http_complex_value()), and use a capture and a map which changes
the capture to trigger buffer overrun.
diff --git a/fastcgi_header_params.t b/fastcgi_header_params.t
--- a/fastcgi_header_params.t
+++ b/fastcgi_header_params.t
@@ -25,7 +25,7 @@ eval { require FCGI; };
plan(skip_all => 'FCGI not installed') if $@;
plan(skip_all => 'win32') if $^O eq 'MSWin32';
-my $t = Test::Nginx->new()->has(qw/http fastcgi/)->plan(4)
+my $t = Test::Nginx->new()->has(qw/http fastcgi rewrite map/)->plan(5)
->write_file_expand('nginx.conf', <<'EOF');
%%TEST_GLOBALS%%
@@ -38,6 +38,10 @@ events {
http {
%%TEST_GLOBALS_HTTP%%
+ map $uri $map_capture {
+ ~(?<capture>.*) $capture;
+ }
+
server {
listen 127.0.0.1:8080;
server_name localhost;
@@ -46,6 +50,12 @@ http {
fastcgi_pass 127.0.0.1:8081;
fastcgi_param HTTP_X_BLAH "blah";
}
+
+ location /map/ {
+ fastcgi_pass 127.0.0.1:8081;
+ fastcgi_param REQUEST_URI $request_uri;
+ fastcgi_param HTTP_FOO "foo $capture $map_capture end";
+ }
}
}
@@ -85,6 +95,17 @@ like($r, qr/X-Cookie: foo; bar; bazz/,
like($r, qr/X-Foo: foo, bar, bazz/,
'fastcgi with multiple unknown headers');
+TODO: {
+todo_skip 'might coredump', 1
+ unless $t->has_version('1.31.3')
+ or $ENV{TEST_NGINX_UNSAFE};
+local $TODO = 'not yet', $t->todo_alerts();
+
+like(http_get('/map/test-long-uri'), qr!foo .* /map/test-long-uri end!,
+ 'fastcgi params and map with side effects');
+
+}
+
###############################################################################
sub http_get_headers {
diff --git a/grpc_headers.t b/grpc_headers.t
new file mode 100644
--- /dev/null
+++ b/grpc_headers.t
@@ -0,0 +1,95 @@
+#!/usr/bin/perl
+
+# (C) Maxim Dounin
+
+# Tests for grpc module, grpc_set_header directive.
+
+###############################################################################
+
+use warnings;
+use strict;
+
+use Test::More;
+
+BEGIN { use FindBin; chdir($FindBin::Bin); }
+
+use lib 'lib';
+use Test::Nginx;
+
+###############################################################################
+
+select STDERR; $| = 1;
+select STDOUT; $| = 1;
+
+my $t = Test::Nginx->new()
+ ->has(qw/http http_v2 grpc rewrite/)->plan(2)
+ ->write_file_expand('nginx.conf', <<'EOF');
+
+%%TEST_GLOBALS%%
+
+daemon off;
+
+events {
+}
+
+http {
+ %%TEST_GLOBALS_HTTP%%
+
+ map $uri $map_capture {
+ ~(?<capture>.*) $capture;
+ }
+
+ server {
+ listen 127.0.0.1:8080;
+ server_name localhost;
+
+ location / {
+ grpc_pass 127.0.0.1:8081;
+ grpc_set_header X-Blah "blah $capture $map_capture end";
+ }
+
+ location /multi {
+ grpc_pass 127.0.0.1:8081;
+ grpc_set_header X-Blah1 "$capture";
+ grpc_set_header X-Blah2 "$capture";
+ grpc_set_header X-Blah3 "$capture";
+ grpc_set_header X-Blah4 "$capture";
+ grpc_set_header X-Blah5 "$capture";
+ grpc_set_header X-Blah6 "$capture";
+ grpc_set_header X-Blah "blah $map_capture end";
+ }
+ }
+
+ server {
+ listen 127.0.0.1:8081;
+ server_name localhost;
+
+ http2 on;
+
+ location / {
+ return 200 "$http_x_blah\n";
+ }
+ }
+}
+
+EOF
+
+$t->run();
+
+###############################################################################
+
+TODO: {
+todo_skip 'might coredump', 2
+ unless $t->has_version('1.31.3')
+ or $ENV{TEST_NGINX_UNSAFE};
+local $TODO = 'not yet', $t->todo_alerts();
+
+like(http_get('/test-long-uri'), qr!blah .* /test-long-uri end!,
+ 'grpc_set_header and map with side effects');
+
+like(http_get('/multi'), qr!blah /multi end!,
+ 'grpc_set_header and map with side effects, multiple headers');
+
+}
+
+###############################################################################
diff --git a/http_try_files.t b/http_try_files.t
--- a/http_try_files.t
+++ b/http_try_files.t
@@ -21,7 +21,7 @@ use Test::Nginx;
select STDERR; $| = 1;
select STDOUT; $| = 1;
-my $t = Test::Nginx->new()->has(qw/http proxy rewrite/)->plan(48)
+my $t = Test::Nginx->new()->has(qw/http proxy rewrite map/)->plan(49)
->write_file_expand('nginx.conf', <<'EOF');
%%TEST_GLOBALS%%
@@ -34,6 +34,10 @@ events {
http {
%%TEST_GLOBALS_HTTP%%
+ map $uri $map_capture {
+ ~(?<capture>.*) $capture;
+ }
+
server {
listen 127.0.0.1:8080;
server_name localhost;
@@ -189,6 +193,10 @@ http {
location = /uri-after-alias-add-redirect {
try_files /notfound /uri-after-alias-add/found;
}
+
+ location /map/ {
+ try_files /$capture/$map_capture =404;
+ }
}
server {
@@ -396,4 +404,15 @@ like(http_get('/uri-after-alias-add-redi
}
+TODO: {
+todo_skip 'might coredump', 1
+ unless $t->has_version('1.31.3')
+ or $ENV{TEST_NGINX_UNSAFE};
+local $TODO = 'not yet', $t->todo_alerts();
+
+like(http_get('/map/test-long-uri'), qr!404 Not!,
+ 'try_files and map with side effects');
+
+}
+
###############################################################################
diff --git a/index.t b/index.t
--- a/index.t
+++ b/index.t
@@ -22,7 +22,7 @@ use Test::Nginx;
select STDERR; $| = 1;
select STDOUT; $| = 1;
-my $t = Test::Nginx->new()->has(qw/http/)->plan(14)
+my $t = Test::Nginx->new()->has(qw/http rewrite map/)->plan(16)
->write_file_expand('nginx.conf', <<'EOF');
%%TEST_GLOBALS%%
@@ -35,6 +35,14 @@ events {
http {
%%TEST_GLOBALS_HTTP%%
+ map $uri $map_capture {
+ ~(?<capture>.*) $capture;
+ }
+
+ map $uri $map_shrink {
+ ~(?<shrink>) "";
+ }
+
server {
listen 127.0.0.1:8080;
server_name localhost;
@@ -86,6 +94,16 @@ http {
log_not_found off;
}
}
+
+ location /map/test-long-uri/ {
+ alias %%TESTDIR%%/;
+ index index.$capture.$map_capture /index.html;
+ }
+ location /shrink/ {
+ alias %%TESTDIR%%/;
+ set $shrink "some-long-variable-value";
+ index index$shrink$map_shrink.html /index.html;
+ }
}
}
@@ -119,6 +137,25 @@ like(http_get('/not_found/off/'), qr/404
like(http_get('/forbidden/'), qr/403 Forbidden/, 'directory access denied');
like(http_get('/index.html/'), qr/404 Not Found/, 'not a directory');
+TODO: {
+todo_skip 'might coredump', 1
+ unless $t->has_version('1.31.3')
+ or $ENV{TEST_NGINX_UNSAFE};
+local $TODO = 'not yet', $t->todo_alerts();
+
+like(http_get('/map/test-long-uri/'), qr!X-URI: /index.html\x0d($).*body!ms,
+ 'index and map with side effects');
+
+}
+
+TODO: {
+local $TODO = 'not yet' unless $t->has_version('1.31.3');
+
+like(http_get('/shrink/'), qr!X-URI: /shrink/index.html\x0d?($).*body!ms,
+ 'index and map with shrink side effect');
+
+}
+
$t->stop();
like($t->read_file('log_not_found.log'), qr/error/, 'log_not_found');
diff --git a/proxy_set_body.t b/proxy_set_body.t
--- a/proxy_set_body.t
+++ b/proxy_set_body.t
@@ -21,7 +21,7 @@ use Test::Nginx;
select STDERR; $| = 1;
select STDOUT; $| = 1;
-my $t = Test::Nginx->new()->has(qw/http proxy rewrite/)->plan(2)
+my $t = Test::Nginx->new()->has(qw/http proxy rewrite map/)->plan(4)
->write_file_expand('nginx.conf', <<'EOF');
%%TEST_GLOBALS%%
@@ -34,6 +34,10 @@ events {
http {
%%TEST_GLOBALS_HTTP%%
+ map $uri $map_capture {
+ ~(?<capture>.*) $capture;
+ }
+
server {
listen 127.0.0.1:8080;
server_name localhost;
@@ -58,8 +62,19 @@ http {
return 204;
}
+ location /map {
+ proxy_pass http://127.0.0.1:8080/body;
+ proxy_set_body "body $capture $map_capture end";
+ }
+
+ location /map_header {
+ proxy_pass http://127.0.0.1:8080/body;
+ proxy_set_header X-Header "header $capture $map_capture end";
+ }
+
location /body {
add_header X-Body $request_body;
+ add_header X-Header $http_x_header;
proxy_pass http://127.0.0.1:8080/empty;
}
@@ -78,4 +93,17 @@ EOF
like(http_get('/'), qr/X-Body: body/, 'proxy_set_body');
like(http_get('/p1'), qr/X-Body: body two/, 'proxy_set_body twice');
+TODO: {
+todo_skip 'might coredump', 2
+ unless $t->has_version('1.31.3')
+ or $ENV{TEST_NGINX_UNSAFE};
+local $TODO = 'not yet', $t->todo_alerts();
+
+like(http_get('/map'), qr!X-Body: body .* /map end!,
+ 'proxy_set_body and map with side effects');
+like(http_get('/map_header'), qr!X-Header: header .* /map_header end!,
+ 'proxy_set_header and map with side effects');
+
+}
+
###############################################################################
diff --git a/scgi.t b/scgi.t
--- a/scgi.t
+++ b/scgi.t
@@ -24,7 +24,7 @@ select STDOUT; $| = 1;
eval { require SCGI; };
plan(skip_all => 'SCGI not installed') if $@;
-my $t = Test::Nginx->new()->has(qw/http scgi/)->plan(10)
+my $t = Test::Nginx->new()->has(qw/http scgi rewrite map/)->plan(11)
->write_file_expand('nginx.conf', <<'EOF');
%%TEST_GLOBALS%%
@@ -41,6 +41,10 @@ http {
server 127.0.0.1:8081;
}
+ map $uri $map_capture {
+ ~(?<capture>.*) $capture;
+ }
+
server {
listen 127.0.0.1:8080;
server_name localhost;
@@ -58,6 +62,12 @@ http {
scgi_param REQUEST_URI $request_uri;
}
+ location /map/ {
+ scgi_pass 127.0.0.1:8081;
+ scgi_param SCGI 1;
+ scgi_param REQUEST_URI $request_uri;
+ scgi_param HTTP_FOO "foo $capture $map_capture end";
+ }
}
}
@@ -103,6 +113,17 @@ like($r, qr/X-Cookie: foo; bar; bazz/,
like($r, qr/X-Foo: foo, bar, bazz/,
'scgi with multiple unknown headers');
+TODO: {
+todo_skip 'might coredump', 1
+ unless $t->has_version('1.31.3')
+ or $ENV{TEST_NGINX_UNSAFE};
+local $TODO = 'not yet', $t->todo_alerts();
+
+like(http_get('/map/test-long-uri'), qr!foo .* /map/test-long-uri end!,
+ 'scgi params and map with side effects');
+
+}
+
###############################################################################
sub http_get_headers {
diff --git a/uwsgi.t b/uwsgi.t
--- a/uwsgi.t
+++ b/uwsgi.t
@@ -21,7 +21,8 @@ use Test::Nginx;
select STDERR; $| = 1;
select STDOUT; $| = 1;
-my $t = Test::Nginx->new()->has(qw/http uwsgi/)->has_daemon('uwsgi')->plan(8)
+my $t = Test::Nginx->new()
+ ->has(qw/http uwsgi rewrite map/)->has_daemon('uwsgi')->plan(9)
->write_file_expand('nginx.conf', <<'EOF');
%%TEST_GLOBALS%%
@@ -38,6 +39,10 @@ http {
server 127.0.0.1:8081;
}
+ map $uri $map_capture {
+ ~(?<capture>.*) $capture;
+ }
+
server {
listen 127.0.0.1:8080;
server_name localhost;
@@ -52,6 +57,12 @@ http {
uwsgi_pass $arg_b;
uwsgi_param SERVER_PROTOCOL $server_protocol;
}
+
+ location /map/ {
+ uwsgi_pass 127.0.0.1:8081;
+ uwsgi_param SERVER_PROTOCOL $server_protocol;
+ uwsgi_param HTTP_FOO "foo $capture $map_capture end";
+ }
}
}
@@ -124,6 +135,17 @@ like($r, qr/X-Cookie: foo; bar; bazz/,
like($r, qr/X-Foo: foo, bar, bazz/,
'uwsgi with multiple unknown headers');
+TODO: {
+todo_skip 'might coredump', 1
+ unless $t->has_version('1.31.3')
+ or $ENV{TEST_NGINX_UNSAFE};
+local $TODO = 'not yet', $t->todo_alerts();
+
+like(http_get('/map/test-long-uri'), qr!foo .* /map/test-long-uri end!,
+ 'uwsgi params and map with side effects');
+
+}
+
###############################################################################
sub http_get_headers {
More information about the nginx-devel
mailing list