changeset 2624:e08b3ffa9536

Module: fixed heap-use-after-free while module loading. Making a copy of file argument because the engine may outlive current ngx_cycle. The bug became visible since 283282f (0.8.8).
author Dmitry Volyntsev <xeioex@nginx.com>
date Wed, 01 Oct 2025 20:07:14 -0700
parents 75221283a3e2
children 463485fdafa1
files nginx/ngx_js.c nginx/t/js_import2.t
diffstat 2 files changed, 21 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/nginx/ngx_js.c	Wed Oct 01 20:23:08 2025 -0700
+++ b/nginx/ngx_js.c	Wed Oct 01 20:07:14 2025 -0700
@@ -557,11 +557,17 @@
     vm_options.backtrace = 1;
     vm_options.addons = opts->u.njs.addons;
     vm_options.metas = opts->u.njs.metas;
-    vm_options.file = opts->file;
     vm_options.argv = ngx_argv;
     vm_options.argc = ngx_argc;
     vm_options.init = 1;
 
+    vm_options.file.start = njs_mp_alloc(engine->pool, opts->file.length);
+    if (vm_options.file.start == NULL) {
+        return NGX_ERROR;
+    }
+
+    ngx_memcpy(vm_options.file.start, opts->file.start, opts->file.length);
+
     vm = njs_vm_create(&vm_options);
     if (vm == NULL) {
         return NGX_ERROR;
@@ -579,7 +585,7 @@
 
     engine->u.njs.vm = vm;
 
-    return NJS_OK;
+    return NGX_OK;
 }
 
 
--- a/nginx/t/js_import2.t	Wed Oct 01 20:23:08 2025 -0700
+++ b/nginx/t/js_import2.t	Wed Oct 01 20:07:14 2025 -0700
@@ -64,6 +64,11 @@
             js_content fun;
         }
 
+        location /test_exception {
+            js_import exception.js;
+            js_content exception.nonexistent;
+        }
+
         location /test_var {
             return 200 $test;
         }
@@ -105,6 +110,11 @@
 
 EOF
 
+$t->write_file('exception.js', <<EOF);
+    export default {nonexistent};
+
+EOF
+
 $t->write_file('main.js', <<EOF);
     function version(r) {
         r.return(200, njs.version);
@@ -127,11 +137,13 @@
 like(http_get('/test_fun'), qr/FUN-TEST/s, 'fun');
 like(http_get('/proxy/test_fun'), qr/FUN-TEST/s, 'proxy fun');
 like(http_get('/test_var'), qr/P-TEST/s, 'foo.bar.p');
+http_get('/test_exception');
+http_get('/test_exception');
 
 $t->stop();
 
 my $content = $t->read_file('error.log');
 my $count = () = $content =~ m/js vm init/g;
-ok($count == 4, 'uniq js vm contexts');
+ok($count == 5, 'uniq js vm contexts');
 
 ###############################################################################