[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