summaryrefslogtreecommitdiffhomepage
path: root/src (follow)
AgeCommit message (Collapse)AuthorFilesLines
2025-09-03php: Fix building with 8.5Andy Postnikov1-0/+6
Closes: https://github.com/nginx/unit/issues/1646 Link: <https://github.com/php/php-src/commit/f4e2e91d4b6d28448104500819b68edf58bd263c> Signed-off-by: Andy Postnikov <apostnikov@gmail.com>
2025-09-02otel: Bump the tracing-subscriber crate from 0.3.19 to 0.3.20dependabot[bot]1-2/+2
Bumps <https://github.com/tokio-rs/tracing> from 0.3.19 to 0.3.20. Link: Release notes <https://github.com/tokio-rs/tracing/releases> Link: Commits <https://github.com/tokio-rs/tracing/compare/tracing-subscriber-0.3.19...tracing-subscriber-0.3.20> Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-08-25http: compression: brotli: Don't leak memory on errorAndrew Clayton1-3/+8
Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-08-25http: compression: Don't set buf->parentAndrew Clayton1-1/+0
When doing some testing I was noticing when using brotli & zstd compression on application responses we were regularly (but not always) getting segfaults with "corrupted double-linked list" being logged from malloc(3) when we were freeing memory via nxt_mp_destroy() when doing nxt_router_http_request_release(). E.g. #5 0x00007f6eeb4f11f5 in malloc_printerr ( str=str@entry=0x7f6eeb625178 "corrupted double-linked list") at malloc.c:5829 #6 0x00007f6eeb4f1d0c in unlink_chunk (p=<optimized out>, av=0x7f6edc000030) at malloc.c:1619 #7 0x00007f6eeb4f1f78 in _int_free_create_chunk (av=av@entry=0x7f6edc000030, p=p@entry=0x7f6edc008ea0, size=size@entry=4192, nextchunk=<optimized out>, nextsize=75520) at malloc.c:4763 #8 0x00007f6eeb4f352e in _int_free_merge_chunk (av=av@entry=0x7f6edc000030, p=0x7f6edc008ea0, size=4192) at malloc.c:4742 #9 0x00007f6eeb4f36e4 in _int_free_chunk (av=0x7f6edc000030, p=<optimized out>, size=<optimized out>, have_lock=<optimized out>, have_lock@entry=0) at malloc.c:4667 #10 0x00007f6eeb4f6512 in _int_free (av=<optimized out>, p=<optimized out>, have_lock=0) at malloc.c:4699 #11 __GI___libc_free (mem=<optimized out>) at malloc.c:3476 #12 0x000000000040d66a in nxt_mp_destroy (mp=0x7f6edc003790) at src/nxt_mp.c:342 #13 0x000000000040d5a4 in nxt_mp_release (mp=0x7f6edc003790) at src/nxt_mp.c:303 #14 0x000000000042f9de in nxt_router_http_request_release (task=0x24cb8c10, obj=0x7f6edc003990, data=0x0) at src/nxt_router.c:5799 Interestingly gzip compression never seemed to trigger this... Also when doing brotli compression for example, I could prevent this from happening by simply commenting out BrotliEncoderDestroyInstance(brotli); in src/nxt_brotli.c::nxt_brotli_compress() Running under libasan showed the following ==281177==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7b94031e90f0 at pc 0x000000422b37 bp 0x7b640027c820 sp 0x7b640027c818 READ of size 4 at 0x7b94031e90f0 thread T2 #0 0x000000422b36 in nxt_buf_parent_completion src/nxt_buf.c:229 #1 0x000000422d5e in nxt_buf_ts_completion src/nxt_buf.c:294 #2 0x000000428fa0 in nxt_event_engine_start src/nxt_event_engine.c:542 #3 0x0000004423de in nxt_router_thread_start src/nxt_router.c:3727 #4 0x00000042497b in nxt_thread_trampoline src/nxt_thread.c:126 #5 0x7f6404828ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f) #6 0x7f640446f153 in start_thread (/lib64/libc.so.6+0x71153) (BuildId: 126a08bf502f4950b215dc773e52df8dcf50c393) #7 0x7f64044f1cab in __clone3 (/lib64/libc.so.6+0xf3cab) (BuildId: 126a08bf502f4950b215dc773e52df8dcf50c393) 0x7b94031e90f0 is located 8 bytes after 24-byte region [0x7b94031e90d0,0x7b94031e90e8) allocated by thread T2 here: #0 0x7f64048e6f2b in malloc (/lib64/libasan.so.8+0xe6f2b) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f) #1 0x000000401b10 in nxt_malloc src/nxt_malloc.c:35 #2 0x000000401bd8 in nxt_zalloc src/nxt_malloc.c:54 #3 0x000000410035 in nxt_port_incoming_port_mmap src/nxt_port_memory.c:247 #4 0x0000004162fa in nxt_port_mmap_handler src/nxt_port.c:366 #5 0x000000415000 in nxt_port_handler src/nxt_port.c:184 #6 0x00000040a761 in nxt_port_read_msg_process src/nxt_port_socket.c:1271 #7 0x00000040d596 in nxt_port_queue_read_handler src/nxt_port_socket.c:997 #8 0x000000428fa0 in nxt_event_engine_start src/nxt_event_engine.c:542 #9 0x0000004423de in nxt_router_thread_start src/nxt_router.c:3727 #10 0x00000042497b in nxt_thread_trampoline src/nxt_thread.c:126 #11 0x7f6404828ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f) Thread T2 created by T0 here: #0 0x7f64048de492 in pthread_create (/lib64/libasan.so.8+0xde492) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f) #1 0x00000042468b in nxt_thread_create src/nxt_thread.c:85 #2 0x00000044b799 in nxt_router_thread_create src/nxt_router.c:3575 #3 0x00000044b799 in nxt_router_threads_create src/nxt_router.c:3543 #4 0x00000044b799 in nxt_router_conf_apply src/nxt_router.c:1271 #5 0x000000428fa0 in nxt_event_engine_start src/nxt_event_engine.c:542 #6 0x00000040140d in main src/nxt_main.c:35 #7 0x7f6404401574 in __libc_start_call_main (/lib64/libc.so.6+0x3574) (BuildId: 126a08bf502f4950b215dc773e52df8dcf50c393) #8 0x7f6404401627 in __libc_start_main_alias_1 (/lib64/libc.so.6+0x3627) (BuildId: 126a08bf502f4950b215dc773e52df8dcf50c393) #9 0x000000401264 in _start (/opt/unit/sbin/unitd+0x401264) (BuildId: c05bd11884a7315b24ec2abf762c4f283def6fea) SUMMARY: AddressSanitizer: heap-buffer-overflow src/nxt_buf.c:229 in nxt_buf_parent_completion Shadow bytes around the buggy address: 0x7b94031e8e00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x7b94031e8e80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x7b94031e8f00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x7b94031e8f80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x7b94031e9000: fa fa fa fa fa fa fa fa fa fa fa fa fa fa 00 00 =>0x7b94031e9080: 00 fa fa fa 00 00 00 05 fa fa 00 00 00 fa[fa]fa 0x7b94031e9100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x7b94031e9180: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x7b94031e9200: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x7b94031e9280: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x7b94031e9300: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==281177==ABORTING "SUMMARY: AddressSanitizer: heap-buffer-overflow src/nxt_buf.c:229 in nxt_buf_parent_completion" Gave some clue. It seems that setting buf->parent on the last buffer triggers this. If we don't set it on the last buffer, everything works fine and no heap-overflow detected. Everything seems to also work fine if we simply don't set it all. So lets do that. Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-08-20Don't leak file descriptor in nxt_main_port_access_log_handler()Andrew Clayton1-0/+3
After opening a file and setting file.fd we _may_ call nxt_port_socket_write(). If so then the file is eventually closed via something like nxt_port_socket_write() nxt_port_socket_write2() nxt_port_write_handler() nxt_port_msg_close_fd() nxt_port_close_fds() Alternatively we may just return from the function and never close(2) file.fd. In which case we should call nxt_file_close(). This was reported by coverity. Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-08-20http: compression: Add a missed nxt_http_comp_compress() return checkAndrew Clayton1-0/+6
In nxt_http_comp_compress_static_response() we should check the return value of the call to nxt_http_comp_compress() in case of error. Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-08-20http: compression: Set the temporary file name in n_h_c_c_s_r()Andrew Clayton3-13/+13
When creating a new nxt_file_t structure in nxt_http_comp_compress_static_response() for the temporary compressed file be sure to set the *name* member. We don't generally need it, but I failed to notice that when calling nxt_file_close() if the close(2) fails then we log an error message containing the file name, which at best would have just printed junk. So set the file name for this particular error case... This issue was reported by coverity. Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-08-15rust, wasm-wc, otel: Bump the slab crate from 0.4.10 to 0.4.11dependabot[bot]2-4/+4
Bumps <https://github.com/tokio-rs/slab> from 0.4.10 to 0.4.11. Fix Slab::get_disjoint_mut out of bounds. (This combines two dependabots into one) Link: Release notes <https://github.com/tokio-rs/slab/releases> Link: Changelog <https://github.com/tokio-rs/slab/blob/master/CHANGELOG.md> Link: Commits <https://github.com/tokio-rs/slab/compare/v0.4.10...v0.4.11> Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-07-25wasm-wc: Update to wasmtime 35.0.0Andrew Clayton3-305/+287
This is mainly just to be on the latest version for the next release of Unit. This required some changes to the language module as described here <https://github.com/bytecodealliance/wasmtime/pull/10016>. We also add unnecessary_transmutes to the list of allowed linters to quell warnings like warning: unnecessary transmute --> /home/andrew/src/unit/src/wasm-wasi-component/target/debug/build/wasm-wasi-component-9ae3c2c94201e6be/out/bindings.rs:440:13 | 440 | ... ::std::mem::transmute(self._bitfield_1.get(0usize, 24u8) as u32) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this with: `u32::cast_signed(self._bitfield_1.get(0usize, 24u8) as u32)` | = note: `#[warn(unnecessary_transmutes)]` on by default Also, because this is new in rustc 1.88, to avoid warnings on older compilers the simplest thing is to just add unknown_lints to the list. Link: <https://lists.gnu.org/archive/html/qemu-rust/2025-07/msg00006.html> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-07-25wasm-wc: Update cratesAndrew Clayton1-259/+336
Run 'cargo update' to get the latest version of the required crates in preparation for the 1.35.0 release. Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-07-25otel: Update cratesAndrew Clayton1-285/+297
Run 'cargo update' to get the latest version of the required crates in preparation for the 1.35.0 release. Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-07-25Set SERVER_PORT appropriatelyAndrew Clayton6-35/+16
The Perl, PHP, Python, Ruby & Java language modules all hard code SERVER_PORT to "80". Adjust them to bring them in line with the wasm language module which uses r->local_port (I.e. the port unit accepted the connection on). Closes: https://github.com/nginx/unit/issues/761 Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-05-28node.js: Fixed issue with duplicate headers in responseskokalin1-3/+3
It fixes losing context in response in cases when there are 2 or more headers with the same name. The prev implementation used to use foreach function which uses local lexical environment and did not find this.headers_len locally, which causes crash of the http server module. It was replaced with a for loop in order to make access for this.headers_len variable and improve performance of calculation. Closes: https://github.com/nginx/unit/issues/1621 Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-05-28Use NULL instead of 0 as null pointer constantAndrew Clayton7-19/+19
GCC 15 enabled "-Wzero-as-null-pointer-constant" for C, which checks for places where '0' has been used as a null pointer constant. This showed a few places in Unit where we were using '0' instead of the more correct NULL macro. E.g. $ make -j4 EXTRA_CFLAGS=-Wzero-as-null-pointer-constant ... src/nxt_buf.c: In function ‘nxt_buf_mmap_alloc’: src/nxt_buf.h:192:21: error: zero as null pointer constant [-Werror=zero-as-null-pointer-constant] 192 | (bm)->start = 0; \ | ^ src/nxt_buf.c:135:9: note: in expansion of macro ‘nxt_buf_mem_set_size’ 135 | nxt_buf_mem_set_size(&b->mem, size); | ^~~~~~~~~~~~~~~~~~~~ Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-05-08njs: Update for version 0.9.0 API changesAndrew Clayton1-20/+29
This bumps the minimum required version of njs to 0.9.0 Cc: Sergey A. Osokin <sergey.osokin@nginx.com> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-04-28Treat a “broken pipe” on SSL_shutdown() as a normal closeAndy Postnikov1-1/+2
Starting with OpenSSL 3.4 errno is flowed up from tls_retry_write_records() which upon EPIPE results in the following log message 2025/04/23 17:12:47 [alert] 14322#14324 *16 SSL_shutdown(25) failed (32: Broken pipe) (32: [null]) (OpenSSL: error:80000020:system library::Broken pipe:tls_retry_write_records failure) Which is harmless except it trips up the test/test_tls.py::test_tls_certificate_change test due it to looking for "alert" log messages and failing if any are found. Now, I think the tests are wrong to do this (they also don't seem to be closing the TLS connection properly). But getting EPIPE when we're shutting down the connection is likely harmless so treat it the same as a clean shutdown which also gets rid of this log message. Link: <https://github.com/openssl/openssl/commit/933f57dfe21657f7aba8f13e0cdb3b02dd64fcc3.patch> Closes: https://github.com/nginx/unit/issues/1600 [ Commit message - Andrew ] Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-04-21http: Compress application responsesAndrew Clayton3-1/+102
This adds initial support for compressing application responses. A couple of things to note 1) Compressed responses are sent 'chunked' as we don't know beforehand how large the compressed response will be. 2) We only compress responses where we know the Content-Length as we need to check with the 'min_length' config parameter. It's also currently how we track when we need to close the compression stream off. Co-authored-by: Alejandro Colomar <alx@kernel.org> Signed-off-by: Alejandro Colomar <alx@kernel.org> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-04-14http: Compress static responsesAndrew Clayton3-0/+133
Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-04-14http: compress: Add a couple of helper functionsAndrew Clayton1-0/+29
This adds two helper functions that will be used in subsequent commits. nxt_http_comp_compress() does the actual compression. nxt_http_comp_bound() returns the maximum compressed size for the given size. Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-04-14http: Wire up HTTP compression support to the config systemAndrew Clayton2-0/+103
This exposes a new "settings.http.compression" configuration object. Under which are types & compressors objects. types is used to specify what MIME types should be considered compressible. compressors is used to configure an array of compressors that are available. For each of these, you specify the encoding, e.g gzip and optional level and min_length parameters. Where level is what compression level to use and min_length is the minimum length of data that should be compressed. By default the default compression level for the specified compressor is used and there is no minimum data length considered for compression. It may look something like "settings": { "http": { "server_version": true, "static": { "mime_types": { "text/x-c": [ ".c", ".h" ] } }, "compression": { "types": [ "text/*" ], "compressors": [ { "encoding": "gzip", "level": 3, "min_length": 2048 }, { "encoding": "deflate", "min_length": 1024 }, { "encoding": "zstd", "min_length": 2048 }, { "encoding": "br", "min_length": 256 } ] } } }, Currently this is a global option that will effect both static and application responses. In future it should be possible to add per-application (and perhaps even per-static) configuration. Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-04-14http: Add support for brotli compressionAndrew Clayton3-0/+106
Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-04-14http: Add support for zstd compressionAndrew Clayton3-0/+97
Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-04-14http: Add zlib compression supportAndrew Clayton3-0/+128
This adds support for both deflate & gzip compressors. Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-04-14http: Add core http compression codeAndrew Clayton2-0/+543
This is the initial step to enabling HTTP compression on both static and application responses. This code itself doesn't do any actual compression, that will come in subsequent commits. It just contains the core functions for initialising structures that describe the available compressors and functions for checking if compression should be done depending on various criteria. Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-04-14http: Add NXT_HTTP_NOT_ACCEPTABLE enum valueAndrew Clayton1-0/+1
This will be used by the compression code to signal no requested compression method is available and the client said to not use identity. Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-04-14http: Add a mime_type member to nxt_http_response_tAndrew Clayton1-0/+1
This is to store the MIME type of the response which will be used by the HTTP compression patches as part of determining whether or not to compress the response. Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-04-11Fully initialise the oob struct in nxt_socket_msg_oob_init()Andrew Clayton1-0/+2
valgrind(1) was producing the following alert ==166470== Syscall param sendmsg(msg.msg_control) points to uninitialised byte(s) ==166470== at 0x4AE6514: sendmsg (sendmsg.c:28) ==166470== by 0x42D86C: nxt_sendmsg (nxt_socket_msg.c:32) ==166470== by 0x4FE6695: nxt_unit_sendmsg (nxt_unit.c:6013) ==166470== by 0x4FEB6E2: nxt_unit_ready (nxt_unit.c:963) ==166470== by 0x4FEB6E2: nxt_unit_init (nxt_unit.c:557) ==166470== by 0x4FEEC56: nxt_php_start (nxt_php_sapi.c:507) ==166470== by 0x426BA0: nxt_app_setup (nxt_application.c:1029) ==166470== by 0x403153: nxt_process_do_start (nxt_process.c:718) ==166470== by 0x4042A3: nxt_process_whoami_ok (nxt_process.c:846) ==166470== by 0x407A28: nxt_port_rpc_handler (nxt_port_rpc.c:347) ==166470== by 0x407E42: nxt_port_handler (nxt_port.c:184) ==166470== by 0x40501B: nxt_port_read_msg_process (nxt_port_socket.c:1271) ==166470== by 0x4055B3: nxt_port_read_handler (nxt_port_socket.c:778) ==166470== Address 0x1ffefffc9c is on thread 1's stack ==166470== in frame #3, created by nxt_unit_init (nxt_unit.c:428) ==166470== Uninitialised value was created by a stack allocation ==166470== at 0x4FEABFE: nxt_unit_init (nxt_unit.c:436) This was due to the nxt_send_oob_t oob structure not being fully initialised. Given the name and intention of this function lets *fully* empty-initialise this structure. Link: <https://en.cppreference.com/w/c/language/initialization#Empty_initialization> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-04-11Fully initialise nxt_port_msg_t msg structuresAndrew Clayton1-10/+2
valgrind(1) was producing the following alerts ==166470== Syscall param sendmsg(msg.msg_iov[0]) points to uninitialised byte(s) ==166470== at 0x4AE6514: sendmsg (sendmsg.c:28) ==166470== by 0x42D86C: nxt_sendmsg (nxt_socket_msg.c:32) ==166470== by 0x4FE6695: nxt_unit_sendmsg (nxt_unit.c:6013) ==166470== by 0x4FEB6E2: nxt_unit_ready (nxt_unit.c:963) ==166470== by 0x4FEB6E2: nxt_unit_init (nxt_unit.c:557) ==166470== by 0x4FEEC56: nxt_php_start (nxt_php_sapi.c:507) ==166470== by 0x426BA0: nxt_app_setup (nxt_application.c:1029) ==166470== by 0x403153: nxt_process_do_start (nxt_process.c:718) ==166470== by 0x4042A3: nxt_process_whoami_ok (nxt_process.c:846) ==166470== by 0x407A28: nxt_port_rpc_handler (nxt_port_rpc.c:347) ==166470== by 0x407E42: nxt_port_handler (nxt_port.c:184) ==166470== by 0x40501B: nxt_port_read_msg_process (nxt_port_socket.c:1271) ==166470== by 0x4055B3: nxt_port_read_handler (nxt_port_socket.c:778) ==166470== Address 0x1ffefffc7f is on thread 1's stack ==166470== in frame #3, created by nxt_unit_init (nxt_unit.c:428) ==166470== Uninitialised value was created by a stack allocation ==166470== at 0x4FEABFE: nxt_unit_init (nxt_unit.c:436) ==166690== Syscall param sendmsg(msg.msg_iov[0]) points to uninitialised byte(s) ==166690== at 0x4AE6514: sendmsg (sendmsg.c:28) ==166690== by 0x42D871: nxt_sendmsg (nxt_socket_msg.c:32) ==166690== by 0x4FE6695: nxt_unit_sendmsg (nxt_unit.c:6009) ==166690== by 0x4FE69C8: nxt_unit_port_send (nxt_unit.c:5939) ==166690== by 0x4FE8C77: nxt_unit_request_done (nxt_unit.c:3309) ==166690== by 0x4FEE13B: nxt_php_execute (nxt_php_sapi.c:1257) ==166690== by 0x4FEE2F1: nxt_php_dynamic_request (nxt_php_sapi.c:1128) ==166690== by 0x4FEE79E: nxt_php_request_handler (nxt_php_sapi.c:1023) ==166690== by 0x4FE92AD: nxt_unit_process_ready_req (nxt_unit.c:4846) ==166690== by 0x4FED1B4: nxt_unit_run_once_impl (nxt_unit.c:4605) ==166690== by 0x4FED3AE: nxt_unit_run (nxt_unit.c:4548) ==166690== by 0x4FEEC2A: nxt_php_start (nxt_php_sapi.c:514) ==166690== Address 0x1ffeffea5f is on thread 1's stack ==166690== in frame #3, created by nxt_unit_port_send (nxt_unit.c:5907) ==166690== Uninitialised value was created by a stack allocation ==166690== at 0x4FE8C05: nxt_unit_request_done (nxt_unit.c:3255) These were due to the nxt_port_msg_t msg struct in nxt_unit_ready() and nxt_unit_request_done() not being fully initialised. Whether or not this is an actual problem an obviously correct thing to do is to fully empty-initialise the structure and then we don't need to explicitly set any members to 0 afterwards providing a nice cleanup as well. Link: <https://en.cppreference.com/w/c/language/initialization#Empty_initialization> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-04-08rust: Update rust cratesAndrew Clayton2-426/+663
Update (cargo update) the rust crates for wasm-wasi-component, otel & unitctl. This will fix build issues with wasm-wasi-component & rustc 1.86+. It will also fix dependabot issues in otel and unitctl. Link: <https://github.com/bytecodealliance/wasmtime/issues/10184> Link: <https://github.com/nginx/unit/pull/1585> Link: <https://github.com/nginx/unit/pull/1589> Link: <https://github.com/nginx/unit/pull/1570> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-03-20Tag various character arrays with NXT_NONSTRINGAndrew Clayton4-6/+6
In Unit we have a number of character arrays which are intentionally not NUL terminated. With GCC 15 this static const char hex[16] = "0123456789ABCDEF"; will trigger a warning like $ gcc -Wextra -c nonstring.c nonstring.c: In function ‘hexit’: nonstring.c:9:37: warning: initializer-string for array of ‘char’ truncates NUL terminator but destination lacks ‘nonstring’ attribute (17 chars into 16 available) [-Wunterminated-string-initialization] 9 | static const char hex[16] = "0123456789ABCDEF"; | ^~~~~~~~~~~~~~~~~~ By adding NXT_NONSTRING like static const char hex[16] NXT_NONSTRING = "0123456789ABCDEF"; we no longer get the warning. Cc: Alejandro Colomar <alx@kernel.org> Co-authored-by: Alejandro Colomar <alx@kernel.org> Signed-off-by: Alejandro Colomar <alx@kernel.org> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-03-19auto/clang: Add a NXT_NONSTRING macroAndrew Clayton1-0/+11
This is a wrapper around __attribute__ ((__nonstring__)). Traditionally this was used to mark char array variables that intentionally lacked a terminating NUL byte, this would then cause warning to either be quelled or emitted for various memory/string functions. GCC 15 introduced a new warning, Wunterminated-string-initialization, which will always warn on things like static const char hex[16] = "0123456789ABCDEF"; However this is very much intentionally not NUL terminated. When the Wunterminated-string-initialization patch went in, the "nonstriong" attribute didn't quell this warning, however a patch has since gone in (prior to the GCC 15 release) to enable this attribute to quell this warning. In Unit we disabled this new warning with an eye to being able to re-enable it again, this patch is the first in a series to do just that. So the above example would become static const char hex[16] NXT_NONSTRING = "0123456789ABCDEF"; Link: <https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=44c9403ed1833ae71a59e84f9e37af3182be0df5> Link: <https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=622968990beee7499e951590258363545b4a3b57> Link: <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117178#c21> Cc: Alejandro Colomar <alx@kernel.org> Reviewed-by: Alejandro Colomar <alx@kernel.org> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-02-21java: websocket: Additional payload length validationMark Thomas1-0/+7
<https://bz.apache.org/bugzilla/show_bug.cgi?id=64563> Patch taken from <https://github.com/apache/tomcat/commit/1c1c77b0efb667cea80b532440b44cea1dc427c3.patch> [ Subject / message tweak - Andrew ] Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-02-21java: websocket: Fix calculation of payload length for > 32bit valuesMark Thomas1-1/+1
Patch taken from <https://github.com/apache/tomcat/commit/1cddae8da4ecb4ac04575d3b5fba2daa2e0c8ead.patch> [ Subject / message tweak - Andrew ] Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-02-21python: Add Django 5.x compatibilityAndrew Clayton1-5/+5
Note: This may not be *specific* to Django 5.x but is where the issue showed up. @codedoga on GitHub reported an issue with Unit and Django 5.x When trying to perform a simple POST/PUT request with body data, Unit was throwing the following error 2025/02/16 11:07:14 [error] 6#6 [unit] #9: Python failed to call 'future.result()' Traceback (most recent call last): File "/usr/local/lib/python3.13/site-packages/django/core/handlers/asgi.py", line 162, in __call__ await self.handle(scope, receive, send) File "/usr/local/lib/python3.13/site-packages/django/core/handlers/asgi.py", line 208, in handle task.result() ~~~~~~~~~~~^^ File "/usr/local/lib/python3.13/site-packages/django/core/handlers/asgi.py", line 239, in listen_for_disconnect assert False, "Invalid ASGI message after request body: %s" % message["type"] ^^^^^ AssertionError: Invalid ASGI message after request body: http.request There is no such issue with Django 4.x The issue was caused when Django started doing an 'async receive()' just after we have handled the initial request and passed it to the application. Django is then looking to see if/when we send it a 'http.disconnect' message. We were not prepared for this and would go through all the motions of handling the request again which would result in the erroneous 'http.request' message. What we need to do is track when we've handled the initial request. We can then use that information coupled with the fact if we get a request with 0 content length then we basically have nothing to do. For this we create a new nxt_py_asgi_http_t member, request_received. We can repurpose 'empty_body_received' for this if we rename it and change where we set it as now if 'request_received' is true then so would 'empty_body_received'. 'empty_body_received' was actually part of a previous commit that was addressing various receive() issues. I've checked that the provided reproducer application still works. Link: <https://github.com/django/django/commit/1d1ddffc27cd55c011298cd09bfa4de3fa73cf7a> Link: <https://github.com/nginx/unit/issues/564> Fixes: 567545213 ("Python: fixing ASGI receive() issues.") Closes: https://github.com/nginx/unit/issues/1561 Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-02-10http: Fix WebSockets with FirefoxAndrew Clayton1-9/+8
Firefox (going back a couple of years at least) was unable to open a WebSocket connection to Unit due to it sending a Connection header of Connection: keep-alive, Upgrade However in Unit we were expecting only a single value in the header. Fix the 'Connection' parsing in nxt_h1p_connection() to address this. Closes: https://github.com/nginx/unit/issues/772 Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-02-04otel, tools/unitctl: bump the openssl crate from 0.10.68 to 0.10.70dependabot[bot]1-4/+4
Bumps <https://github.com/sfackler/rust-openssl> from 0.10.68 to 0.10.70. Signed-off-by: dependabot[bot] <support@github.com> Link: Release notes <https://github.com/sfackler/rust-openssl/releases> Link: Commits <https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.68...openssl-v0.10.70> [ Tweaked commit message/subject - Andrew ] Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-02-03python: Fix Litestar WebSockets compatibilityAndrew Clayton1-8/+10
It was reported on GitHub that Unit was unable to work with WebSockets under Litestar Python applications. This was due to Unit sending a 'method' variable in the WebSocket's connection scope, which Litestar was interpreting as being a normal HTTP connection. The ASGI WebSocket specification makes no mention about setting a 'method', so let's not send it on WebSockets. Also tested this change with basic ASGI WebSockets and FastAPI WebSockets and obviously pytests still pass. Closes: https://github.com/nginx/unit/issues/1507 Link: <https://asgi.readthedocs.io/en/latest/specs/www.html#websocket-connection-scope> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-01-22ruby: Fix build failures with Ruby 3.4Andrew Clayton1-5/+23
Ruby 3.4 started to actually mark some deprecated functions as *deprecated* now resulting in compiler warnings (which due to -Werror we treat as errors and thus the build fails). The *new* functions were actually introduced back in Ruby 1.9.2, so have been around for quite some time. We claim support for Ruby 2.0 onwards so this is more than fine. The new API replaces the old 'mark' and 'free' parameters with a struct that allows for more fine tuning/configuration. We never made use of either of those parameters and so the only members of this struct we *need* to set is the structure wrapper name and the dsize function pointer which is passed a pointer to the underlying wrapped structure to calculate its memory usage. While this is *not* required the documentation *recommends* setting it (though it doesn't say how it's used). Ruby pytests still pass after this change... Closes: https://github.com/nginx/unit/issues/1525 Link: <https://bugs.ruby-lang.org/issues/19998> Link: <https://docs.ruby-lang.org/en/3.4/extension_rdoc.html#label-C+struct+to+Ruby+object> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-01-14http: add `.mjs` extension to default mime typesTal Kedar1-0/+1
Associate file extension `.mjs` with `application/javascript`. Context: common output of static site generators. There's little risk of ambiguity for this extension, so might as well support it out of the box. [ Subject tweak - Andrew ] Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2025-01-08otel: remove deadcodeAva Hahn1-10/+1
The superfluous else condition in nxt_otel_propagate_header was dead code. This commit removes it. Signed-off-by: Ava Hahn <a.hahn@f5.com>
2025-01-08otel: fix segfaults when otel not configuredAva Hahn1-6/+9
This commit adds NULL checks for the request->otel object that were missed in the Traceparent and Tracestate routines. Closes: https://github.com/nginx/unit/issues/1523 Closes: https://github.com/nginx/unit/issues/1526 Fixes: 9d3dcb800 ("otel: add build tooling to include otel code") Signed-off-by: Ava Hahn <a.hahn@f5.com>
2024-12-18wasm-wc: Update cratesAndrew Clayton1-417/+564
Run 'cargo update' to get the latest version of the required crates in preparation for the 1.34.0 release. This resolves a dependabot notification regarding 'idna'. Link: <https://github.com/nginx/unit/security/dependabot/13> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2024-12-18otel: Update cratesAndrew Clayton1-237/+531
Run 'cargo update' to get the latest version of the required crates in preparation for the 1.34.0 release. The rustls update fixes a panic in `rustls::server::Acceptor::accept()`, but Unit does not use this code path and was not affected. Link: <https://rustsec.org/advisories/RUSTSEC-2024-0399.html> Link: <https://github.com/nginx/unit/security/dependabot/11> Closes: <https://github.com/nginx/unit/issues/1503> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2024-12-18wasm-wc: Update to wasmtime 27.0.0Andrew Clayton2-76/+76
For no real reason other than to be on the latest release for the next release of Unit... Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2024-12-10otel: Disable static_mut_refs warning for nxt_otel_rs_span_tx()Andrew Clayton1-0/+1
When compiling OTEL support with rustc 1.83.0 we started getting the following warning Compiling otel v0.1.0 (/home/andrew/src/unit/src/otel) warning: creating a mutable reference to mutable static is discouraged --> src/lib.rs:42:9 | 42 | SPAN_TX.take(); | ^^^^^^^^^^^^^^ mutable reference to mutable static | = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html> = note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives = note: `#[warn(static_mut_refs)]` on by default warning: `otel` (lib) generated 1 warning Finished `release` profile [optimized] target(s) in 1m 07s However it *seems* our usage is OK, so we can disable this warning (which it seems will soon turn into a hard error), fortunately we only need to disable it for the nxt_otel_rs_span_tx() function. Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2024-11-26wasm: Fix build with wasmtime 27.0.0Sergey A. Osokin1-0/+6
Wasmtime 27.0.0 adjusted the C API to start flowing through the directory and file permission bits of the underlying rust wasi_config_preopen_dir() implementation. The directory permissions control whether a directory is read-only or whether you can create/modify files within. You always need at least WASMTIME_WASI_DIR_PERMS_READ. The file permissions control whether you can read or read/write files. WASMTIME_WASI_FILE_PERMS_WRITE seems to imply WASMTIME_WASI_FILE_PERMS_READ (but we add both just to make it clear what we want) [ Permissions tweak and commit message - Andrew ] Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2024-11-19Decast nxt_cpymem()Andrew Clayton1-1/+1
nxt_cpymem() is basically mempcpy(3) Like mempcpy() nxt_cpymem() returns a void *. nxt_cpymem() is implemented as a wrapper around memcpy(3), however before returning the new pointer value we cast the return of memcpy(3) to a u_char *, then add the length parameter to it. I guess this was done to support compilers that do not support arithmetic on void pointers as the C standard forbids it. However since we removed support for compilers other than GCC and Clang (ending in commit 9cd11133 ("Remove support for Sun's Sun Studio/SunPro C compiler")) this is no longer an issue as both GCC and Clang support arithmetic on void pointers (without the -pedantic option) by treating the size of a void as 1. While removing the unnecessary casting in this case doesn't necessarily improve type-safety (as we're dealing with void *'s in and out), it does just make the code that little more readable. Oh and for interest we have actually already been relying on this extension src/nxt_array.c:143:40: warning: arithmetic on a pointer to void is a GNU extension [-Wgnu-pointer-arith] 143 | nxt_memcpy(data, src->elts + (i * size), size); | ~~~~~~~~~ ^ src/nxt_string.h:45:24: note: expanded from macro 'nxt_memcpy' 45 | (void) memcpy(dst, src, length) | ^~~ which was introduced in e2b53e16 ("Added "rootfs" feature.") back in 2020. Link: <https://gcc.gnu.org/onlinedocs/gcc/Pointer-Arith.html> Link: <https://clang.llvm.org/docs/LanguageExtensions.html#introduction> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2024-11-14http: Support JSON format in access logZhidao HONG2-16/+229
Allow format to be an object to generate JSON logs. The object keys become JSON field names, and values support string, variable, and JS. Note that when there is no JS in the format values, the object will be pre-serialized to a JSON template string at configuration phase for better performance. Example config: { "access_log": { "path": "/tmp/access.log", "format": { "remote_addr": "$remote_addr", "time_local": "$time_local", "request_line": "$request_line", "status": "$status", "body_bytes_sent": "$body_bytes_sent", "header_referer": "$header_referer", "header_user_agent": "$header_user_agent" } } }
2024-11-14http: Introduce nxt_router_access_log_format_t structureZhidao HONG2-37/+68
This is a preparatory refactoring for upcoming JSON format support in access log. We will extend format option to access object for JSON support. No functional changes.
2024-11-14http: Refactor format field in nxt_router_access_log_conf_tZhidao HONG1-12/+15
This is a preparatory refactoring for upcoming JSON format support in access log. No functional changes.