[njs] Ignoring UndefinedBehaviorSanitizer warnings where appropriate.

2024-01-08 Thread Dmitry Volyntsev
details:   https://hg.nginx.org/njs/rev/0490f1ae4cf5
branches:  
changeset: 2258:0490f1ae4cf5
user:  Dmitry Volyntsev 
date:  Sun Jul 30 10:21:51 2023 +0100
description:
Ignoring UndefinedBehaviorSanitizer warnings where appropriate.

Prodded by David Carlier and Ben Kallus.

diffstat:

 auto/clang|  11 +++
 src/njs_clang.h   |  25 +
 src/njs_number.c  |   4 +++-
 src/njs_number.h  |   2 +-
 src/njs_typed_array.c |   2 +-
 5 files changed, 41 insertions(+), 3 deletions(-)

diffs (94 lines):

diff -r 275d785ab5bf -r 0490f1ae4cf5 auto/clang
--- a/auto/clangMon Jan 08 16:40:42 2024 -0800
+++ b/auto/clangSun Jul 30 10:21:51 2023 +0100
@@ -161,6 +161,17 @@ njs_feature_test="int main(int argc, cha
 . auto/feature
 
 
+njs_feature="GCC __attribute__ no_sanitize"
+njs_feature_name=NJS_HAVE_GCC_ATTRIBUTE_NO_SANITIZE
+njs_feature_run=no
+njs_feature_path=
+njs_feature_libs=
+njs_feature_test="__attribute__((no_sanitize(\"undefined\"))) int main(void) {
+return 0;
+  }"
+. auto/feature
+
+
 njs_feature="Address sanitizer"
 njs_feature_name=NJS_HAVE_ADDRESS_SANITIZER
 njs_feature_run=no
diff -r 275d785ab5bf -r 0490f1ae4cf5 src/njs_clang.h
--- a/src/njs_clang.h   Mon Jan 08 16:40:42 2024 -0800
+++ b/src/njs_clang.h   Sun Jul 30 10:21:51 2023 +0100
@@ -183,6 +183,31 @@ njs_leading_zeros64(uint64_t x)
 #define njs_msan_unpoison(ptr, size)
 #endif
 
+#if (NJS_HAVE_GCC_ATTRIBUTE_NO_SANITIZE)
+#define NJS_NOSANITIZE(options) __attribute__((no_sanitize(options)))
+#else
+#define NJS_NOSANITIZE(options)
+#endif
+
+
+njs_inline NJS_NOSANITIZE("float-cast-overflow") int64_t
+njs_unsafe_cast_double_to_int64(double num)
+{
+   /*
+* Casting NaN to integer is undefined behavior,
+* but it is fine in some cases where we do additional checks later.
+* For example:
+*  int64_t i64 = njs_unsafe_cast_double_to_int64(num);
+*  if (i64 == num) {
+*// num is integer
+*  }
+*
+* We do this as inline function to avoid UndefinedBehaviorSanitizer
+* warnings.
+*/
+   return (int64_t) num;
+}
+
 
 #if (NJS_HAVE_DENORMALS_CONTROL)
 #include 
