From ff263588a2660c6403075e0bccd8d0f166a9875f Mon Sep 17 00:00:00 2001 From: Gabriel Clima Date: Fri, 10 Jul 2026 09:06:45 +0000 Subject: [PATCH] timer: pad Data so the ngx_event_ident debug read stays in bounds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nginx debug logging evaluates ngx_event_ident(ev->data) on every timer expiry, reading ((ngx_connection_t *) data)->fd — 4 bytes at offset 24. Timer sets ev->data to a Box> that can be as small as 8 bytes (24 observed), so the read lands past the allocation: benign garbage in a debug line on plain builds, fatal heap-buffer-overflow under AddressSanitizer (worker abort on first expiry on any node with 'error_log memory:32m debug' and a --with-debug binary). Pad Data to keep offset 24..28 readable. --- nginx_module/src/timer.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nginx_module/src/timer.rs b/nginx_module/src/timer.rs index 423db39..caaa6c2 100644 --- a/nginx_module/src/timer.rs +++ b/nginx_module/src/timer.rs @@ -34,6 +34,10 @@ impl Drop for Timer { struct Data { handler: HandlerFn, interval_msec: usize, + // nginx debug logging reads ngx_event_ident(ev->data), i.e. + // ((ngx_connection_t *) data)->fd — 4 bytes at offset 24; keep the + // allocation large enough for that read to stay in bounds + _ident_pad: [u8; 32], } impl Timer { @@ -44,6 +48,7 @@ impl Timer { let data = Data { handler, interval_msec, + _ident_pad: [0; 32], }; event.data = Box::into_raw(Box::new(data)).cast(); event.log = unsafe { (*ngx_cycle).log };