From af0978ef6919fa7b74875067b490bc140118ab36 Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Wed, 5 Mar 2025 16:33:21 +0400 Subject: [PATCH 1/2] Core: error checks for localtime() and friends (fixes #169). Previously localtime(), localtime_r(), gmtime() and gmtime_r() were assumed to always be successful and return a valid pointer. In nginx code these functions are only called for current time() and should never fail, since the only documented error EOVERFLOW should not occur for it. However since these functions are a part of nginx API and are available to third-party modules, error handling is added to avoid potential segfaults in such modules. --- src/os/unix/ngx_time.c | 33 ++++++++++++++++++++++++++++++--- src/os/win32/ngx_time.c | 10 ++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/os/unix/ngx_time.c b/src/os/unix/ngx_time.c index cc760b2eb..270a80e17 100644 --- a/src/os/unix/ngx_time.c +++ b/src/os/unix/ngx_time.c @@ -46,6 +46,9 @@ ngx_timezone_update(void) s = time(0); t = localtime(&s); + if (t == NULL) { + return; + } strftime(buf, 4, "%H", t); @@ -57,12 +60,20 @@ void ngx_localtime(time_t s, ngx_tm_t *tm) { #if (NGX_HAVE_LOCALTIME_R) - (void) localtime_r(&s, tm); + if (localtime_r(&s, tm) == NULL) { + ngx_memzero(tm, sizeof(struct tm)); + return; + } #else ngx_tm_t *t; t = localtime(&s); + if (t == NULL) { + ngx_memzero(tm, sizeof(struct tm)); + return; + } + *tm = *t; #endif @@ -76,12 +87,20 @@ void ngx_libc_localtime(time_t s, struct tm *tm) { #if (NGX_HAVE_LOCALTIME_R) - (void) localtime_r(&s, tm); + if (localtime_r(&s, tm) == NULL) { + ngx_memzero(tm, sizeof(struct tm)); + return; + } #else struct tm *t; t = localtime(&s); + if (t == NULL) { + ngx_memzero(tm, sizeof(struct tm)); + return; + } + *tm = *t; #endif @@ -92,12 +111,20 @@ void ngx_libc_gmtime(time_t s, struct tm *tm) { #if (NGX_HAVE_LOCALTIME_R) - (void) gmtime_r(&s, tm); + if (gmtime_r(&s, tm) == NULL) { + ngx_memzero(tm, sizeof(struct tm)); + return; + } #else struct tm *t; t = gmtime(&s); + if (t == NULL) { + ngx_memzero(tm, sizeof(struct tm)); + return; + } + *tm = *t; #endif diff --git a/src/os/win32/ngx_time.c b/src/os/win32/ngx_time.c index 79149b2c7..d578d31d0 100644 --- a/src/os/win32/ngx_time.c +++ b/src/os/win32/ngx_time.c @@ -44,6 +44,11 @@ ngx_libc_localtime(time_t s, struct tm *tm) struct tm *t; t = localtime(&s); + if (t == NULL) { + ngx_memzero(tm, sizeof(struct tm)); + return; + } + *tm = *t; } @@ -54,6 +59,11 @@ ngx_libc_gmtime(time_t s, struct tm *tm) struct tm *t; t = gmtime(&s); + if (t == NULL) { + ngx_memzero(tm, sizeof(struct tm)); + return; + } + *tm = *t; } From b857b3415ff9a459cbdef69e5fc85b5ed560a481 Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Wed, 5 Mar 2025 17:08:36 +0400 Subject: [PATCH 2/2] Core: avoid potential underflow in ngx_gmtime(). The underflow may happen for small argument values. Normally the code is optimized by the compiler, which elimitaes the undeflow. Even if the underflow happens, the followup addition will also eliminate it. The change reorders operations to avoid the underflow in any case. Found by Coverity (CID 1605495). --- src/core/ngx_times.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ngx_times.c b/src/core/ngx_times.c index 16788c98c..d7ef77ef5 100644 --- a/src/core/ngx_times.c +++ b/src/core/ngx_times.c @@ -360,7 +360,7 @@ ngx_gmtime(time_t t, ngx_tm_t *tp) */ /* days since March 1, 1 BC */ - days = days - (31 + 28) + 719527; + days = days + 719527 - (31 + 28); /* * The "days" should be adjusted to 1 only, however, some March 1st's go