diff -r 275d785ab5bf -r 0490f1ae4cf5 src/njs_number.c
--- a/src/njs_number.c  Mon Jan 08 16:40:42 2024 -0800
+++ b/src/njs_number.c  Sun Jul 30 10:21:51 2023 +0100
@@ -382,7 +382,9 @@ njs_number_is_safe_integer(njs_vm_t *vm,
 if (nargs > 1 && njs_is_number(&args[1])) {
 num = njs_number(&args[1]);
 
-if (num == (int64_t) num && fabs(num) <= NJS_MAX_SAFE_INTEGER) {
+if (num == njs_unsafe_cast_double_to_int64(num)
+&& fabs(num) <= NJS_MAX_SAFE_INTEGER)
+{
 integer = 1;
 }
 }
diff -r 275d785ab5bf -r 0490f1ae4cf5 src/njs_number.h
--- a/src/njs_number.h  Mon Jan 08 16:40:42 2024 -0800
+++ b/src/njs_number.h  Sun Jul 30 10:21:51 2023 +0100
@@ -36,7 +36,7 @@ njs_int_t njs_number_parse_float(njs_vm_
 njs_uint_t nargs, njs_index_t unused, njs_value_t *retval);
 
 
-njs_inline njs_bool_t
+njs_inline NJS_NOSANITIZE("float-cast-overflow") njs_bool_t
 njs_number_is_integer_index(double num)
 {
 uint32_t  u32;
diff -r 275d785ab5bf -r 0490f1ae4cf5 src/njs_typed_array.c
--- a/src/njs_typed_array.c Mon Jan 08 16:40:42 2024 -0800
+++ b/src/njs_typed_array.c Sun Jul 30 10:21:51 2023 +0100
@@ -1388,7 +1388,7 @@ njs_typed_array_prototype_index_of(njs_v
 
 v = njs_number(njs_argument(args, 1));
 
-i64 = v;
+i64 = njs_unsafe_cast_double_to_int64(v);
 integer = (v == i64);
 
 buffer = array->buffer;
___
nginx-devel mailing list
nginx-devel@nginx.org
https://mailman.nginx.org/mailman/listinfo/nginx-devel


Re: [PATCH 4 of 4] AIO operations now add timers (ticket #2162)

2024-01-08 Thread Maxim Dounin
Hello!

On Mon, Jan 08, 2024 at 01:31:11PM +, J Carter wrote:

> On Mon, 8 Jan 2024 11:25:55 +
> J Carter  wrote:
> 
> > Hello,
> > 
> > On Mon, 27 Nov 2023 05:50:27 +0300
> > Maxim Dounin  wrote:
> > 
> > > # HG changeset patch
> > > # User Maxim Dounin 
> > > # Date 1701050170 -10800
> > > #  Mon Nov 27 04:56:10 2023 +0300
> > > # Node ID 00c3e7333145ddb5ea0eeaaa66b3d9c26973c9c2
> > > # Parent  61d08e4cf97cc073200ec32fc6ada9a2d48ffe51
> > > AIO operations now add timers (ticket #2162).
> > > 
> > > Each AIO (thread IO) operation being run is now accompanied with 1-minute
> > > timer.  This timer prevents unexpected shutdown of the worker process 
> > > while
> > > an AIO operation is running, and logs an alert if the operation is running
> > > for too long.  
> > 
> > Shouldn't this timer's duration be set to match worker_shutdown_timeout's
> > duration rather than being hard coded to 60s ?
> 
> Ah nevermind, I understand.
> 
> These timers will either expire from passing the 60s set duration, or 
> will expire as worker_process_timeout itself expires, kills the 
> connection and times out associated timers (including the aio timers). 
> 
> Setting it to worker_shutdown_timeout's duration would be pointless 
> (an 'infinite' timer would give the same result).
> 
> So the only situation in which a different value for these AIO 
> timers would make sense is if these AIO operations are expected to
> take longer 60s, but less than worker_shutdown_timeout (in cases 
> where it has been increased from it's own default of 60s).
> 
> In that case the AIO operation's timeout would have to be one 
> (or more) of it's own directives, with a value less than 
> worker_shutdown_timeout. 

Not really.

When worker_shutdown_timeout expires, it tries to terminate the 
request, but it can't as long as an AIO operation is running.  
When the AIO operation completes, the request will be actually 
terminated and the worker process will be allowed to exit.  So far 
so good.

But if the AIO operation never completes, the timer will expire 
after 1 minute, will log an alert, and the worker processes will 
be anyway allowed to exit (with the request still present).  This 
might not be actually possible though - for example, 
ngx_thread_pool_exit_worker() will just block waiting for all 
pending operations to complete.

In theory, the situation when an AIO operation never completes 
should never happen, and just a counter of pending AIO 
operations can be used instead to delay shutdown (which is 
essentially equivalent to an infinite timer).  

In practice, though, using a large enough guard timer might be 
better: it provides additional level of protection against bugs or 
system misbehaviour, and at least logs an alert if something 
really weird happens.  It is also looks more universal and in line 
with current approach of using existing timers as an indicator 
that something is going on and shutdown should be delayed.

The timer is expected to be "large enough", since we cannot do 
anything meaningful with an AIO operation which never completes, 
we can only complain loudly, so the timer should never expire 
unless there is something really wrong.  This is not the case with 
worker_shutdown_timeout: it can be set to an arbitrary low value, 
which is not expected to mean that something is really wrong if 
the timer expires, but rather means that nginx shouldn't try to 
process remaining requests, but should instead close them as long 
as it can do so.  That is, worker_shutdown_timeout does not fit 
semantically.  Further, worker_shutdown_timeout is not set by 
default, so it simply cannot be used.

The 1 minute was chosen as it matches default send_timeout, which 
typically accompanies AIO operations when sending responses (and 
also delays shutdown, so no "open socket left" alerts are normally 
seen).  Still, send_timeout is also quite different semantically, 
and therefore a hardcoded value is used instead.

I don't think there are valid cases when AIO operations can take 
longer than 1 minute, as these are considered to be small and fast 
operations, which are normally done synchronously within nginx 
event loop when not using AIO, and an operations which takes 1m 
would mean nginx is completely unresponsive.  Still, if we'll 
found out that 1 minute is not large enough in some cases, 
we can just bump it to a larger value.

[...]

-- 
Maxim Dounin
http://mdounin.ru/
___
nginx-devel mailing list
nginx-devel@nginx.org
https://mailman.nginx.org/mailman/listinfo/nginx-devel


Re: [PATCH] SSL: raised limit for upstream session size

2024-01-08 Thread Maxim Dounin
Hello!

On Tue, Dec 26, 2023 at 12:29:54AM +0400, Sergey Kandaurov wrote:

> > On 23 Dec 2023, at 01:46, Maxim Dounin  wrote:
> > 
> > Hello!
> > 
> > On Fri, Dec 22, 2023 at 06:28:34PM +0400, Sergey Kandaurov wrote:
> > 
> >> # HG changeset patch
> >> # User Sergey Kandaurov 
> >> # Date 1703255284 -14400
> >> #  Fri Dec 22 18:28:04 2023 +0400
> >> # Node ID a463fb67e143c051fd373d1df94e5813a37d5cea
> >> # Parent  44266e0651c44f530c4aa66e68c1b9464a9acee7
> >> SSL: raised limit for upstream session size.
> >> 
> >> Unlike shared session cache used to store multiple client SSL sessions and
> >> which may be per a single SSL connection, sessions saved from upstream are
> >> per upstream server peer, so there is no such multiplier effect, but they
> >> may be of noticeably larger size due to session tickets being used.
> >> 
> >> It was observed that session tickets sent from JVM backends may result in
> >> a decoded session size nearly the previous maximum session size limit of
> >> 4096 or slightly beyond.  Raising the limit allows to save such sessions.
> > 
> > Session tickets are not expected to be larger than sessions 
> > itself, except by several bytes used for key identification and 
> > encryption overhead.  I see no reasons why the limit should be 
> > different in different places.
> > 
> > And 4096 for an SSL session looks a lot.  The only justification I 
> > can assume here is an SSL session with the client certificate (or 
> > even certificate chain) being saved into the session.  It might 
> > worth looking into what actually happens here.
> > 
> 
> Indeed.  Both local and peer certificate chains are serialized and
> encrypted as part of constructing a session ticket.  Per the original
> change to support tickets, this is hardcoded and may not be adjusted:
> https://hg.openjdk.org/jdk/jdk/rev/c2398053ee90#l4.352
> https://hg.openjdk.org/jdk/jdk/rev/c2398053ee90#l10.261

From my limited understanding of the JDK code, at least peerCerts 
seems to contain only certificates actually sent by the client, 
which is understandable (links to Github, since hg.openjdk.org 
used to be unresponsive when writing this, and returned 504 for 
almost all requests):

https://github.com/openjdk/jdk/blob/4fc6b0ffa4f771991a5ebd982b5133d2e364fdae/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java#L416

But localCerts seems to be always set on the server side, with all 
the certificates being sent to the client:

https://github.com/openjdk/jdk/blob/4fc6b0ffa4f771991a5ebd982b5133d2e364fdae/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java#L265
 

This looks like an issue on the JDK side: there are no reasons why 
server certificates needs to be saved into the session on the 
server, as they are readily available on the server.  Further, 
relevant saving code seems to be commented as "Client identity", 
which suggests that these might be saved unintentionally with an 
assumption that the code is only used on the client (OTOH, I don't 
see why the client needs its own certificates in the session as 
well).

Do you have an affected JVM backend on hand to confirm it's indeed 
the case?

I tend to think this needs to be reported to JDK developers.  
Their current code results in sending server certificate chain to 
the client at least two times (once in the handshake itself, and 
at least once in the ticket; not to mention that there can be more 
than one ticket in TLSv1.3), and they might reconsider doing this.

(Funny enough, they seems to be using cache to deserialize 
certificates from such tickets, see 
https://bugs.openjdk.org/browse/JDK-8286433 for details.)

Meanwhile, we can consider implementing a workaround on our side 
(that is, raising the limit, though I don't think there should be 
separate limits; also, I'm somewhat concerned about using 8k 
buffers on stack, we currently don't use anything larger than 4k) 
or instead focus on providing some guidance to users of affected 
JVM backends (I guess switching off tickets and/or TLSv1.3 should 
be enough in most cases).

-- 
Maxim Dounin
http://mdounin.ru/
___
nginx-devel mailing list
nginx-devel@nginx.org
https://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Fixed RegExp.prototype.exec() when second argument is absent.

2024-01-08 Thread Dmitry Volyntsev
details:   https://hg.nginx.org/njs/rev/275d785ab5bf
branches:  
changeset: 2257:275d785ab5bf
user:  Dmitry Volyntsev 
date:  Mon Jan 08 16:40:42 2024 -0800
description:
Fixed RegExp.prototype.exec() when second argument is absent.

Previously, when the second argument is undefined, NaN is casted to
unsigned which is undefined behavior.

Found by UndefinedBehaviorSanitizer.

diffstat:

 src/njs_regexp.c |  11 +--
 1 files changed, 9 insertions(+), 2 deletions(-)

diffs (28 lines):

diff -r 41d0de3ad198 -r 275d785ab5bf src/njs_regexp.c
--- a/src/njs_regexp.c  Mon Jan 08 16:40:42 2024 -0800
+++ b/src/njs_regexp.c  Mon Jan 08 16:40:42 2024 -0800
@@ -1235,6 +1235,7 @@ njs_int_t
 njs_regexp_prototype_exec(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
 njs_index_t unused, njs_value_t *retval)
 {
+unsigned flags;
 njs_int_tret;
 njs_value_t  *r, *s;
 njs_value_t  string_lvalue;
@@ -1253,8 +1254,14 @@ njs_regexp_prototype_exec(njs_vm_t *vm, 
 return ret;
 }
 
-return njs_regexp_builtin_exec(vm, r, s,
-   njs_number(njs_arg(args, nargs, 2)), 
retval);
+if (nargs > 2) {
+flags = njs_number(njs_arg(args, nargs, 2));
+
+} else {
+flags = 0;
+}
+
+return njs_regexp_builtin_exec(vm, r, s, flags, retval);
 }
 
 
___
nginx-devel mailing list
nginx-devel@nginx.org
https://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Fixed initialization of external prototypes with object entry.

2024-01-08 Thread Dmitry Volyntsev
details:   https://hg.nginx.org/njs/rev/ee4d396aa418
branches:  
changeset: 2255:ee4d396aa418
user:  Dmitry Volyntsev 
date:  Mon Jan 08 16:40:42 2024 -0800
description:
Fixed initialization of external prototypes with object entry.

When external was NULL (for example, when .u.object.properties is not
declared), an arithmetic operation was performed with NULL pointer which
is undefined behavior.

Found by UndefinedBehaviorSanitizer.

diffstat:

 src/njs_extern.c |  4 
 1 files changed, 4 insertions(+), 0 deletions(-)

diffs (14 lines):

diff -r c43745da92cd -r ee4d396aa418 src/njs_extern.c
--- a/src/njs_extern.c  Mon Jan 08 16:40:42 2024 -0800
+++ b/src/njs_extern.c  Mon Jan 08 16:40:42 2024 -0800
@@ -34,6 +34,10 @@ njs_external_add(njs_vm_t *vm, njs_arr_t
 hash = &slot->external_shared_hash;
 njs_lvlhsh_init(hash);
 
+if (n == 0) {
+return NJS_OK;
+}
+
 lhq.replace = 0;
 lhq.proto = &njs_object_hash_proto;
 lhq.pool = vm->mem_pool;
___
nginx-devel mailing list
nginx-devel@nginx.org
https://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Improved array enumeration with length 0.

2024-01-08 Thread Dmitry Volyntsev
details:   https://hg.nginx.org/njs/rev/41d0de3ad198
branches:  
changeset: 2256:41d0de3ad198
user:  Dmitry Volyntsev 
date:  Mon Jan 08 16:40:42 2024 -0800
description:
Improved array enumeration with length 0.

The fix eliminates an arithmetic operation with NULL pointer.

Found by UndefinedBehaviorSanitizer.

diffstat:

 src/njs_object.c |  2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diffs (12 lines):

diff -r ee4d396aa418 -r 41d0de3ad198 src/njs_object.c
--- a/src/njs_object.c  Mon Jan 08 16:40:42 2024 -0800
+++ b/src/njs_object.c  Mon Jan 08 16:40:42 2024 -0800
@@ -591,7 +591,7 @@ njs_object_enumerate_array(njs_vm_t *vm,
 njs_value_t  *p, *start, *end;
 njs_array_t  *entry;
 
-if (!array->object.fast_array) {
+if (!array->object.fast_array || array->length == 0) {
 return NJS_OK;
 }
 
___
nginx-devel mailing list
nginx-devel@nginx.org
https://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] QueryString: fixed underflow in parse().

2024-01-08 Thread Dmitry Volyntsev
details:   https://hg.nginx.org/njs/rev/c43745da92cd
branches:  
changeset: 2254:c43745da92cd
user:  Dmitry Volyntsev 
date:  Mon Jan 08 16:40:42 2024 -0800
description:
QueryString: fixed underflow in parse().

Previously, njs_query_string_append() might be provided with invalid
val_size value when value in a key-value pair was absent.

Found by UndefinedBehaviorSanitizer.

diffstat:

 external/njs_query_string_module.c |  2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diffs (12 lines):

diff -r 9fadb2e9c6ea -r c43745da92cd external/njs_query_string_module.c
--- a/external/njs_query_string_module.cMon Jan 08 16:40:42 2024 -0800
+++ b/external/njs_query_string_module.cMon Jan 08 16:40:42 2024 -0800
@@ -506,7 +506,7 @@ njs_query_string_parser(njs_vm_t *vm, u_
 
 size = val - key;
 
-if (val != end) {
+if (val != part) {
 val += eq->length;
 }
 
___
nginx-devel mailing list
nginx-devel@nginx.org
https://mailman.nginx.org/mailman/listinfo/nginx-devel


[njs] Fixed external values initialization in unit tests.

2024-01-08 Thread Dmitry Volyntsev
details:   https://hg.nginx.org/njs/rev/9fadb2e9c6ea
branches:  
changeset: 2253:9fadb2e9c6ea
user:  Dmitry Volyntsev 
date:  Mon Jan 08 16:40:42 2024 -0800
description:
Fixed external values initialization in unit tests.

Since 0.8.0 modules can create their own constructors and prototypes.
A modules has two method: preinit() and init(). A module should
add its constructors and prototypes in preinit() and create its own
values in init(). Creating a value in preinit() results in an error.
The patch fixes the issue by creating an external value in init()
instead of preinit().

Found by UndefinedBehaviorSanitizer.

diffstat:

 src/test/njs_externals_test.c |  136 ++---
 1 files changed, 72 insertions(+), 64 deletions(-)

diffs (176 lines):

diff -r 721475693b80 -r 9fadb2e9c6ea src/test/njs_externals_test.c
--- a/src/test/njs_externals_test.c Mon Jan 08 16:40:42 2024 -0800
+++ b/src/test/njs_externals_test.c Mon Jan 08 16:40:42 2024 -0800
@@ -28,6 +28,7 @@ typedef struct {
 
 static njs_int_t njs_externals_262_init(njs_vm_t *vm);
 static njs_int_t njs_externals_shared_preinit(njs_vm_t *vm);
+static njs_int_t njs_externals_shared_init(njs_vm_t *vm);
 njs_int_t njs_array_buffer_detach(njs_vm_t *vm, njs_value_t *args,
 njs_uint_t nargs, njs_index_t unused, njs_value_t *retval);
 
@@ -47,7 +48,7 @@ njs_module_t  njs_unit_test_262_module =
 njs_module_t  njs_unit_test_external_module = {
 .name = njs_str("external"),
 .preinit = njs_externals_shared_preinit,
-.init = NULL,
+.init = njs_externals_shared_init,
 };
 
 
@@ -1253,77 +1254,15 @@ njs_externals_init_internal(njs_vm_t *vm
 {
 njs_int_t ret;
 njs_uint_ti, j;
-njs_function_t*f;
-njs_opaque_value_tvalue;
 njs_unit_test_req_t   *requests;
 njs_unit_test_prop_t  *prop;
 
-static const njs_str_t  external_ctor = njs_str("ExternalConstructor");
-static const njs_str_t  external_null = njs_str("ExternalNull");
-static const njs_str_t  external_error = njs_str("ExternalError");
-
-if (shared) {
-njs_external_r_proto_id = njs_vm_external_prototype(vm,
- njs_unit_test_r_external,
- njs_nitems(njs_unit_test_r_external));
-if (njs_slow_path(njs_external_r_proto_id < 0)) {
-njs_printf("njs_vm_external_prototype() failed\n");
-return NJS_ERROR;
-}
-
-f = njs_vm_function_alloc(vm, njs_unit_test_constructor, 1, 1);
-if (f == NULL) {
-njs_printf("njs_vm_function_alloc() failed\n");
-return NJS_ERROR;
-}
-
-njs_value_function_set(njs_value_arg(&value), f);
-
-ret = njs_vm_bind(vm, &external_ctor, njs_value_arg(&value), 1);
-if (njs_slow_path(ret != NJS_OK)) {
-njs_printf("njs_vm_bind() failed\n");
-return NJS_ERROR;
-}
-
-njs_external_null_proto_id = njs_vm_external_prototype(vm,
-   njs_unit_test_null_external,
-   
njs_nitems(njs_unit_test_null_external));
-if (njs_slow_path(njs_external_null_proto_id < 0)) {
-njs_printf("njs_vm_external_prototype() failed\n");
-return NJS_ERROR;
-}
-
-ret = njs_vm_external_create(vm, njs_value_arg(&value),
- njs_external_null_proto_id, NULL, 1);
-if (njs_slow_path(ret != NJS_OK)) {
-return NJS_ERROR;
-}
-
-ret = njs_vm_bind(vm, &external_null, njs_value_arg(&value), 1);
-if (njs_slow_path(ret != NJS_OK)) {
-njs_printf("njs_vm_bind() failed\n");
-return NJS_ERROR;
-}
-
-njs_external_error_ctor_id =
-njs_vm_external_constructor(vm, &external_error,
-  njs_error_constructor, njs_unit_test_ctor_props,
-  njs_nitems(njs_unit_test_ctor_props),
-  njs_unit_test_proto_props,
-  njs_nitems(njs_unit_test_proto_props));
-if (njs_slow_path(njs_external_error_ctor_id < 0)) {
-njs_printf("njs_vm_external_constructor() failed\n");
-return NJS_ERROR;
-}
-}
-
 requests = njs_mp_zalloc(vm->mem_pool, n * sizeof(njs_unit_test_req_t));
 if (njs_slow_path(requests == NULL)) {
 return NJS_ERROR;
 }
 
 for (i = 0; i < n; i++) {
-
 requests[i] = init[i].request;
 
 ret = njs_vm_external_create(vm, njs_value_arg(&requests[i].value),
@@ -1396,7 +1335,76 @@ njs_externals_262_init(njs_vm_t *vm)
 static njs_int_t
 njs_externals_shared_preinit(njs_vm_t *vm)
 {
-return njs_externals_init_internal(vm, njs_test_requests, 1, 1);
+static const njs_str_t  external_error = njs_str("ExternalError");
+
+njs_external_r_proto_id = njs_vm_external_p

[njs] Unifying hash function prototypes.

2024-01-08 Thread Dmitry Volyntsev
details:   https://hg.nginx.org/njs/rev/721475693b80
branches:  
changeset: 2252:721475693b80
user:  Dmitry Volyntsev 
date:  Mon Jan 08 16:40:42 2024 -0800
description:
Unifying hash function prototypes.

This fixes UndefinedBehaviorSanitizer warning "call to function through
pointer to incorrect function type".

Found by UndefinedBehaviorSanitizer.

diffstat:

 external/njs_crypto_module.c |  71 +--
 src/njs_hash.h   |  32 +++
 src/njs_main.h   |   4 +-
 src/njs_md5.c|  10 +++---
 src/njs_md5.h|  23 --
 src/njs_sha1.c   |  10 +++---
 src/njs_sha1.h   |  24 --
 src/njs_sha2.c   |  10 +++---
 src/njs_sha2.h   |  24 --
 9 files changed, 77 insertions(+), 131 deletions(-)

diffs (424 lines):

diff -r 57071ecadeb5 -r 721475693b80 external/njs_crypto_module.c
--- a/external/njs_crypto_module.c  Mon Jan 08 16:40:27 2024 -0800
+++ b/external/njs_crypto_module.c  Mon Jan 08 16:40:42 2024 -0800
@@ -6,16 +6,14 @@
 
 
 #include 
-#include 
-#include 
-#include 
+#include 
 #include 
 #include 
 
 
-typedef void (*njs_hash_init)(void *ctx);
-typedef void (*njs_hash_update)(void *ctx, const void *data, size_t size);
-typedef void (*njs_hash_final)(u_char *result, void *ctx);
+typedef void (*njs_hash_init)(njs_hash_t *ctx);
+typedef void (*njs_hash_update)(njs_hash_t *ctx, const void *data, size_t 
size);
+typedef void (*njs_hash_final)(u_char result[32], njs_hash_t *ctx);
 
 typedef njs_int_t (*njs_digest_encode)(njs_vm_t *vm, njs_value_t *value,
 const njs_str_t *src);
@@ -31,24 +29,13 @@ typedef struct {
 } njs_hash_alg_t;
 
 typedef struct {
-union {
-njs_md5_t   md5;
-njs_sha1_t  sha1;
-njs_sha2_t  sha2;
-} u;
-
+njs_hash_t  ctx;
 njs_hash_alg_t  *alg;
 } njs_digest_t;
 
 typedef struct {
 u_char  opad[64];
-
-union {
-njs_md5_t   md5;
-njs_sha1_t  sha1;
-njs_sha2_t  sha2;
-} u;
-
+njs_hash_t  ctx;
 njs_hash_alg_t  *alg;
 } njs_hmac_t;
 
@@ -85,25 +72,25 @@ static njs_hash_alg_t njs_hash_algorithm
{
  njs_str("md5"),
  16,
- (njs_hash_init) njs_md5_init,
- (njs_hash_update) njs_md5_update,
- (njs_hash_final) njs_md5_final
+ njs_md5_init,
+ njs_md5_update,
+ njs_md5_final
},
 
{
  njs_str("sha1"),
  20,
- (njs_hash_init) njs_sha1_init,
- (njs_hash_update) njs_sha1_update,
- (njs_hash_final) njs_sha1_final
+ njs_sha1_init,
+ njs_sha1_update,
+ njs_sha1_final
},
 
{
  njs_str("sha256"),
  32,
- (njs_hash_init) njs_sha2_init,
- (njs_hash_update) njs_sha2_update,
- (njs_hash_final) njs_sha2_final
+ njs_sha2_init,
+ njs_sha2_update,
+ njs_sha2_final
},
 
{
@@ -312,7 +299,7 @@ njs_crypto_create_hash(njs_vm_t *vm, njs
 
 dgst->alg = alg;
 
-alg->init(&dgst->u);
+alg->init(&dgst->ctx);
 
 return njs_vm_external_create(vm, retval, njs_crypto_hash_proto_id,
   dgst, 0);
@@ -390,10 +377,10 @@ njs_hash_prototype_update(njs_vm_t *vm, 
 }
 
 if (!hmac) {
-dgst->alg->update(&dgst->u, data.start, data.length);
+dgst->alg->update(&dgst->ctx, data.start, data.length);
 
 } else {
-ctx->alg->update(&ctx->u, data.start, data.length);
+ctx->alg->update(&ctx->ctx, data.start, data.length);
 }
 
 njs_value_assign(retval, this);
@@ -450,17 +437,17 @@ njs_hash_prototype_digest(njs_vm_t *vm, 
 
 if (!hmac) {
 alg = dgst->alg;
-alg->final(digest, &dgst->u);
+alg->final(digest, &dgst->ctx);
 dgst->alg = NULL;
 
 } else {
 alg = ctx->alg;
-alg->final(hash1, &ctx->u);
+alg->final(hash1, &ctx->ctx);
 
-alg->init(&ctx->u);
-alg->update(&ctx->u, ctx->opad, 64);
-alg->update(&ctx->u, hash1, alg->size);
-alg->final(digest, &ctx->u);
+alg->init(&ctx->ctx);
+alg->update(&ctx->ctx, ctx->opad, 64);
+alg->update(&ctx->ctx, hash1, alg->size);
+alg->final(digest, &ctx->ctx);
 ctx->alg = NULL;
 }
 
@@ -562,9 +549,9 @@ njs_crypto_create_hmac(njs_vm_t *vm, njs
 ctx->alg = alg;
 
 if (key.length > sizeof(key_buf)) {
-alg->init(&ctx->u);
-alg->update(&ctx->u, key.start, key.length);
-alg->final(digest, &ctx->u);
+alg->init(&ctx->ctx);
+alg->update(&ctx->ctx, key.start, key.length);
+alg->final(digest, &ctx->ctx);
 
 memcpy(key_buf, digest, alg->size);
 njs_explicit_memzero(key_buf + alg->size, sizeof(key_buf) - alg->size);
@@ -583,8 +570,8 @@ njs_crypto_create_hmac(njs_vm_t *vm, njs
  key_buf[i] ^= 0x36;
 }
 
-alg->init(&ctx->u);
-alg->update(&ctx->u, key_buf, 

[njs] Fixed Date constructor for overflows and with NaN values.

2024-01-08 Thread Dmitry Volyntsev
details:   https://hg.nginx.org/njs/rev/57071ecadeb5
branches:  
changeset: 2251:57071ecadeb5
user:  Dmitry Volyntsev 
date:  Mon Jan 08 16:40:27 2024 -0800
description:
Fixed Date constructor for overflows and with NaN values.

Found by UndefinedBehaviorSanitizer.

diffstat:

 src/njs_date.c |  8 
 1 files changed, 8 insertions(+), 0 deletions(-)

diffs (23 lines):

diff -r 4a15613f4e8b -r 57071ecadeb5 src/njs_date.c
--- a/src/njs_date.cTue Dec 19 12:37:05 2023 -0800
+++ b/src/njs_date.cMon Jan 08 16:40:27 2024 -0800
@@ -243,11 +243,19 @@ njs_make_date(int64_t tm[], njs_bool_t l
 days = njs_make_day(tm[NJS_DATE_YR], tm[NJS_DATE_MON],
 tm[NJS_DATE_DAY]);
 
+if (njs_slow_path(isnan(days))) {
+return NAN;
+}
+
 time = ((tm[NJS_DATE_HR] * 60.0 + tm[NJS_DATE_MIN]) * 60.0
 + tm[NJS_DATE_SEC]) * 1000.0 + tm[NJS_DATE_MSEC];
 
 time += days * 8640.0;
 
+if (time < -8.64e15 || time > 8.64e15) {
+return NAN;
+}
+
 if (local) {
 time += njs_tz_offset(time) * 6;
 }
___
nginx-devel mailing list
nginx-devel@nginx.org
https://mailman.nginx.org/mailman/listinfo/nginx-devel


Re: [PATCH 1 of 6] Stream: using ngx_stream_ssl_srv_conf_t *sscf naming convention

2024-01-08 Thread Roman Arutyunyan
Hi,

On Fri, Dec 15, 2023 at 07:37:44PM +0400, Sergey Kandaurov wrote:
> # HG changeset patch
> # User Sergey Kandaurov 
> # Date 1702646778 -14400
> #  Fri Dec 15 17:26:18 2023 +0400
> # Node ID cb377d36446e1ce22b71848a4a138564b2e38719
> # Parent  763803589a36e3c67cbe39dd324b4e91fe57ecb7
> Stream: using ngx_stream_ssl_srv_conf_t *sscf naming convention.
> 
> Originally, the stream module was developed based on the mail module,
> following the existing style.  Then it was diverged to closely follow
> the http module development.  This change updates style to use sscf
> naming convention troughout the stream module, which matches the http
> module code style.  No functional changes.
> 
> diff --git a/src/stream/ngx_stream_ssl_module.c 
> b/src/stream/ngx_stream_ssl_module.c
> --- a/src/stream/ngx_stream_ssl_module.c
> +++ b/src/stream/ngx_stream_ssl_module.c
> @@ -40,12 +40,12 @@ static ngx_int_t ngx_stream_ssl_variable
>  ngx_stream_variable_value_t *v, uintptr_t data);
>  
>  static ngx_int_t ngx_stream_ssl_add_variables(ngx_conf_t *cf);
> -static void *ngx_stream_ssl_create_conf(ngx_conf_t *cf);
> -static char *ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent,
> +static void *ngx_stream_ssl_create_srv_conf(ngx_conf_t *cf);
> +static char *ngx_stream_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent,
>  void *child);
>  
>  static ngx_int_t ngx_stream_ssl_compile_certificates(ngx_conf_t *cf,
> -ngx_stream_ssl_conf_t *conf);
> +ngx_stream_ssl_srv_conf_t *conf);
>  
>  static char *ngx_stream_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
>  void *conf);
> @@ -90,21 +90,21 @@ static ngx_command_t  ngx_stream_ssl_com
>NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
>ngx_conf_set_msec_slot,
>NGX_STREAM_SRV_CONF_OFFSET,
> -  offsetof(ngx_stream_ssl_conf_t, handshake_timeout),
> +  offsetof(ngx_stream_ssl_srv_conf_t, handshake_timeout),
>NULL },
>  
>  { ngx_string("ssl_certificate"),
>NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
>ngx_conf_set_str_array_slot,
>NGX_STREAM_SRV_CONF_OFFSET,
> -  offsetof(ngx_stream_ssl_conf_t, certificates),
> +  offsetof(ngx_stream_ssl_srv_conf_t, certificates),
>NULL },
>  
>  { ngx_string("ssl_certificate_key"),
>NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
>ngx_conf_set_str_array_slot,
>NGX_STREAM_SRV_CONF_OFFSET,
> -  offsetof(ngx_stream_ssl_conf_t, certificate_keys),
> +  offsetof(ngx_stream_ssl_srv_conf_t, certificate_keys),
>NULL },
>  
>  { ngx_string("ssl_password_file"),
> @@ -118,63 +118,63 @@ static ngx_command_t  ngx_stream_ssl_com
>NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
>ngx_conf_set_str_slot,
>NGX_STREAM_SRV_CONF_OFFSET,
> -  offsetof(ngx_stream_ssl_conf_t, dhparam),
> +  offsetof(ngx_stream_ssl_srv_conf_t, dhparam),
>NULL },
>  
>  { ngx_string("ssl_ecdh_curve"),
>NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
>ngx_conf_set_str_slot,
>NGX_STREAM_SRV_CONF_OFFSET,
> -  offsetof(ngx_stream_ssl_conf_t, ecdh_curve),
> +  offsetof(ngx_stream_ssl_srv_conf_t, ecdh_curve),
>NULL },
>  
>  { ngx_string("ssl_protocols"),
>NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
>ngx_conf_set_bitmask_slot,
>NGX_STREAM_SRV_CONF_OFFSET,
> -  offsetof(ngx_stream_ssl_conf_t, protocols),
> +  offsetof(ngx_stream_ssl_srv_conf_t, protocols),
>&ngx_stream_ssl_protocols },
>  
>  { ngx_string("ssl_ciphers"),
>NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
>ngx_conf_set_str_slot,
>NGX_STREAM_SRV_CONF_OFFSET,
> -  offsetof(ngx_stream_ssl_conf_t, ciphers),
> +  offsetof(ngx_stream_ssl_srv_conf_t, ciphers),
>NULL },
>  
>  { ngx_string("ssl_verify_client"),
>NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
>ngx_conf_set_enum_slot,
>NGX_STREAM_SRV_CONF_OFFSET,
> -  offsetof(ngx_stream_ssl_conf_t, verify),
> +  offsetof(ngx_stream_ssl_srv_conf_t, verify),
>&ngx_stream_ssl_verify },
>  
>  { ngx_string("ssl_verify_depth"),
>NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
>ngx_conf_set_num_slot,
>NGX_STREAM_SRV_CONF_OFFSET,
> -  offsetof(ngx_stream_ssl_conf_t, verify_depth),
> +  offsetof(ngx_stream_ssl_srv_conf_t, verify_depth),
>NULL },
>  
>  { ngx_string("ssl_client_certificate"),
>NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
>ngx_conf_set_str_slot,
>NGX_STREAM_SRV_CONF_OFFSET,
> -  offsetof(ngx_stream_ssl_conf_t, client_certificate),
> +  offsetof(ngx_stream_ssl_srv_conf_t, client_certificate),
>NULL },
>  
>  { ngx_string("ssl_trusted_certificate"),
>NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
>   

Re: [PATCH 4 of 4] AIO operations now add timers (ticket #2162)

2024-01-08 Thread J Carter
On Mon, 8 Jan 2024 11:25:55 +
J Carter  wrote:

> Hello,
> 
> On Mon, 27 Nov 2023 05:50:27 +0300
> Maxim Dounin  wrote:
> 
> > # HG changeset patch
> > # User Maxim Dounin 
> > # Date 1701050170 -10800
> > #  Mon Nov 27 04:56:10 2023 +0300
> > # Node ID 00c3e7333145ddb5ea0eeaaa66b3d9c26973c9c2
> > # Parent  61d08e4cf97cc073200ec32fc6ada9a2d48ffe51
> > AIO operations now add timers (ticket #2162).
> > 
> > Each AIO (thread IO) operation being run is now accompanied with 1-minute
> > timer.  This timer prevents unexpected shutdown of the worker process while
> > an AIO operation is running, and logs an alert if the operation is running
> > for too long.  
> 
> Shouldn't this timer's duration be set to match worker_shutdown_timeout's
> duration rather than being hard coded to 60s ?

Ah nevermind, I understand.

These timers will either expire from passing the 60s set duration, or 
will expire as worker_process_timeout itself expires, kills the 
connection and times out associated timers (including the aio timers). 

Setting it to worker_shutdown_timeout's duration would be pointless 
(an 'infinite' timer would give the same result).

So the only situation in which a different value for these AIO 
timers would make sense is if these AIO operations are expected to
take longer 60s, but less than worker_shutdown_timeout (in cases 
where it has been increased from it's own default of 60s).

In that case the AIO operation's timeout would have to be one 
(or more) of it's own directives, with a value less than 
worker_shutdown_timeout. 

(doesn't seem like it's worth it from the ticket discussion,
sorry for the noise).


> > This fixes "open socket left" alerts during worker processes shutdown
> > due to pending AIO (or thread IO) operations while corresponding requests
> > have no timers.  In particular, such errors were observed while reading
> > cache headers (ticket #2162), and with worker_shutdown_timeout.  
> 
> [...]
___
nginx-devel mailing list
nginx-devel@nginx.org
https://mailman.nginx.org/mailman/listinfo/nginx-devel


Re: [PATCH 4 of 4] AIO operations now add timers (ticket #2162)

2024-01-08 Thread J Carter
Hello,

On Mon, 27 Nov 2023 05:50:27 +0300
Maxim Dounin  wrote:

> # HG changeset patch
> # User Maxim Dounin 
> # Date 1701050170 -10800
> #  Mon Nov 27 04:56:10 2023 +0300
> # Node ID 00c3e7333145ddb5ea0eeaaa66b3d9c26973c9c2
> # Parent  61d08e4cf97cc073200ec32fc6ada9a2d48ffe51
> AIO operations now add timers (ticket #2162).
> 
> Each AIO (thread IO) operation being run is now accompanied with 1-minute
> timer.  This timer prevents unexpected shutdown of the worker process while
> an AIO operation is running, and logs an alert if the operation is running
> for too long.

Shouldn't this timer's duration be set to match worker_shutdown_timeout's
duration rather than being hard coded to 60s ?

> This fixes "open socket left" alerts during worker processes shutdown
> due to pending AIO (or thread IO) operations while corresponding requests
> have no timers.  In particular, such errors were observed while reading
> cache headers (ticket #2162), and with worker_shutdown_timeout.

[...]
___
nginx-devel mailing list
nginx-devel@nginx.org
https://mailman.nginx.org/mailman/listinfo/nginx-devel