]> git.kaiwu.me - nginx.git/commitdiff
Avoid undefined behaviour in ngx_pstrdup()
authorAndrew Clayton <a.clayton@nginx.com>
Thu, 19 Mar 2026 04:21:21 +0000 (04:21 +0000)
committerAndrew Clayton <a.clayton@nginx.com>
Mon, 20 Apr 2026 18:56:40 +0000 (19:56 +0100)
In the third call to ngx_pstrdup() for setting cycle->conf_param.data in
ngx_init_cycle() we would pass in a nulled ngx_str_t in the case there
was no -g command line option passed to nginx.

This would result in a

  memcpy(dst, NULL, 0)

which up to and including C23 is Undefined Behaviour.

Currently Clang and GCC (in this particular case) just treat this as a
no-op, so things just happen to work.

However some undefined behaviour sanitizers will throw an error when
this is hit, e.g. Clang and the zig compiler and it's probably best not
to rely on this behaviour.

It's worth noting that the next C standard will make this (and other
NULL related operations) defined behaviour.

Link: <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>
Closes: https://github.com/nginx/nginx/issues/1079
src/core/ngx_cycle.c

index e5fd40285311108eadb1d9ac4da07e71fe84272b..410cc3cd29cf6b444e59126493d576d38c2721f1 100644 (file)
@@ -114,11 +114,13 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
     ngx_cpystrn(cycle->conf_file.data, old_cycle->conf_file.data,
                 old_cycle->conf_file.len + 1);
 
-    cycle->conf_param.len = old_cycle->conf_param.len;
-    cycle->conf_param.data = ngx_pstrdup(pool, &old_cycle->conf_param);
-    if (cycle->conf_param.data == NULL) {
-        ngx_destroy_pool(pool);
-        return NULL;
+    if (old_cycle->conf_param.len) {
+        cycle->conf_param.len = old_cycle->conf_param.len;
+        cycle->conf_param.data = ngx_pstrdup(pool, &old_cycle->conf_param);
+        if (cycle->conf_param.data == NULL) {
+            ngx_destroy_pool(pool);
+            return NULL;
+        }
     }