From ranier.vf at gmail.com Sun Mar 1 19:57:48 2020 From: ranier.vf at gmail.com (Ranier Vilela) Date: Sun, 1 Mar 2020 16:57:48 -0300 Subject: [PATCH] CORE: array, reduce var declaration Message-ID: Hi, Is it in the interest of the nginx team, patches that promote the reduction of variable declaration? regards, Ranier Vilela --- \dll\nginx-1.17.8\a\core\ngx_array.c 2020-01-21 10:39:42.000000000 -0300 +++ ngx_array.c 2020-03-01 10:51:56.769840300 -0300 @@ -48,10 +48,10 @@ ngx_array_push(ngx_array_t *a) { void *elt, *new; - size_t size; - ngx_pool_t *p; if (a->nelts == a->nalloc) { + size_t size; + ngx_pool_t *p; /* the array is full */ @@ -94,14 +94,13 @@ void * ngx_array_push_n(ngx_array_t *a, ngx_uint_t n) { - void *elt, *new; + void *elt; size_t size; - ngx_uint_t nalloc; - ngx_pool_t *p; size = n * a->size; if (a->nelts + n > a->nalloc) { + ngx_pool_t *p; /* the array is full */ @@ -119,6 +118,9 @@ a->nalloc += n; } else { + void *new; + ngx_uint_t nalloc; + /* allocate a new array */ nalloc = 2 * ((n >= a->nalloc) ? n : a->nalloc); -------------- next part -------------- An HTML attachment was scrubbed... URL: From xeioex at nginx.com Mon Mar 2 11:51:47 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 02 Mar 2020 11:51:47 +0000 Subject: [njs] Fixed integer-overflow in Date() constructor. Message-ID: details: https://hg.nginx.org/njs/rev/36208bd2362f branches: changeset: 1343:36208bd2362f user: Dmitry Volyntsev date: Fri Feb 28 19:39:13 2020 +0300 description: Fixed integer-overflow in Date() constructor. Found by UndefinedBehaviorSanitizer. diffstat: src/njs_date.c | 17 +++++++++++------ src/test/njs_unit_test.c | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+), 6 deletions(-) diffs (73 lines): diff -r 3f094214cd64 -r 36208bd2362f src/njs_date.c --- a/src/njs_date.c Fri Feb 28 18:56:24 2020 +0300 +++ b/src/njs_date.c Fri Feb 28 19:39:13 2020 +0300 @@ -118,14 +118,19 @@ njs_days_from_year(int64_t y) } -njs_inline int64_t +njs_inline double njs_make_day(int64_t yr, int64_t month, int64_t date) { - int64_t i, ym, mn, md, days; + double days; + int64_t i, ym, mn, md; static const int month_days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + if (yr < -271822 || yr > 275761) { + return NAN; + } + mn = njs_mod(month, 12); ym = yr + (month - mn) / 12; @@ -228,15 +233,15 @@ njs_year_from_days(int64_t *days) njs_inline double njs_make_date(int64_t tm[], njs_bool_t local) { - int64_t days, time; + double time, days; days = njs_make_day(tm[NJS_DATE_YR], tm[NJS_DATE_MON], tm[NJS_DATE_DAY]); - time = ((tm[NJS_DATE_HR] * 60 + tm[NJS_DATE_MIN]) * 60 - + tm[NJS_DATE_SEC]) * 1000 + tm[NJS_DATE_MSEC]; + 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 * 86400000; + time += days * 86400000.0; if (local) { time += njs_tz_offset(time) * 60000; diff -r 3f094214cd64 -r 36208bd2362f src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Fri Feb 28 18:56:24 2020 +0300 +++ b/src/test/njs_unit_test.c Fri Feb 28 19:39:13 2020 +0300 @@ -13270,6 +13270,24 @@ static njs_unit_test_t njs_test[] = { njs_str("new Date(8.65e15)"), njs_str("Invalid Date") }, + { njs_str("var d = new Date(1308895200000); new Date(d.getTime(), d.getTime())"), + njs_str("Invalid Date") }, + + { njs_str("new Date(275760, 1, 2**61)"), + njs_str("Invalid Date") }, + + { njs_str("new Date(275760, 1, 1, 2**61)"), + njs_str("Invalid Date") }, + + { njs_str("new Date(275760, 1, 1, 1, 2**61)"), + njs_str("Invalid Date") }, + + { njs_str("new Date(275760, 1, 1, 1, 1, 2**61)"), + njs_str("Invalid Date") }, + + { njs_str("new Date(275760, 1, 1, 1, 1, 1, 2**61)"), + njs_str("Invalid Date") }, + { njs_str("njs.dump([new Date(8.65e15)])"), njs_str("[Invalid Date]") }, From mdounin at mdounin.ru Mon Mar 2 12:24:05 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 2 Mar 2020 15:24:05 +0300 Subject: [PATCH] CORE: array, reduce var declaration In-Reply-To: References: Message-ID: <20200302122405.GL12894@mdounin.ru> Hello! On Sun, Mar 01, 2020 at 04:57:48PM -0300, Ranier Vilela wrote: > Is it in the interest of the nginx team, patches that promote the reduction > of variable declaration? No, thanks. This contradicts nginx coding style. -- Maxim Dounin http://mdounin.ru/ From thibaultcha at fastmail.com Mon Mar 2 16:27:28 2020 From: thibaultcha at fastmail.com (Thibault Charbonnier) Date: Mon, 2 Mar 2020 08:27:28 -0800 Subject: [PATCH] Ensured SIGQUIT deletes listening UNIX socket files. In-Reply-To: References: <4b6bc48b-6c7a-7c76-51ae-1038421ed36c@fastmail.com> <20200227152429.GI12894@mdounin.ru> Message-ID: <2c06ad76-c309-d387-2c40-f6e60aacf4f8@fastmail.com> Hello Maxim, Any thoughts on the latest version of this patch? Cheers, On 2/27/20 4:23 PM, Thibault Charbonnier wrote: > On 2/27/20 7:24 AM, Maxim Dounin wrote: >> Have you checked what happens during binary upgrade with your >> patch? > > Good call, I gave it a thought but did not bother checking, thanks for > sharing the previous patch. This one is slightly simpler. > > Below is a new version of the patch covering binary upgrade edge-cases > by relying on the existence of the nginx.oldpid file. > > Also attached to this email is a file I used as a test suite covering > the behavior of this patch with SIGQUIT, SIGTERM, and binary upgrade > scenarios. > > # HG changeset patch > # User Thibault Charbonnier > # Date 1582764433 28800 > # Wed Feb 26 16:47:13 2020 -0800 > # Node ID ec619d02801b925b4dad51515fb9668c1d993418 > # Parent 4f18393a1d51bce6103ea2f1b2587900f349ba3d > Ensured SIGQUIT deletes listening UNIX socket files. > > Prior to this patch, the SIGQUIT signal handling (graceful shutdown) did not > remove UNIX socket files since ngx_master_process_cycle reimplemented > listening > socket closings in lieu of using ngx_close_listening_sockets. > > Since ngx_master_process_exit will call the aforementioned > ngx_close_listening_sockets, we can remove the custom implementation and now > expect listening sockets to be closed properly by > ngx_close_listening_sockets > instead. > > This fixes the trac issue #753 (https://trac.nginx.org/nginx/ticket/753). > > diff -r 4f18393a1d51 -r ec619d02801b src/core/ngx_connection.c > --- a/src/core/ngx_connection.c Thu Feb 20 16:51:07 2020 +0300 > +++ b/src/core/ngx_connection.c Wed Feb 26 16:47:13 2020 -0800 > @@ -1023,6 +1023,10 @@ > ngx_uint_t i; > ngx_listening_t *ls; > ngx_connection_t *c; > +#if (NGX_HAVE_UNIX_DOMAIN) > + ngx_core_conf_t *ccf; > + ngx_fd_t fd; > +#endif > > if (ngx_event_flags & NGX_USE_IOCP_EVENT) { > return; > @@ -1067,10 +1071,22 @@ > } > > #if (NGX_HAVE_UNIX_DOMAIN) > + ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, > ngx_core_module); > + > + fd = ngx_open_file(ccf->oldpid.data, NGX_FILE_RDONLY, > NGX_FILE_OPEN, 0); > + > + if (fd != NGX_INVALID_FILE) { > + if (ngx_close_file(fd) == NGX_FILE_ERROR) { > + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, > + ngx_close_file_n " \"%s\" failed", > + ccf->oldpid.data); > + } > + } > > if (ls[i].sockaddr->sa_family == AF_UNIX > && ngx_process <= NGX_PROCESS_MASTER > - && ngx_new_binary == 0) > + && ngx_new_binary == 0 > + && fd == NGX_INVALID_FILE) > { > u_char *name = ls[i].addr_text.data + sizeof("unix:") - 1; > > diff -r 4f18393a1d51 -r ec619d02801b src/os/unix/ngx_process_cycle.c > --- a/src/os/unix/ngx_process_cycle.c Thu Feb 20 16:51:07 2020 +0300 > +++ b/src/os/unix/ngx_process_cycle.c Wed Feb 26 16:47:13 2020 -0800 > @@ -77,12 +77,11 @@ > u_char *p; > size_t size; > ngx_int_t i; > - ngx_uint_t n, sigio; > + ngx_uint_t sigio; > sigset_t set; > struct itimerval itv; > ngx_uint_t live; > ngx_msec_t delay; > - ngx_listening_t *ls; > ngx_core_conf_t *ccf; > > >> Previous attempt to fix this was here: >> >> http://mailman.nginx.org/pipermail/nginx-devel/2016-December/009207.html >> http://mailman.nginx.org/pipermail/nginx-devel/2016-December/009208.html >> >> Yet it failed to address binary upgrade case properly, see here: >> >> http://mailman.nginx.org/pipermail/nginx-devel/2016-December/009239.html >> > > sigemptyset(&set); > @@ -205,16 +204,6 @@ > ngx_signal_worker_processes(cycle, > > ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); > > - ls = cycle->listening.elts; > - for (n = 0; n < cycle->listening.nelts; n++) { > - if (ngx_close_socket(ls[n].fd) == -1) { > - ngx_log_error(NGX_LOG_EMERG, cycle->log, > ngx_socket_errno, > - ngx_close_socket_n " %V failed", > - &ls[n].addr_text); > - } > - } > - cycle->listening.nelts = 0; > - > continue; > } > > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > From xeioex at nginx.com Mon Mar 2 17:30:36 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 02 Mar 2020 17:30:36 +0000 Subject: [nginx] Fixed premature background subrequest finalization. Message-ID: details: https://hg.nginx.org/nginx/rev/b4dbf8b98f9a branches: changeset: 7631:b4dbf8b98f9a user: Dmitry Volyntsev date: Mon Mar 02 20:07:36 2020 +0300 description: Fixed premature background subrequest finalization. When "aio" or "aio threads" is used while processing the response body of an in-memory background subrequest, the subrequest could be finalized with an aio operation still in progress. Upon aio completion either parent request is woken or the old r->write_event_handler is called again. The latter may result in request errors. In either case post_subrequest handler is never called with the full response body, which is typically expected when using in-memory subrequests. Currently in nginx background subrequests are created by the upstream module and the mirror module. The issue does not manifest itself with these subrequests because they are header-only. But it can manifest itself with third-party modules which create in-memory background subrequests. diffstat: src/http/ngx_http_request.c | 18 +++++++++--------- 1 files changed, 9 insertions(+), 9 deletions(-) diffs (35 lines): diff -r f001d9384293 -r b4dbf8b98f9a src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c Fri Feb 28 17:21:18 2020 +0300 +++ b/src/http/ngx_http_request.c Mon Mar 02 20:07:36 2020 +0300 @@ -2490,6 +2490,15 @@ ngx_http_finalize_request(ngx_http_reque if (r != r->main) { clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + if (r->buffered || r->postponed) { + + if (ngx_http_set_write_handler(r) != NGX_OK) { + ngx_http_terminate_request(r, 0); + } + + return; + } + if (r->background) { if (!r->logged) { if (clcf->log_subrequest) { @@ -2509,15 +2518,6 @@ ngx_http_finalize_request(ngx_http_reque return; } - if (r->buffered || r->postponed) { - - if (ngx_http_set_write_handler(r) != NGX_OK) { - ngx_http_terminate_request(r, 0); - } - - return; - } - pr = r->parent; if (r == c->data) { From arut at nginx.com Mon Mar 2 17:54:15 2020 From: arut at nginx.com (Roman Arutyunyan) Date: Mon, 02 Mar 2020 17:54:15 +0000 Subject: [nginx] Simplified subrequest finalization. Message-ID: details: https://hg.nginx.org/nginx/rev/1d207b77b44a branches: changeset: 7632:1d207b77b44a user: Roman Arutyunyan date: Fri Feb 28 19:54:13 2020 +0300 description: Simplified subrequest finalization. Now it looks similar to what it was before background subrequests were introduced in 9552758a786e. diffstat: src/http/ngx_http_request.c | 36 ++++++++++++------------------------ 1 files changed, 12 insertions(+), 24 deletions(-) diffs (64 lines): diff -r b4dbf8b98f9a -r 1d207b77b44a src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c Mon Mar 02 20:07:36 2020 +0300 +++ b/src/http/ngx_http_request.c Fri Feb 28 19:54:13 2020 +0300 @@ -2488,7 +2488,6 @@ ngx_http_finalize_request(ngx_http_reque } if (r != r->main) { - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); if (r->buffered || r->postponed) { @@ -2499,8 +2498,14 @@ ngx_http_finalize_request(ngx_http_reque return; } - if (r->background) { + pr = r->parent; + + if (r == c->data || r->background) { + if (!r->logged) { + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + if (clcf->log_subrequest) { ngx_http_log_request(r); } @@ -2514,31 +2519,14 @@ ngx_http_finalize_request(ngx_http_reque } r->done = 1; - ngx_http_finalize_connection(r); - return; - } - - pr = r->parent; - - if (r == c->data) { + + if (r->background) { + ngx_http_finalize_connection(r); + return; + } r->main->count--; - if (!r->logged) { - if (clcf->log_subrequest) { - ngx_http_log_request(r); - } - - r->logged = 1; - - } else { - ngx_log_error(NGX_LOG_ALERT, c->log, 0, - "subrequest: \"%V?%V\" logged again", - &r->uri, &r->args); - } - - r->done = 1; - if (pr->postponed && pr->postponed->request == r) { pr->postponed = pr->postponed->next; } From xeioex at nginx.com Mon Mar 2 18:12:07 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 02 Mar 2020 18:12:07 +0000 Subject: [njs] HTTP: introduced detached subrequest mode in r.subrequest(). Message-ID: details: https://hg.nginx.org/njs/rev/a95c44303c1b branches: changeset: 1344:a95c44303c1b user: Dmitry Volyntsev date: Mon Mar 02 21:11:37 2020 +0300 description: HTTP: introduced detached subrequest mode in r.subrequest(). If "options.detached" boolean flag is true the created subrequest is a detached subrequest. Responses to detached subrequest are ignored. Unlike ordinary subrequests, a detached subrequest can be created inside a variable handler. The detached flag and callback argument are mutually exclusive. diffstat: nginx/ngx_http_js_module.c | 58 +++++++++++++++++++++++++++++++-------------- 1 files changed, 40 insertions(+), 18 deletions(-) diffs (119 lines): diff -r 36208bd2362f -r a95c44303c1b nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Fri Feb 28 19:39:13 2020 +0300 +++ b/nginx/ngx_http_js_module.c Mon Mar 02 21:11:37 2020 +0300 @@ -1786,7 +1786,7 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, { ngx_int_t rc, promise; njs_str_t uri_arg, args_arg, method_name, body_arg; - ngx_uint_t method, methods_max, has_body; + ngx_uint_t method, methods_max, has_body, detached; njs_value_t *value, *arg, *options; njs_function_t *callback; ngx_http_js_ctx_t *ctx; @@ -1817,6 +1817,7 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, static const njs_str_t args_key = njs_str("args"); static const njs_str_t method_key = njs_str("method"); static const njs_str_t body_key = njs_str("body"); + static const njs_str_t detached_key = njs_str("detached"); r = njs_vm_external(vm, njs_arg(args, nargs, 0)); if (njs_slow_path(r == NULL)) { @@ -1852,6 +1853,7 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, args_arg.start = NULL; has_body = 0; promise = 0; + detached = 0; arg = njs_arg(args, nargs, 2); @@ -1881,6 +1883,11 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, } } + value = njs_vm_object_prop(vm, options, &detached_key); + if (value != NULL) { + detached = njs_value_bool(value); + } + value = njs_vm_object_prop(vm, options, &method_key); if (value != NULL) { if (ngx_http_js_string(vm, value, &method_name) != NJS_OK) { @@ -1924,7 +1931,12 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, } } - if (callback == NULL) { + if (detached && callback != NULL) { + njs_vm_error(vm, "detached flag and callback are mutually exclusive"); + return NJS_ERROR; + } + + if (!detached && callback == NULL) { callback = njs_vm_function_alloc(vm, ngx_http_js_promise_trampoline); if (callback == NULL) { goto memory_error; @@ -1948,7 +1960,7 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, sr->method_name.data = method_name.start; } - sr->header_only = (sr->method == NGX_HTTP_HEAD); + sr->header_only = (sr->method == NGX_HTTP_HEAD) || (callback == NULL); if (has_body) { rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); @@ -1993,6 +2005,8 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, njs_value_arg(&ctx->promise_callbacks)); } + njs_value_undefined_set(njs_vm_retval(vm)); + return NJS_OK; memory_error: @@ -2015,23 +2029,31 @@ ngx_http_js_subrequest(ngx_http_request_ ctx = ngx_http_get_module_ctx(r, ngx_http_js_module); - flags = NGX_HTTP_SUBREQUEST_BACKGROUND | NGX_HTTP_SUBREQUEST_IN_MEMORY; - - ps = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t)); - if (ps == NULL) { - njs_vm_error(ctx->vm, "internal error"); - return NJS_ERROR; + flags = NGX_HTTP_SUBREQUEST_BACKGROUND; + + if (callback != NULL) { + ps = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t)); + if (ps == NULL) { + njs_vm_error(ctx->vm, "internal error"); + return NJS_ERROR; + } + + vm_event = njs_vm_add_event(ctx->vm, callback, 1, NULL, NULL); + if (vm_event == NULL) { + njs_vm_error(ctx->vm, "internal error"); + return NJS_ERROR; + } + + ps->handler = ngx_http_js_subrequest_done; + ps->data = vm_event; + + flags |= NGX_HTTP_SUBREQUEST_IN_MEMORY; + + } else { + ps = NULL; + vm_event = NULL; } - vm_event = njs_vm_add_event(ctx->vm, callback, 1, NULL, NULL); - if (vm_event == NULL) { - njs_vm_error(ctx->vm, "internal error"); - return NJS_ERROR; - } - - ps->handler = ngx_http_js_subrequest_done; - ps->data = vm_event; - uri.len = uri_arg->length; uri.data = uri_arg->start; From xeioex at nginx.com Tue Mar 3 14:18:34 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 03 Mar 2020 14:18:34 +0000 Subject: [njs] Version 0.3.9. Message-ID: details: https://hg.nginx.org/njs/rev/fc4eeaaf0dfe branches: changeset: 1345:fc4eeaaf0dfe user: Dmitry Volyntsev date: Tue Mar 03 17:17:08 2020 +0300 description: Version 0.3.9. diffstat: CHANGES | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 47 insertions(+), 0 deletions(-) diffs (54 lines): diff -r a95c44303c1b -r fc4eeaaf0dfe CHANGES --- a/CHANGES Mon Mar 02 21:11:37 2020 +0300 +++ b/CHANGES Tue Mar 03 17:17:08 2020 +0300 @@ -1,3 +1,50 @@ + +Changes with njs 0.3.9 03 Mar 2020 + + nginx modules: + + *) Feature: added detached mode for r.subrequest(). Responses to + detached subrequests are ignored. Unlike ordinary subrequests, + a detached subrequest can be created inside a variable handler. + + Core: + + *) Feature: added promises API for "fs" module. + Thanks to Artem S. Povalyukhin. + + *) Feature: extended "fs" module. Added access(), symlink(), unlink(), + realpath() and friends. + Thanks to Artem S. Povalyukhin. + + *) Improvement: introduced memory-efficient ordinary arrays. + + *) Improvement: lexer refactoring. + + *) Bugfix: fixed matching of native functions in backtraces. + + *) Bugfix: fixed callback invocations in "fs" module. + Thanks to Artem S. Povalyukhin. + + *) Bugfix: fixed Object.getOwnPropertySymbols(). + + *) Bugfix: fixed heap-buffer-overflow in njs_json_append_string(). + + *) Bugfix: fixed encodeURI() and decodeURI() according to + the specification. + + *) Bugfix: fixed Number.prototype.toPrecision(). + + *) Bugfix: fixed handling of space argument in JSON.stringify(). + + *) Bugfix: fixed JSON.stringify() with Number() and String() objects. + + *) Bugfix: fixed Unicode Escaping in JSON.stringify() according + to specification. + + *) Bugfix: fixed non-native module importing. + Thanks to ??? (Hong Zhi Dao). + + *) Bugfix: fixed njs.dump() with the Date() instance in a container. Changes with njs 0.3.8 21 Jan 2020 From xeioex at nginx.com Tue Mar 3 14:18:36 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 03 Mar 2020 14:18:36 +0000 Subject: [njs] Added tag 0.3.9 for changeset fc4eeaaf0dfe Message-ID: details: https://hg.nginx.org/njs/rev/9c9617d54e53 branches: changeset: 1346:9c9617d54e53 user: Dmitry Volyntsev date: Tue Mar 03 17:18:06 2020 +0300 description: Added tag 0.3.9 for changeset fc4eeaaf0dfe diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff -r fc4eeaaf0dfe -r 9c9617d54e53 .hgtags --- a/.hgtags Tue Mar 03 17:17:08 2020 +0300 +++ b/.hgtags Tue Mar 03 17:18:06 2020 +0300 @@ -32,3 +32,4 @@ b7fa83f27f1b64443b88c990e1851f59583b2182 7b302775917b72537e1abdbd5dc9d04e55a7d582 0.3.6 9e5ef927c7eaed003de3e5e4a16fa3eab08de7f7 0.3.7 1abb97e9d9dc07dcff2616d4c75132e6d189a6aa 0.3.8 +fc4eeaaf0dfe7dc7d41232f1b643bd364f1efe82 0.3.9 From mdounin at mdounin.ru Tue Mar 3 14:28:11 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 3 Mar 2020 17:28:11 +0300 Subject: [PATCH] Ensured SIGQUIT deletes listening UNIX socket files. In-Reply-To: <2c06ad76-c309-d387-2c40-f6e60aacf4f8@fastmail.com> References: <4b6bc48b-6c7a-7c76-51ae-1038421ed36c@fastmail.com> <20200227152429.GI12894@mdounin.ru> <2c06ad76-c309-d387-2c40-f6e60aacf4f8@fastmail.com> Message-ID: <20200303142811.GO12894@mdounin.ru> Hello! On Mon, Mar 02, 2020 at 08:27:28AM -0800, Thibault Charbonnier wrote: > Any thoughts on the latest version of this patch? Checking for the oldpid file does not look like a reliable approach to me. -- Maxim Dounin http://mdounin.ru/ From mdounin at mdounin.ru Tue Mar 3 15:05:31 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 03 Mar 2020 15:05:31 +0000 Subject: [nginx] Updated PCRE used for win32 builds. Message-ID: details: https://hg.nginx.org/nginx/rev/ac52638cd269 branches: changeset: 7633:ac52638cd269 user: Maxim Dounin date: Tue Mar 03 18:03:28 2020 +0300 description: Updated PCRE used for win32 builds. diffstat: misc/GNUmakefile | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 1d207b77b44a -r ac52638cd269 misc/GNUmakefile --- a/misc/GNUmakefile Fri Feb 28 19:54:13 2020 +0300 +++ b/misc/GNUmakefile Tue Mar 03 18:03:28 2020 +0300 @@ -8,7 +8,7 @@ CC = cl OBJS = objs.msvc8 OPENSSL = openssl-1.1.1d ZLIB = zlib-1.2.11 -PCRE = pcre-8.43 +PCRE = pcre-8.44 release: export From mdounin at mdounin.ru Tue Mar 3 15:05:35 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 03 Mar 2020 15:05:35 +0000 Subject: [nginx] nginx-1.17.9-RELEASE Message-ID: details: https://hg.nginx.org/nginx/rev/5e8d52bca714 branches: changeset: 7634:5e8d52bca714 user: Maxim Dounin date: Tue Mar 03 18:04:21 2020 +0300 description: nginx-1.17.9-RELEASE diffstat: docs/xml/nginx/changes.xml | 76 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 76 insertions(+), 0 deletions(-) diffs (86 lines): diff -r ac52638cd269 -r 5e8d52bca714 docs/xml/nginx/changes.xml --- a/docs/xml/nginx/changes.xml Tue Mar 03 18:03:28 2020 +0300 +++ b/docs/xml/nginx/changes.xml Tue Mar 03 18:04:21 2020 +0300 @@ -5,6 +5,82 @@ + + + + +?????? nginx ?? ????????? +????????? ????? "Host" ? ????????? ???????. + + +now nginx does not allow +several "Host" request header lines. + + + + + +nginx ??????????? ?????????????? +?????? "Transfer-Encoding" ? ????????? ???????. + + +nginx ignored additional +"Transfer-Encoding" request header lines. + + + + + +?????? ??????? ??? ????????????? HTTP/2. + + +socket leak when using HTTP/2. + + + + + +? ??????? ???????? ??? ????????? segmentation fault, +???? ????????????? OCSP stapling. + + +a segmentation fault might occur in a worker process +if OCSP stapling was used. + + + + + +? ?????? ngx_http_mp4_module. + + +in the ngx_http_mp4_module. + + + + + +??? ??????????????? ?????? ? ????? 494 ? ??????? ????????? error_page +nginx ????????? ????? ? ????? 494 ?????? 400. + + +nginx used status code 494 instead of 400 +if errors with code 494 were redirected with the "error_page" directive. + + + + + +?????? ??????? ??? ????????????? ??????????? ? ?????? njs ? ????????? aio. + + +socket leak when using subrequests in the njs module and the "aio" directive. + + + + + + From mdounin at mdounin.ru Tue Mar 3 15:05:38 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 03 Mar 2020 15:05:38 +0000 Subject: [nginx] release-1.17.9 tag Message-ID: details: https://hg.nginx.org/nginx/rev/4eb606b4a5b5 branches: changeset: 7635:4eb606b4a5b5 user: Maxim Dounin date: Tue Mar 03 18:04:21 2020 +0300 description: release-1.17.9 tag diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff -r 5e8d52bca714 -r 4eb606b4a5b5 .hgtags --- a/.hgtags Tue Mar 03 18:04:21 2020 +0300 +++ b/.hgtags Tue Mar 03 18:04:21 2020 +0300 @@ -447,3 +447,4 @@ 9af0dddbddb2c368bfedd2801bc100ffad01e19b de68d0d94320cbf033599c6f3ca37e5335c67fd7 release-1.17.6 e56295fe0ea76bf53b06bffa77a2d3a9a335cb8c release-1.17.7 fdacd273711ddf20f778c1fb91529ab53979a454 release-1.17.8 +5e8d52bca714d4b85284ddb649d1ba4a3ca978a8 release-1.17.9 From xeioex at nginx.com Tue Mar 3 16:01:49 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 03 Mar 2020 16:01:49 +0000 Subject: [njs] Version bump. Message-ID: details: https://hg.nginx.org/njs/rev/ef30d99ea2be branches: changeset: 1347:ef30d99ea2be user: Dmitry Volyntsev date: Tue Mar 03 18:57:15 2020 +0300 description: Version bump. diffstat: src/njs.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 9c9617d54e53 -r ef30d99ea2be src/njs.h --- a/src/njs.h Tue Mar 03 17:18:06 2020 +0300 +++ b/src/njs.h Tue Mar 03 18:57:15 2020 +0300 @@ -11,7 +11,7 @@ #include -#define NJS_VERSION "0.3.9" +#define NJS_VERSION "0.3.10" #include /* STDOUT_FILENO, STDERR_FILENO */ From xeioex at nginx.com Tue Mar 3 16:01:50 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 03 Mar 2020 16:01:50 +0000 Subject: [njs] Fixed integer constant is too large compilation error by gcc 4.4. Message-ID: details: https://hg.nginx.org/njs/rev/c5c6aab76bb4 branches: changeset: 1348:c5c6aab76bb4 user: Dmitry Volyntsev date: Tue Mar 03 19:00:54 2020 +0300 description: Fixed integer constant is too large compilation error by gcc 4.4. diffstat: src/njs_number.c | 2 +- src/njs_number.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diffs (24 lines): diff -r ef30d99ea2be -r c5c6aab76bb4 src/njs_number.c --- a/src/njs_number.c Tue Mar 03 18:57:15 2020 +0300 +++ b/src/njs_number.c Tue Mar 03 19:00:54 2020 +0300 @@ -236,7 +236,7 @@ njs_uint64_to_string(njs_vm_t *vm, njs_v u_char *dst, *p; u_char buf[128]; - if (njs_fast_path(u64 < 0x3fffffffffff)) { + if (njs_fast_path(u64 < 0x3fffffffffffULL)) { /* Fits to short_string. */ dst = njs_string_short_start(value); diff -r ef30d99ea2be -r c5c6aab76bb4 src/njs_number.h --- a/src/njs_number.h Tue Mar 03 18:57:15 2020 +0300 +++ b/src/njs_number.h Tue Mar 03 19:00:54 2020 +0300 @@ -8,7 +8,7 @@ #define _NJS_NUMBER_H_INCLUDED_ -#define NJS_MAX_LENGTH (0x1fffffffffffff) +#define NJS_MAX_LENGTH (0x1fffffffffffffULL) double njs_key_to_index(const njs_value_t *value); From xeioex at nginx.com Tue Mar 3 17:36:47 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 03 Mar 2020 17:36:47 +0000 Subject: [njs] Fixed compilation with gcc. Message-ID: details: https://hg.nginx.org/njs/rev/65f4b11e3302 branches: changeset: 1349:65f4b11e3302 user: Dmitry Volyntsev date: Tue Mar 03 20:14:48 2020 +0300 description: Fixed compilation with gcc. diffstat: src/njs_fs.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diffs (13 lines): diff -r c5c6aab76bb4 -r 65f4b11e3302 src/njs_fs.c --- a/src/njs_fs.c Tue Mar 03 19:00:54 2020 +0300 +++ b/src/njs_fs.c Tue Mar 03 20:14:48 2020 +0300 @@ -818,6 +818,9 @@ njs_fs_mode(njs_vm_t *vm, njs_value_t *v uint32_t u32; njs_int_t ret; + /* GCC complains about uninitialized u32. */ + u32 = 0; + if (njs_is_undefined(value)) { return default_mode; } From alexander.borisov at nginx.com Wed Mar 4 14:14:12 2020 From: alexander.borisov at nginx.com (Alexander Borisov) Date: Wed, 04 Mar 2020 14:14:12 +0000 Subject: [njs] Fixed NULL-pointer dereference in "__proto__" property handler. Message-ID: details: https://hg.nginx.org/njs/rev/a16e0c8f4bb2 branches: changeset: 1350:a16e0c8f4bb2 user: Alexander Borisov date: Wed Mar 04 17:12:55 2020 +0300 description: Fixed NULL-pointer dereference in "__proto__" property handler. This closes #293 issue on GitHub. diffstat: src/njs_object.c | 7 ++++++- src/test/njs_unit_test.c | 3 +++ 2 files changed, 9 insertions(+), 1 deletions(-) diffs (30 lines): diff -r 65f4b11e3302 -r a16e0c8f4bb2 src/njs_object.c --- a/src/njs_object.c Tue Mar 03 20:14:48 2020 +0300 +++ b/src/njs_object.c Wed Mar 04 17:12:55 2020 +0300 @@ -2005,7 +2005,12 @@ njs_primitive_prototype_get_proto(njs_vm proto = &vm->prototypes[index].object; } - njs_set_type_object(retval, proto, proto->type); + if (proto != NULL) { + njs_set_type_object(retval, proto, proto->type); + + } else { + njs_set_undefined(retval); + } return NJS_OK; } diff -r 65f4b11e3302 -r a16e0c8f4bb2 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Tue Mar 03 20:14:48 2020 +0300 +++ b/src/test/njs_unit_test.c Wed Mar 04 17:12:55 2020 +0300 @@ -12637,6 +12637,9 @@ static njs_unit_test_t njs_test[] = { njs_str("typeof Object.setPrototypeOf({}, null)"), njs_str("object") }, + { njs_str("Object.setPrototypeOf(Object.getPrototypeOf(''), null).__proto__"), + njs_str("undefined") }, + { njs_str("var p = {}; var o = Object.create(p);" "p.isPrototypeOf(o)"), njs_str("true") }, From mdounin at mdounin.ru Wed Mar 4 16:30:06 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 4 Mar 2020 19:30:06 +0300 Subject: Dynamic Modules - Support CXXFLAGS In-Reply-To: <147FA808-5906-4B64-BFBF-3333B940BF71@firma.seznam.cz> References: <147FA808-5906-4B64-BFBF-3333B940BF71@firma.seznam.cz> Message-ID: <20200304163006.GY12894@mdounin.ru> Hello! On Fri, Feb 28, 2020 at 10:14:31AM +0100, Patrik Mada wrote: > Dear NGINX developers, > > we are using C++ dynamic modules in our NGINX based servers, > while multiple Debian distributions have to be supported. > On older Debian distributions it is impossible to use more > recent C++ standard, due to build defaulting to system provided > clang package. > > Our developers stood before decision to either create wrappers > around modern C++ libraries which would be compliant with older > standards or write the entire logic using obsolete featureless > language. > Neither of these approaches is sustainable in terms of > developers' productivity and long term maintenance. > > Would it be possible to consider a change in dynamic modules' > build system, so that C++ flags may be provided? > We propose a low intrusive changes concerning 3 files. The > changes are backwards compatible: if CXX is not provided by an > user, the build uses CC instead (as well as CFLAGS instead of > CXXFLAGS). > > Would you be so kind and share your opinion on those? Please > find attachment provided bellow (the patch was created using > Quilt). The most serious problem I see with this approach is that nginx does not try to use C++ itself, and hence it will always fail to properly detect and use separate C++ compiler and/or provide reasonable C++ compiler flags. And, given that CXX might be set to something completely different from CC, it does not look like a problem which is easy to solve. Further, as far as I see from your patch, it simply does not try provide any flags at all, except those set explicitly with CXXFLAGS. While this might work in your particular case, this looks wrong, and certainly not in line with how things are handled now, with CFLAGS set based on compiler unless explicitly specified. A better approach might be to either provide reasonable CFLAGS (and/or --with-cc-opt) for a particular system, which will make it compile your C++ code with the same compiler and compiler flags as used to compile nginx itself. Or, if it is not possible for some reason, to provide a config.make script to provide instructions on how to compile your code independently. -- Maxim Dounin http://mdounin.ru/ From chienhsw at opentext.com Wed Mar 4 19:57:07 2020 From: chienhsw at opentext.com (ChienHsing Wu) Date: Wed, 4 Mar 2020 19:57:07 +0000 Subject: HTTP/2: allow unlimited number of requests in connection Message-ID: Hi Maxim, Does the allocated memory from connection memory pool for a given connection grow as the number of request grows? If so could you elaborate on how much it grows for a new request? If not, I guess the main reason to limit the request number is to limit the lifetime of a connection so the connection pool size is under control, right? Is there an parameter to control the lifetime of a http2 connection instead? Thanks, ChienHsing -------------------------------------------------------------------------------------------------------------------- Maxim Dounin mdounin at mdounin.ru Fri Jul 12 14:24:54 UTC 2019 Hello! On Mon, Jul 01, 2019 at 11:24:28AM +0200, Michael W?rtinger wrote: > thanks a lot for your reply. Could you please elaborate a little bit > which memory resources need to be freed periodically? How much memory > can be held by a connection? What's the worst case scenario? > We are currently running it in production with http2_max_requests set > to a value so high that the connection practically lives forever and > so far we cannot spot any problems but maybe we're missing something? And example of "wost case" can be seen here: http://mailman.nginx.org/pipermail/nginx/2018-July/056525.html Memory can be allocated from the connection memory pool. And this memory have to be freed at some point - so you have to close the connection to do this. And that's why number of requests in a particular connection is limited by default. Whether or not memory allocations happens in your particular use case - doesn't really matter, especially given that things can change with seamingly minor configuration and/or client behaviour changes. In most cases we try to limit allocations from the connection memory pool to a minimum, yet it is not always possible/convinient to completely avoid allocations from connection memory pool. This allows processing of thousands of requests on a single connection without observable memory impact. Likely millions will also work except may be in some specific use cases, yet I wouldn't recommend allowing that many requests, just to be on the safe side. -- Maxim Dounin http://mdounin.ru/ -------------- next part -------------- An HTML attachment was scrubbed... URL: From xeioex at nginx.com Thu Mar 5 13:10:17 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 05 Mar 2020 13:10:17 +0000 Subject: [njs] Sharing external initialization between unit and interactive tests. Message-ID: details: https://hg.nginx.org/njs/rev/eb9258cfcf40 branches: changeset: 1351:eb9258cfcf40 user: Dmitry Volyntsev date: Thu Mar 05 15:24:52 2020 +0300 description: Sharing external initialization between unit and interactive tests. diffstat: auto/make | 25 +- src/test/njs_externals_test.c | 682 ++++++++++++++++++++++++++++++++++++++++ src/test/njs_externals_test.h | 14 + src/test/njs_interactive_test.c | 7 + src/test/njs_unit_test.c | 674 +--------------------------------------- 5 files changed, 729 insertions(+), 673 deletions(-) diffs (truncated from 1465 to 1000 lines): diff -r a16e0c8f4bb2 -r eb9258cfcf40 auto/make --- a/auto/make Wed Mar 04 17:12:55 2020 +0300 +++ b/auto/make Thu Mar 05 15:24:52 2020 +0300 @@ -173,6 +173,27 @@ done # njs tests. +njs_src="src/test/njs_externals_test.c" +fname=$(basename $njs_src) +njs_externals_obj="test/${fname%.c}.o" +njs_dep="test/${fname%.c}.dep" +njs_dep_flags=`njs_gen_dep_flags $njs_dep $fname` +njs_dep_post=`njs_gen_dep_post $njs_dep $fname` + +cat << END >> $NJS_MAKEFILE + +$NJS_BUILD_DIR/$njs_externals_obj: $njs_src + \$(NJS_CC) -c \$(NJS_CFLAGS) $NJS_LIB_AUX_CFLAGS \\ + \$(NJS_LIB_INCS) -Injs \\ + -o $NJS_BUILD_DIR/$njs_externals_obj \\ + $njs_dep_flags \\ + $njs_src + $njs_dep_post + +-include $NJS_BUILD_DIR/$njs_dep + +END + for njs_src in $NJS_TEST_SRCS do fname=$(basename $njs_src) @@ -183,11 +204,13 @@ do cat << END >> $NJS_MAKEFILE $NJS_BUILD_DIR/$njs_bin: $njs_src \\ - $NJS_BUILD_DIR/libnjs.a + $NJS_BUILD_DIR/libnjs.a \\ + $NJS_BUILD_DIR/$njs_externals_obj \$(NJS_CC) -o $NJS_BUILD_DIR/$njs_bin \$(NJS_CFLAGS) \\ $NJS_LIB_AUX_CFLAGS \$(NJS_LIB_INCS) \\ $njs_dep_flags \\ -Injs $njs_src $NJS_BUILD_DIR/libnjs.a \\ + $NJS_BUILD_DIR/$njs_externals_obj \\ -lm $NJS_LIBS $NJS_LIB_AUX_LIBS $njs_dep_post diff -r a16e0c8f4bb2 -r eb9258cfcf40 src/test/njs_externals_test.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/test/njs_externals_test.c Thu Mar 05 15:24:52 2020 +0300 @@ -0,0 +1,682 @@ + +/* + * Copyright (C) Dmitry Volyntsev + * Copyright (C) NGINX, Inc. + */ + +#include + +#include "njs_externals_test.h" + + +typedef struct { + njs_lvlhsh_t hash; + const njs_extern_t *proto; + njs_mp_t *pool; + + uint32_t a; + njs_str_t uri; + + njs_opaque_value_t value; +} njs_unit_test_req_t; + + +typedef struct { + njs_value_t name; + njs_value_t value; +} njs_unit_test_prop_t; + + +static njs_int_t +lvlhsh_unit_test_key_test(njs_lvlhsh_query_t *lhq, void *data) +{ + njs_str_t name; + njs_unit_test_prop_t *prop; + + prop = data; + njs_string_get(&prop->name, &name); + + if (name.length != lhq->key.length) { + return NJS_DECLINED; + } + + if (memcmp(name.start, lhq->key.start, lhq->key.length) == 0) { + return NJS_OK; + } + + return NJS_DECLINED; +} + + +static void * +lvlhsh_unit_test_pool_alloc(void *pool, size_t size) +{ + return njs_mp_align(pool, size, size); +} + + +static void +lvlhsh_unit_test_pool_free(void *pool, void *p, size_t size) +{ + njs_mp_free(pool, p); +} + + +static const njs_lvlhsh_proto_t lvlhsh_proto njs_aligned(64) = { + NJS_LVLHSH_LARGE_SLAB, + lvlhsh_unit_test_key_test, + lvlhsh_unit_test_pool_alloc, + lvlhsh_unit_test_pool_free, +}; + + +static njs_unit_test_prop_t * +lvlhsh_unit_test_alloc(njs_mp_t *pool, const njs_value_t *name, + const njs_value_t *value) +{ + njs_unit_test_prop_t *prop; + + prop = njs_mp_alloc(pool, sizeof(njs_unit_test_prop_t)); + if (prop == NULL) { + return NULL; + } + + prop->name = *name; + prop->value = *value; + + return prop; +} + + +static njs_int_t +lvlhsh_unit_test_add(njs_unit_test_req_t *r, njs_unit_test_prop_t *prop) +{ + njs_lvlhsh_query_t lhq; + + njs_string_get(&prop->name, &lhq.key); + lhq.key_hash = njs_djb_hash(lhq.key.start, lhq.key.length); + + lhq.replace = 1; + lhq.value = (void *) prop; + lhq.proto = &lvlhsh_proto; + lhq.pool = r->pool; + + switch (njs_lvlhsh_insert(&r->hash, &lhq)) { + + case NJS_OK: + return NJS_OK; + + case NJS_DECLINED: + default: + return NJS_ERROR; + } +} + + +static njs_int_t +njs_unit_test_r_get_uri_external(njs_vm_t *vm, njs_value_t *value, void *obj, + uintptr_t data) +{ + char *p; + njs_str_t *field; + + p = obj; + field = (njs_str_t *) (p + data); + + return njs_vm_value_string_set(vm, value, field->start, field->length); +} + + +static njs_int_t +njs_unit_test_r_set_uri_external(njs_vm_t *vm, void *obj, uintptr_t data, + njs_str_t *value) +{ + char *p; + njs_str_t *field; + + p = obj; + field = (njs_str_t *) (p + data); + + *field = *value; + + return NJS_OK; +} + + +static njs_int_t +njs_unit_test_r_get_a_external(njs_vm_t *vm, njs_value_t *value, void *obj, + uintptr_t data) +{ + u_char *p; + njs_unit_test_req_t *r; + u_char buf[16]; + + r = (njs_unit_test_req_t *) obj; + + p = njs_sprintf(buf, buf + njs_length(buf), "%uD", r->a); + + return njs_vm_value_string_set(vm, value, buf, p - buf); +} + + +static njs_int_t +njs_unit_test_r_get_b_external(njs_vm_t *vm, njs_value_t *value, void *obj, + uintptr_t data) +{ + njs_value_number_set(value, data); + + return NJS_OK; +} + + +static njs_int_t +njs_unit_test_host_external(njs_vm_t *vm, njs_value_t *value, void *obj, + uintptr_t data) +{ + return njs_vm_value_string_set(vm, value, (u_char *) "???????????", 22); +} + + +static njs_int_t +njs_unit_test_r_get_vars(njs_vm_t *vm, njs_value_t *value, void *obj, + uintptr_t data) +{ + njs_int_t ret; + njs_str_t *key; + njs_lvlhsh_query_t lhq; + njs_unit_test_req_t *r; + njs_unit_test_prop_t *prop; + + r = (njs_unit_test_req_t *) obj; + key = (njs_str_t *) data; + + lhq.key = *key; + lhq.key_hash = njs_djb_hash(key->start, key->length); + lhq.proto = &lvlhsh_proto; + + ret = njs_lvlhsh_find(&r->hash, &lhq); + + prop = lhq.value; + + if (ret == NJS_OK && njs_is_valid(&prop->value)) { + *value = prop->value; + return NJS_OK; + } + + njs_value_undefined_set(value); + + return NJS_OK; +} + + +static njs_int_t +njs_unit_test_r_set_vars(njs_vm_t *vm, void *obj, uintptr_t data, + njs_str_t *value) +{ + njs_int_t ret; + njs_str_t *key; + njs_value_t name, val; + njs_unit_test_req_t *r; + njs_unit_test_prop_t *prop; + + r = (njs_unit_test_req_t *) obj; + key = (njs_str_t *) data; + + if (key->length == 5 && memcmp(key->start, "error", 5) == 0) { + njs_vm_error(vm, "cannot set \"error\" prop"); + return NJS_ERROR; + } + + njs_vm_value_string_set(vm, &name, key->start, key->length); + njs_vm_value_string_set(vm, &val, value->start, value->length); + + prop = lvlhsh_unit_test_alloc(vm->mem_pool, &name, &val); + if (prop == NULL) { + njs_memory_error(vm); + return NJS_ERROR; + } + + ret = lvlhsh_unit_test_add(r, prop); + if (ret != NJS_OK) { + njs_vm_error(vm, "lvlhsh_unit_test_add() failed"); + return NJS_ERROR; + } + + return NJS_OK; +} + + +static njs_int_t +njs_unit_test_r_del_vars(njs_vm_t *vm, void *obj, uintptr_t data, + njs_bool_t delete) +{ + njs_int_t ret; + njs_str_t *key; + njs_lvlhsh_query_t lhq; + njs_unit_test_req_t *r; + njs_unit_test_prop_t *prop; + + r = (njs_unit_test_req_t *) obj; + key = (njs_str_t *) data; + + if (key->length == 5 && memcmp(key->start, "error", 5) == 0) { + njs_vm_error(vm, "cannot delete \"error\" prop"); + return NJS_ERROR; + } + + lhq.key = *key; + lhq.key_hash = njs_djb_hash(key->start, key->length); + lhq.proto = &lvlhsh_proto; + + ret = njs_lvlhsh_find(&r->hash, &lhq); + + prop = lhq.value; + + if (ret == NJS_OK) { + njs_set_invalid(&prop->value); + } + + return NJS_OK; +} + + +static njs_int_t +njs_unit_test_header_external(njs_vm_t *vm, njs_value_t *value, void *obj, + uintptr_t data) +{ + u_char *p; + uint32_t size; + njs_str_t *h; + + h = (njs_str_t *) data; + + size = 7 + h->length; + + p = njs_vm_value_string_alloc(vm, value, size); + if (p == NULL) { + return NJS_ERROR; + } + + p = njs_cpymem(p, h->start, h->length); + *p++ = '|'; + memcpy(p, "???", 6); + + return NJS_OK; +} + + +static njs_int_t +njs_unit_test_header_keys_external(njs_vm_t *vm, void *obj, njs_value_t *keys) +{ + njs_int_t rc, i; + njs_value_t *value; + u_char k[2]; + + rc = njs_vm_array_alloc(vm, keys, 4); + if (rc != NJS_OK) { + return NJS_ERROR; + } + + k[0] = '0'; + k[1] = '1'; + + for (i = 0; i < 3; i++) { + value = njs_vm_array_push(vm, keys); + if (value == NULL) { + return NJS_ERROR; + } + + (void) njs_vm_value_string_set(vm, value, k, 2); + + k[1]++; + } + + return NJS_OK; +} + + +static njs_int_t +njs_unit_test_method_external(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, + njs_index_t unused) +{ + njs_int_t ret; + njs_str_t s; + njs_unit_test_req_t *r; + + r = njs_vm_external(vm, njs_arg(args, nargs, 0)); + if (r == NULL) { + return NJS_ERROR; + } + + ret = njs_vm_value_to_string(vm, &s, njs_arg(args, nargs, 1)); + if (ret == NJS_OK && s.length == 3 && memcmp(s.start, "YES", 3) == 0) { + return njs_vm_value_string_set(vm, njs_vm_retval(vm), r->uri.start, + r->uri.length); + } + + njs_set_undefined(&vm->retval); + + return NJS_OK; +} + + +static njs_int_t +njs_unit_test_create_external(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, + njs_index_t unused) +{ + njs_int_t ret; + njs_str_t uri; + njs_value_t *value; + njs_unit_test_req_t *r, *sr; + + r = njs_vm_external(vm, njs_arg(args, nargs, 0)); + if (r == NULL) { + return NJS_ERROR; + } + + if (njs_vm_value_to_string(vm, &uri, njs_arg(args, nargs, 1)) != NJS_OK) { + return NJS_ERROR; + } + + value = njs_mp_zalloc(r->pool, sizeof(njs_opaque_value_t)); + if (value == NULL) { + goto memory_error; + } + + sr = njs_mp_zalloc(r->pool, sizeof(njs_unit_test_req_t)); + if (sr == NULL) { + goto memory_error; + } + + sr->uri = uri; + sr->pool = r->pool; + sr->proto = r->proto; + + ret = njs_vm_external_create(vm, value, sr->proto, sr); + if (ret != NJS_OK) { + return NJS_ERROR; + } + + njs_vm_retval_set(vm, value); + + return NJS_OK; + +memory_error: + + njs_memory_error(vm); + + return NJS_ERROR; +} + + +static njs_int_t +njs_unit_test_bind_external(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, + njs_index_t unused) +{ + njs_str_t name; + njs_unit_test_req_t *r; + + r = njs_vm_external(vm, njs_arg(args, nargs, 0)); + if (r == NULL) { + return NJS_ERROR; + } + + if (njs_vm_value_to_string(vm, &name, njs_arg(args, nargs, 1)) != NJS_OK) { + return NJS_ERROR; + } + + return njs_vm_bind(vm, &name, njs_arg(args, nargs, 2), 0); +} + + +static njs_external_t njs_unit_test_r_props[] = { + + { njs_str("a"), + NJS_EXTERN_PROPERTY, + NULL, + 0, + njs_unit_test_r_get_a_external, + NULL, + NULL, + NULL, + NULL, + 0 }, + + { njs_str("b"), + NJS_EXTERN_PROPERTY, + NULL, + 0, + njs_unit_test_r_get_b_external, + NULL, + NULL, + NULL, + NULL, + 42 }, +}; + + +static njs_external_t njs_unit_test_r_external[] = { + + { njs_str("uri"), + NJS_EXTERN_PROPERTY, + NULL, + 0, + njs_unit_test_r_get_uri_external, + njs_unit_test_r_set_uri_external, + NULL, + NULL, + NULL, + offsetof(njs_unit_test_req_t, uri) }, + + { njs_str("host"), + NJS_EXTERN_PROPERTY, + NULL, + 0, + njs_unit_test_host_external, + NULL, + NULL, + NULL, + NULL, + 0 }, + + { njs_str("props"), + NJS_EXTERN_OBJECT, + njs_unit_test_r_props, + njs_nitems(njs_unit_test_r_props), + NULL, + NULL, + NULL, + NULL, + NULL, + 0 }, + + { njs_str("vars"), + NJS_EXTERN_OBJECT, + NULL, + 0, + njs_unit_test_r_get_vars, + njs_unit_test_r_set_vars, + njs_unit_test_r_del_vars, + NULL, + NULL, + 0 }, + + { njs_str("consts"), + NJS_EXTERN_OBJECT, + NULL, + 0, + njs_unit_test_r_get_vars, + NULL, + NULL, + NULL, + NULL, + 0 }, + + { njs_str("header"), + NJS_EXTERN_OBJECT, + NULL, + 0, + njs_unit_test_header_external, + NULL, + NULL, + njs_unit_test_header_keys_external, + NULL, + 0 }, + + { njs_str("some_method"), + NJS_EXTERN_METHOD, + NULL, + 0, + NULL, + NULL, + NULL, + NULL, + njs_unit_test_method_external, + 0 }, + + { njs_str("create"), + NJS_EXTERN_METHOD, + NULL, + 0, + NULL, + NULL, + NULL, + NULL, + njs_unit_test_create_external, + 0 }, + + { njs_str("bind"), + NJS_EXTERN_METHOD, + NULL, + 0, + NULL, + NULL, + NULL, + NULL, + njs_unit_test_bind_external, + 0 }, + +}; + + +static njs_external_t njs_test_external[] = { + + { njs_str("request.proto"), + NJS_EXTERN_OBJECT, + njs_unit_test_r_external, + njs_nitems(njs_unit_test_r_external), + NULL, + NULL, + NULL, + NULL, + NULL, + 0 }, + +}; + + +typedef struct { + njs_str_t name; + njs_unit_test_req_t request; + njs_unit_test_prop_t props[2]; +} njs_unit_test_req_t_init_t; + + +static const njs_unit_test_req_t_init_t njs_test_requests[] = { + + { njs_str("$r"), + { + .uri = njs_str("???"), + .a = 1 + }, + { + { njs_string("p"), njs_string("pval") }, + { njs_string("p2"), njs_string("p2val") }, + } + }, + + { njs_str("$r2"), + { + .uri = njs_str("???"), + .a = 2 + }, + { + { njs_string("q"), njs_string("qval") }, + { njs_string("q2"), njs_string("q2val") }, + } + }, + + { njs_str("$r3"), + { + .uri = njs_str("abc"), + .a = 3 + }, + { + { njs_string("k"), njs_string("kval") }, + { njs_string("k2"), njs_string("k2val") }, + } + }, +}; + + +njs_int_t +njs_externals_init(njs_vm_t *vm) +{ + njs_int_t ret; + njs_uint_t i, j; + const njs_extern_t *proto; + njs_unit_test_req_t *requests; + njs_unit_test_prop_t *prop; + + proto = njs_vm_external_prototype(vm, &njs_test_external[0]); + if (njs_slow_path(proto == NULL)) { + njs_printf("njs_vm_external_prototype() failed\n"); + return NJS_ERROR; + } + + requests = njs_mp_zalloc(vm->mem_pool, njs_nitems(njs_test_requests) + * sizeof(njs_unit_test_req_t)); + if (njs_slow_path(requests == NULL)) { + return NJS_ERROR; + } + + for (i = 0; i < njs_nitems(njs_test_requests); i++) { + + requests[i] = njs_test_requests[i].request; + requests[i].pool = vm->mem_pool; + requests[i].proto = proto; + + ret = njs_vm_external_create(vm, njs_value_arg(&requests[i].value), + proto, &requests[i]); + if (njs_slow_path(ret != NJS_OK)) { + njs_printf("njs_vm_external_create() failed\n"); + return NJS_ERROR; + } + + ret = njs_vm_bind(vm, &njs_test_requests[i].name, + njs_value_arg(&requests[i].value), 1); + if (njs_slow_path(ret != NJS_OK)) { + njs_printf("njs_vm_bind() failed\n"); + return NJS_ERROR; + } + + for (j = 0; j < njs_nitems(njs_test_requests[i].props); j++) { + prop = lvlhsh_unit_test_alloc(vm->mem_pool, + &njs_test_requests[i].props[j].name, + &njs_test_requests[i].props[j].value); + + if (njs_slow_path(prop == NULL)) { + njs_printf("lvlhsh_unit_test_alloc() failed\n"); + return NJS_ERROR; + } + + ret = lvlhsh_unit_test_add(&requests[i], prop); + if (njs_slow_path(ret != NJS_OK)) { + njs_printf("lvlhsh_unit_test_add() failed\n"); + return NJS_ERROR; + } + } + } + + return NJS_OK; +} diff -r a16e0c8f4bb2 -r eb9258cfcf40 src/test/njs_externals_test.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/test/njs_externals_test.h Thu Mar 05 15:24:52 2020 +0300 @@ -0,0 +1,14 @@ + +/* + * Copyright (C) Dmitry Volyntsev + * Copyright (C) NGINX, Inc. + */ + +#ifndef _NJS_EXTERNALS_TEST_H_INCLUDED_ +#define _NJS_EXTERNALS_TEST_H_INCLUDED_ + + +njs_int_t njs_externals_init(njs_vm_t *vm); + + +#endif /* _NJS_EXTERNALS_TEST_H_INCLUDED_ */ diff -r a16e0c8f4bb2 -r eb9258cfcf40 src/test/njs_interactive_test.c --- a/src/test/njs_interactive_test.c Wed Mar 04 17:12:55 2020 +0300 +++ b/src/test/njs_interactive_test.c Thu Mar 05 15:24:52 2020 +0300 @@ -10,6 +10,8 @@ #include #include +#include "njs_externals_test.h" + typedef struct { njs_str_t script; @@ -321,6 +323,11 @@ njs_interactive_test(njs_bool_t verbose) goto done; } + ret = njs_externals_init(vm); + if (ret != NJS_OK) { + goto done; + } + start = test->script.start; last = start + test->script.length; end = NULL; diff -r a16e0c8f4bb2 -r eb9258cfcf40 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Wed Mar 04 17:12:55 2020 +0300 +++ b/src/test/njs_unit_test.c Thu Mar 05 15:24:52 2020 +0300 @@ -6,6 +6,8 @@ #include +#include "njs_externals_test.h" + #define NJS_HAVE_LARGE_STACK (!NJS_HAVE_ADDRESS_SANITIZER && !NJS_HAVE_MEMORY_SANITIZER) #define _NJS_ARRAY(sz) "Array(" njs_stringify(sz) ")" @@ -16959,678 +16961,6 @@ static njs_unit_test_t njs_regexp_test[ typedef struct { - njs_lvlhsh_t hash; - const njs_extern_t *proto; - njs_mp_t *pool; - - uint32_t a; - njs_str_t uri; - - njs_opaque_value_t value; -} njs_unit_test_req_t; - - -typedef struct { - njs_value_t name; - njs_value_t value; -} njs_unit_test_prop_t; - - -static njs_int_t -lvlhsh_unit_test_key_test(njs_lvlhsh_query_t *lhq, void *data) -{ - njs_str_t name; - njs_unit_test_prop_t *prop; - - prop = data; - njs_string_get(&prop->name, &name); - - if (name.length != lhq->key.length) { - return NJS_DECLINED; - } - - if (memcmp(name.start, lhq->key.start, lhq->key.length) == 0) { - return NJS_OK; - } - - return NJS_DECLINED; -} - - -static void * -lvlhsh_unit_test_pool_alloc(void *pool, size_t size) -{ - return njs_mp_align(pool, size, size); -} - - -static void -lvlhsh_unit_test_pool_free(void *pool, void *p, size_t size) -{ - njs_mp_free(pool, p); -} - - -static const njs_lvlhsh_proto_t lvlhsh_proto njs_aligned(64) = { - NJS_LVLHSH_LARGE_SLAB, - lvlhsh_unit_test_key_test, - lvlhsh_unit_test_pool_alloc, - lvlhsh_unit_test_pool_free, -}; - - -static njs_unit_test_prop_t * -lvlhsh_unit_test_alloc(njs_mp_t *pool, const njs_value_t *name, - const njs_value_t *value) -{ - njs_unit_test_prop_t *prop; - - prop = njs_mp_alloc(pool, sizeof(njs_unit_test_prop_t)); - if (prop == NULL) { - return NULL; - } - - prop->name = *name; - prop->value = *value; - - return prop; -} - - -static njs_int_t -lvlhsh_unit_test_add(njs_unit_test_req_t *r, njs_unit_test_prop_t *prop) -{ - njs_lvlhsh_query_t lhq; - - njs_string_get(&prop->name, &lhq.key); - lhq.key_hash = njs_djb_hash(lhq.key.start, lhq.key.length); - - lhq.replace = 1; - lhq.value = (void *) prop; - lhq.proto = &lvlhsh_proto; - lhq.pool = r->pool; - - switch (njs_lvlhsh_insert(&r->hash, &lhq)) { - - case NJS_OK: - return NJS_OK; - - case NJS_DECLINED: - default: - return NJS_ERROR; - } -} - - -static njs_int_t -njs_unit_test_r_get_uri_external(njs_vm_t *vm, njs_value_t *value, void *obj, - uintptr_t data) -{ - char *p = obj; - - njs_str_t *field; - - field = (njs_str_t *) (p + data); - - return njs_vm_value_string_set(vm, value, field->start, field->length); -} - - -static njs_int_t -njs_unit_test_r_set_uri_external(njs_vm_t *vm, void *obj, uintptr_t data, - njs_str_t *value) -{ - char *p = obj; - - njs_str_t *field; - - field = (njs_str_t *) (p + data); - - *field = *value; - - return NJS_OK; -} - - -static njs_int_t -njs_unit_test_r_get_a_external(njs_vm_t *vm, njs_value_t *value, void *obj, - uintptr_t data) -{ - u_char buf[16], *p; - njs_unit_test_req_t *r; - - r = (njs_unit_test_req_t *) obj; - - p = njs_sprintf(buf, buf + njs_length(buf), "%uD", r->a); - - return njs_vm_value_string_set(vm, value, buf, p - buf); -} - - -static njs_int_t -njs_unit_test_r_get_b_external(njs_vm_t *vm, njs_value_t *value, void *obj, - uintptr_t data) -{ - njs_value_number_set(value, data); - - return NJS_OK; -} - - -static njs_int_t -njs_unit_test_host_external(njs_vm_t *vm, njs_value_t *value, void *obj, - uintptr_t data) -{ - return njs_vm_value_string_set(vm, value, (u_char *) "???????????", 22); -} - - -static njs_int_t -njs_unit_test_r_get_vars(njs_vm_t *vm, njs_value_t *value, void *obj, - uintptr_t data) -{ - njs_int_t ret; - njs_str_t *key; - njs_lvlhsh_query_t lhq; - njs_unit_test_req_t *r; - njs_unit_test_prop_t *prop; - - r = (njs_unit_test_req_t *) obj; - key = (njs_str_t *) data; - - lhq.key = *key; - lhq.key_hash = njs_djb_hash(key->start, key->length); - lhq.proto = &lvlhsh_proto; - - ret = njs_lvlhsh_find(&r->hash, &lhq); - - prop = lhq.value; - - if (ret == NJS_OK && njs_is_valid(&prop->value)) { - *value = prop->value; - return NJS_OK; - } - - njs_value_undefined_set(value); - - return NJS_OK; -} - - -static njs_int_t -njs_unit_test_r_set_vars(njs_vm_t *vm, void *obj, uintptr_t data, - njs_str_t *value) -{ - njs_int_t ret; - njs_str_t *key; - njs_value_t name, val; - njs_unit_test_req_t *r; - njs_unit_test_prop_t *prop; - - r = (njs_unit_test_req_t *) obj; - key = (njs_str_t *) data; From xeioex at nginx.com Thu Mar 5 13:10:19 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 05 Mar 2020 13:10:19 +0000 Subject: [njs] Added externals backtrace test. Message-ID: details: https://hg.nginx.org/njs/rev/51ce6ffc3c66 branches: changeset: 1352:51ce6ffc3c66 user: Dmitry Volyntsev date: Thu Mar 05 15:24:54 2020 +0300 description: Added externals backtrace test. diffstat: src/test/njs_interactive_test.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diffs (15 lines): diff -r eb9258cfcf40 -r 51ce6ffc3c66 src/test/njs_interactive_test.c --- a/src/test/njs_interactive_test.c Thu Mar 05 15:24:52 2020 +0300 +++ b/src/test/njs_interactive_test.c Thu Mar 05 15:24:54 2020 +0300 @@ -185,6 +185,11 @@ static njs_interactive_test_t njs_test[ " at eval (native)\n" " at main (native)\n") }, + { njs_str("$r.some_method({}.a.a)" ENTER), + njs_str("TypeError: cannot get property \"a\" of undefined\n" + " at request.proto.some_method (native)\n" + " at main (native)\n") }, + { njs_str("new Function(\n\n@)" ENTER), njs_str("SyntaxError: Unexpected token \"@\" in 3") }, From xeioex at nginx.com Thu Mar 5 13:10:21 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 05 Mar 2020 13:10:21 +0000 Subject: [njs] Removed unused typedef. Message-ID: details: https://hg.nginx.org/njs/rev/cc5c687ebc1c branches: changeset: 1353:cc5c687ebc1c user: Dmitry Volyntsev date: Thu Mar 05 16:05:40 2020 +0300 description: Removed unused typedef. diffstat: src/njs_extern.h | 6 ------ 1 files changed, 0 insertions(+), 6 deletions(-) diffs (16 lines): diff -r 51ce6ffc3c66 -r cc5c687ebc1c src/njs_extern.h --- a/src/njs_extern.h Thu Mar 05 15:24:54 2020 +0300 +++ b/src/njs_extern.h Thu Mar 05 16:05:40 2020 +0300 @@ -34,12 +34,6 @@ struct njs_extern_s { }; -typedef struct { - njs_value_t value; - njs_str_t name; -} njs_extern_value_t; - - njs_array_t *njs_extern_keys_array(njs_vm_t *vm, const njs_extern_t *external); njs_int_t njs_external_match_native_function(njs_vm_t *vm, njs_function_native_t func, njs_str_t *name); From seenafallah at gmail.com Tue Mar 10 15:43:56 2020 From: seenafallah at gmail.com (Seena Fallah) Date: Tue, 10 Mar 2020 19:13:56 +0330 Subject: Fwd: RTSP request response In-Reply-To: References: Message-ID: Hi all. When we send RTSP request to NGINX, NGINX will return 400 bad request without headers and when we have loadbalancers like HAProxy in front of NGINX because of no headers, HAProxy figured out that the response from NGINX is invalid and return 502! Won't you want to send headers with the response for these types of requests? -------------- next part -------------- An HTML attachment was scrubbed... URL: From vbart at nginx.com Tue Mar 10 22:06:06 2020 From: vbart at nginx.com (Valentin V. Bartenev) Date: Wed, 11 Mar 2020 01:06:06 +0300 Subject: Fwd: RTSP request response In-Reply-To: References: Message-ID: <4550809.31r3eYUQgx@vbart-laptop> On Tuesday, 10 March 2020 18:43:56 MSK Seena Fallah wrote: > Hi all. > When we send RTSP request to NGINX, NGINX will return 400 bad request > without headers and when we have loadbalancers like HAProxy in front of > NGINX because of no headers, HAProxy figured out that the response from > NGINX is invalid and return 502! > Won't you want to send headers with the response for these types of > requests? > What nginx version do you use? If nginx fails to parse a request line, it returns a valid HTTP/1.0 response (with headers). But before nginx 1.5.5 (which was released about 7 years ago) it used HTTP/0.9 protocol to respond in this case. wbr, Valentin V. Bartenev From mdounin at mdounin.ru Wed Mar 11 12:00:58 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 11 Mar 2020 15:00:58 +0300 Subject: Fwd: RTSP request response In-Reply-To: <4550809.31r3eYUQgx@vbart-laptop> References: <4550809.31r3eYUQgx@vbart-laptop> Message-ID: <20200311120058.GF12894@mdounin.ru> Hello! On Wed, Mar 11, 2020 at 01:06:06AM +0300, Valentin V. Bartenev wrote: > On Tuesday, 10 March 2020 18:43:56 MSK Seena Fallah wrote: > > Hi all. > > When we send RTSP request to NGINX, NGINX will return 400 bad request > > without headers and when we have loadbalancers like HAProxy in front of > > NGINX because of no headers, HAProxy figured out that the response from > > NGINX is invalid and return 502! > > Won't you want to send headers with the response for these types of > > requests? > > > > What nginx version do you use? > > If nginx fails to parse a request line, it returns a valid HTTP/1.0 response > (with headers). > > But before nginx 1.5.5 (which was released about 7 years ago) it used HTTP/0.9 > protocol to respond in this case. The RTSP protocol uses requests like (quote from https://en.wikipedia.org/wiki/Real_Time_Streaming_Protocol): OPTIONS rtsp://example.com/media.mp4 RTSP/1.0 CSeq: 1 Require: implicit-play Proxy-Require: gzipped-messages This will be interpreted as HTTP/0.9 request with method "OPTIONS" and URI "rtsp://example.com/media.mp4 RTSP/1.0", and will trigger 400 due to invalid method for HTTP/0.9. Removing support for spaces in URI (as introduced in 31e9677b15a1, 0.8.41) should make the response to be interpreted as a garbage instead, leading to a HTTP/1.0 response. Since support for spaces in URI is something known to cause other issues as well (see https://trac.nginx.org/nginx/ticket/196), this might be something are willing to do. Note though that it is generally a bad idea to assume that a RTSP frequest will trigger a meaningful response from an HTTP server. -- Maxim Dounin http://mdounin.ru/ From agile6v at agile6v.com Fri Mar 13 15:29:51 2020 From: agile6v at agile6v.com (=?gb18030?B?0ru9rbS6y66jrM/ytqvB9w==?=) Date: Fri, 13 Mar 2020 23:29:51 +0800 Subject: [PATCH] Mirror directive supports variable Message-ID: # HG changeset patch # User agile6v # Date 1584110606 -28800 # Fri Mar 13 22:43:26 2020 +0800 # Node ID e4a0277cab79865fde6fefeed9374154449e6948 # Parent 4eb606b4a5b521603c23223cf8863f3999df743c mirror directive supports variable. diff -r 4eb606b4a5b5 -r e4a0277cab79 src/http/modules/ngx_http_mirror_module.c --- a/src/http/modules/ngx_http_mirror_module.c Tue Mar 03 18:04:21 2020 +0300 +++ b/src/http/modules/ngx_http_mirror_module.c Fri Mar 13 22:43:26 2020 +0800 @@ -149,17 +149,28 @@ static ngx_int_t ngx_http_mirror_handler_internal(ngx_http_request_t *r) { - ngx_str_t *name; + ngx_str_t val; ngx_uint_t i; ngx_http_request_t *sr; ngx_http_mirror_loc_conf_t *mlcf; + ngx_http_complex_value_t *pcv; mlcf = ngx_http_get_module_loc_conf(r, ngx_http_mirror_module); - name = mlcf->mirror->elts; + pcv = mlcf->mirror->elts; for (i = 0; i < mlcf->mirror->nelts; i++) { - if (ngx_http_subrequest(r, &name[i], &r->args, &sr, NULL, + if (ngx_http_complex_value(r, &pcv[i], &val) != NGX_OK) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + if (val.len == 0 + || (val.len == 3 && ngx_strncmp(val.data, "off", 3) == 0)) + { + continue; + } + + if (ngx_http_subrequest(r, &val, &r->args, &sr, NULL, NGX_HTTP_SUBREQUEST_BACKGROUND) != NGX_OK) { @@ -208,9 +219,10 @@ static char * ngx_http_mirror(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - ngx_http_mirror_loc_conf_t *mlcf = conf; - - ngx_str_t *value, *s; + ngx_http_mirror_loc_conf_t *mlcf = conf; + ngx_http_complex_value_t *pcv, cv; + ngx_http_compile_complex_value_t ccv; + ngx_str_t *value; value = cf->args->elts; @@ -227,19 +239,30 @@ return "is duplicate"; } + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = &cv; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + if (mlcf->mirror == NGX_CONF_UNSET_PTR) { - mlcf->mirror = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t)); + mlcf->mirror = ngx_array_create(cf->pool, 4, + sizeof(ngx_http_complex_value_t)); if (mlcf->mirror == NULL) { return NGX_CONF_ERROR; } } - s = ngx_array_push(mlcf->mirror); - if (s == NULL) { + pcv = ngx_array_push(mlcf->mirror); + if (pcv == NULL) { return NGX_CONF_ERROR; } - *s = value[1]; + *pcv = cv; return NGX_CONF_OK; } -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: nginx.patch Type: application/octet-stream Size: 2800 bytes Desc: not available URL: From ru at nginx.com Mon Mar 16 09:47:34 2020 From: ru at nginx.com (Ruslan Ermilov) Date: Mon, 16 Mar 2020 09:47:34 +0000 Subject: [nginx] Version bump. Message-ID: details: https://hg.nginx.org/nginx/rev/2a9aeb3426c3 branches: changeset: 7636:2a9aeb3426c3 user: Ruslan Ermilov date: Mon Mar 16 12:41:41 2020 +0300 description: Version bump. diffstat: src/core/nginx.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff -r 4eb606b4a5b5 -r 2a9aeb3426c3 src/core/nginx.h --- a/src/core/nginx.h Tue Mar 03 18:04:21 2020 +0300 +++ b/src/core/nginx.h Mon Mar 16 12:41:41 2020 +0300 @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1017009 -#define NGINX_VERSION "1.17.9" +#define nginx_version 1017010 +#define NGINX_VERSION "1.17.10" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD From ru at nginx.com Mon Mar 16 09:47:37 2020 From: ru at nginx.com (Ruslan Ermilov) Date: Mon, 16 Mar 2020 09:47:37 +0000 Subject: [nginx] Auth basic: explicitly zero out password buffer. Message-ID: details: https://hg.nginx.org/nginx/rev/0cb942c1c1aa branches: changeset: 7637:0cb942c1c1aa user: Ruslan Ermilov date: Fri Mar 13 02:12:10 2020 +0300 description: Auth basic: explicitly zero out password buffer. diffstat: src/http/modules/ngx_http_auth_basic_module.c | 37 +++++++++++++------------- 1 files changed, 18 insertions(+), 19 deletions(-) diffs (91 lines): diff -r 2a9aeb3426c3 -r 0cb942c1c1aa src/http/modules/ngx_http_auth_basic_module.c --- a/src/http/modules/ngx_http_auth_basic_module.c Mon Mar 16 12:41:41 2020 +0300 +++ b/src/http/modules/ngx_http_auth_basic_module.c Fri Mar 13 02:12:10 2020 +0300 @@ -25,7 +25,6 @@ static ngx_int_t ngx_http_auth_basic_cry ngx_str_t *passwd, ngx_str_t *realm); static ngx_int_t ngx_http_auth_basic_set_realm(ngx_http_request_t *r, ngx_str_t *realm); -static void ngx_http_auth_basic_close(ngx_file_t *file); static void *ngx_http_auth_basic_create_loc_conf(ngx_conf_t *cf); static char *ngx_http_auth_basic_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child); @@ -177,8 +176,8 @@ ngx_http_auth_basic_handler(ngx_http_req offset); if (n == NGX_ERROR) { - ngx_http_auth_basic_close(&file); - return NGX_HTTP_INTERNAL_SERVER_ERROR; + rc = NGX_HTTP_INTERNAL_SERVER_ERROR; + goto cleanup; } if (n == 0) { @@ -219,12 +218,11 @@ ngx_http_auth_basic_handler(ngx_http_req if (buf[i] == LF || buf[i] == CR || buf[i] == ':') { buf[i] = '\0'; - ngx_http_auth_basic_close(&file); - pwd.len = i - passwd; pwd.data = &buf[passwd]; - return ngx_http_auth_basic_crypt_handler(r, &pwd, &realm); + rc = ngx_http_auth_basic_crypt_handler(r, &pwd, &realm); + goto cleanup; } break; @@ -251,8 +249,6 @@ ngx_http_auth_basic_handler(ngx_http_req offset += n; } - ngx_http_auth_basic_close(&file); - if (state == sw_passwd) { pwd.len = i - passwd; pwd.data = ngx_pnalloc(r->pool, pwd.len + 1); @@ -262,14 +258,26 @@ ngx_http_auth_basic_handler(ngx_http_req ngx_cpystrn(pwd.data, &buf[passwd], pwd.len + 1); - return ngx_http_auth_basic_crypt_handler(r, &pwd, &realm); + rc = ngx_http_auth_basic_crypt_handler(r, &pwd, &realm); + goto cleanup; } ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "user \"%V\" was not found in \"%s\"", &r->headers_in.user, user_file.data); - return ngx_http_auth_basic_set_realm(r, &realm); + rc = ngx_http_auth_basic_set_realm(r, &realm); + +cleanup: + + if (ngx_close_file(file.fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, + ngx_close_file_n " \"%s\" failed", user_file.data); + } + + ngx_explicit_memzero(buf, NGX_HTTP_AUTH_BUF_SIZE); + + return rc; } @@ -338,15 +346,6 @@ ngx_http_auth_basic_set_realm(ngx_http_r return NGX_HTTP_UNAUTHORIZED; } -static void -ngx_http_auth_basic_close(ngx_file_t *file) -{ - if (ngx_close_file(file->fd) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ALERT, file->log, ngx_errno, - ngx_close_file_n " \"%s\" failed", file->name.data); - } -} - static void * ngx_http_auth_basic_create_loc_conf(ngx_conf_t *cf) From xeioex at nginx.com Tue Mar 17 18:05:37 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 17 Mar 2020 18:05:37 +0000 Subject: [njs] Fixed makefile dependency issue introduced in eb9258cfcf40. Message-ID: details: https://hg.nginx.org/njs/rev/b2bea51069fd branches: changeset: 1354:b2bea51069fd user: Dmitry Volyntsev date: Mon Mar 16 15:49:51 2020 +0300 description: Fixed makefile dependency issue introduced in eb9258cfcf40. diffstat: auto/make | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diffs (24 lines): diff -r cc5c687ebc1c -r b2bea51069fd auto/make --- a/auto/make Thu Mar 05 16:05:40 2020 +0300 +++ b/auto/make Mon Mar 16 15:49:51 2020 +0300 @@ -177,8 +177,8 @@ njs_src="src/test/njs_externals_test.c" fname=$(basename $njs_src) njs_externals_obj="test/${fname%.c}.o" njs_dep="test/${fname%.c}.dep" -njs_dep_flags=`njs_gen_dep_flags $njs_dep $fname` -njs_dep_post=`njs_gen_dep_post $njs_dep $fname` +njs_dep_flags=`njs_gen_dep_flags $njs_dep $njs_externals_obj` +njs_dep_post=`njs_gen_dep_post $njs_dep $njs_externals_obj` cat << END >> $NJS_MAKEFILE @@ -209,8 +209,8 @@ do \$(NJS_CC) -o $NJS_BUILD_DIR/$njs_bin \$(NJS_CFLAGS) \\ $NJS_LIB_AUX_CFLAGS \$(NJS_LIB_INCS) \\ $njs_dep_flags \\ + $NJS_BUILD_DIR/$njs_externals_obj \\ -Injs $njs_src $NJS_BUILD_DIR/libnjs.a \\ - $NJS_BUILD_DIR/$njs_externals_obj \\ -lm $NJS_LIBS $NJS_LIB_AUX_LIBS $njs_dep_post From xeioex at nginx.com Tue Mar 17 18:05:39 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 17 Mar 2020 18:05:39 +0000 Subject: [njs] Added benchmark tests for externals. Message-ID: details: https://hg.nginx.org/njs/rev/627def6a4630 branches: changeset: 1355:627def6a4630 user: Dmitry Volyntsev date: Tue Mar 17 18:33:25 2020 +0300 description: Added benchmark tests for externals. diffstat: src/test/njs_benchmark.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 48 insertions(+), 0 deletions(-) diffs (79 lines): diff -r b2bea51069fd -r 627def6a4630 src/test/njs_benchmark.c --- a/src/test/njs_benchmark.c Mon Mar 16 15:49:51 2020 +0300 +++ b/src/test/njs_benchmark.c Tue Mar 17 18:33:25 2020 +0300 @@ -6,6 +6,8 @@ #include +#include "njs_externals_test.h" + #include #include #include @@ -65,6 +67,11 @@ njs_benchmark_test(njs_vm_t *parent, njs goto done; } + ret = njs_externals_init(vm); + if (ret != NJS_OK) { + goto done; + } + n = test->repeat; expected = &test->result; @@ -212,6 +219,27 @@ static njs_benchmark_test_t njs_test[] njs_str("3524578"), 1 }, + { "array 64k keys", + njs_str("var arr = new Array(2**16);" + "arr.fill(1);" + "Object.keys(arr)[0]"), + njs_str("0"), + 10 }, + + { "array 64k values", + njs_str("var arr = new Array(2**16);" + "arr.fill(1);" + "Object.values(arr)[0]"), + njs_str("1"), + 10 }, + + { "array 64k entries", + njs_str("var arr = new Array(2**16);" + "arr.fill(1);" + "Object.entries(arr)[0][0]"), + njs_str("0"), + 10 }, + { "array 1M", njs_str("var arr = new Array(1000000);" "var count = 0, length = arr.length;" @@ -229,6 +257,26 @@ static njs_benchmark_test_t njs_test[] "count"), njs_str("20000000"), 1 }, + + { "external property ($r.uri)", + njs_str("$r.uri"), + njs_str("???"), + 1000 }, + + { "external object property ($r.props.a)", + njs_str("$r.props.a"), + njs_str("1"), + 1000 }, + + { "external dump (JSON.stringify($r.header))", + njs_str("JSON.stringify($r.header)"), + njs_str("{\"01\":\"01|???\",\"02\":\"02|???\",\"03\":\"03|???\"}"), + 1000 }, + + { "external method ($r.some_method('YES'))", + njs_str("$r.some_method('YES')"), + njs_str("???"), + 1000 }, }; From xeioex at nginx.com Wed Mar 18 11:55:45 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 18 Mar 2020 11:55:45 +0000 Subject: [njs] Simplifed object enumeration. Message-ID: details: https://hg.nginx.org/njs/rev/dee85b788982 branches: changeset: 1356:dee85b788982 user: Dmitry Volyntsev date: Wed Mar 18 14:50:46 2020 +0300 description: Simplifed object enumeration. diffstat: src/njs_object.c | 337 ++++++++++++++---------------------------------------- 1 files changed, 88 insertions(+), 249 deletions(-) diffs (544 lines): diff -r 627def6a4630 -r dee85b788982 src/njs_object.c --- a/src/njs_object.c Tue Mar 17 18:33:25 2020 +0300 +++ b/src/njs_object.c Wed Mar 18 14:50:46 2020 +0300 @@ -11,13 +11,6 @@ static njs_int_t njs_object_hash_test(njs_lvlhsh_query_t *lhq, void *data); static njs_object_prop_t *njs_object_exist_in_proto(const njs_object_t *begin, const njs_object_t *end, njs_lvlhsh_query_t *lhq); -static uint32_t njs_object_enumerate_array_length(const njs_object_t *object); -static uint32_t njs_object_enumerate_string_length(const njs_object_t *object); -static uint32_t njs_object_enumerate_object_length(const njs_object_t *object, - njs_object_enum_type_t type, njs_bool_t all); -static uint32_t njs_object_own_enumerate_object_length( - const njs_object_t *object, const njs_object_t *parent, - njs_object_enum_type_t type, njs_bool_t all); static njs_int_t njs_object_enumerate_array(njs_vm_t *vm, const njs_array_t *array, njs_array_t *items, njs_object_enum_t kind); static njs_int_t njs_object_enumerate_typed_array(njs_vm_t *vm, @@ -425,64 +418,6 @@ next: } -njs_inline uint32_t -njs_object_enumerate_length(const njs_object_t *object, - njs_object_enum_type_t type, njs_bool_t all) -{ - uint32_t length; - - length = njs_object_enumerate_object_length(object, type, all); - - if (type & NJS_STRING) { - switch (object->type) { - case NJS_ARRAY: - length += njs_object_enumerate_array_length(object); - break; - - case NJS_OBJECT_STRING: - length += njs_object_enumerate_string_length(object); - break; - - default: - break; - } - } - - return length; -} - - -njs_inline uint32_t -njs_object_own_enumerate_length(const njs_object_t *object, - const njs_object_t *parent, njs_object_enum_type_t type, njs_bool_t all) -{ - uint32_t length; - - length = njs_object_own_enumerate_object_length(object, parent, type, all); - - if (type & NJS_ENUM_STRING) { - switch (object->type) { - case NJS_ARRAY: - length += njs_object_enumerate_array_length(object); - break; - - case NJS_TYPED_ARRAY: - length += njs_typed_array_length((njs_typed_array_t *) object); - break; - - case NJS_OBJECT_STRING: - length += njs_object_enumerate_string_length(object); - break; - - default: - break; - } - } - - return length; -} - - njs_inline njs_int_t njs_object_enumerate_value(njs_vm_t *vm, const njs_object_t *object, njs_array_t *items, njs_object_enum_t kind, njs_object_enum_type_t type, @@ -576,13 +511,10 @@ njs_array_t * njs_object_enumerate(njs_vm_t *vm, const njs_object_t *object, njs_object_enum_t kind, njs_object_enum_type_t type, njs_bool_t all) { - uint32_t length; njs_int_t ret; njs_array_t *items; - length = njs_object_enumerate_length(object, type, all); - - items = njs_array_alloc(vm, 1, length, NJS_ARRAY_SPARE); + items = njs_array_alloc(vm, 1, 0, NJS_ARRAY_SPARE); if (njs_slow_path(items == NULL)) { return NULL; } @@ -592,8 +524,6 @@ njs_object_enumerate(njs_vm_t *vm, const return NULL; } - items->start -= items->length; - return items; } @@ -602,13 +532,10 @@ njs_array_t * njs_object_own_enumerate(njs_vm_t *vm, const njs_object_t *object, njs_object_enum_t kind, njs_object_enum_type_t type, njs_bool_t all) { - uint32_t length; njs_int_t ret; njs_array_t *items; - length = njs_object_own_enumerate_length(object, object, type, all); - - items = njs_array_alloc(vm, 1, length, NJS_ARRAY_SPARE); + items = njs_array_alloc(vm, 1, 0, NJS_ARRAY_SPARE); if (njs_slow_path(items == NULL)) { return NULL; } @@ -619,64 +546,10 @@ njs_object_own_enumerate(njs_vm_t *vm, c return NULL; } - items->start -= items->length; - return items; } -static uint32_t -njs_object_enumerate_array_length(const njs_object_t *object) -{ - uint32_t i, length; - njs_array_t *array; - - length = 0; - array = (njs_array_t *) object; - - if (object->fast_array) { - for (i = 0; i < array->length; i++) { - if (njs_is_valid(&array->start[i])) { - length++; - } - } - } - - return length; -} - - -static uint32_t -njs_object_enumerate_string_length(const njs_object_t *object) -{ - njs_object_value_t *obj_val; - - obj_val = (njs_object_value_t *) object; - - return njs_string_length(&obj_val->value); -} - - -static uint32_t -njs_object_enumerate_object_length(const njs_object_t *object, - njs_object_enum_type_t type, njs_bool_t all) -{ - uint32_t length; - const njs_object_t *proto; - - length = njs_object_own_enumerate_object_length(object, object, type, all); - - proto = object->__proto__; - - while (proto != NULL) { - length += njs_object_own_enumerate_length(proto, object, type, all); - proto = proto->__proto__; - } - - return length; -} - - njs_inline njs_bool_t njs_is_enumerable(const njs_value_t *value, njs_object_enum_type_t type) { @@ -685,136 +558,79 @@ njs_is_enumerable(const njs_value_t *val } -static uint32_t -njs_object_own_enumerate_object_length(const njs_object_t *object, - const njs_object_t *parent, njs_object_enum_type_t type, njs_bool_t all) -{ - uint32_t length; - njs_int_t ret; - njs_lvlhsh_each_t lhe; - njs_object_prop_t *prop, *ext_prop; - njs_lvlhsh_query_t lhq; - const njs_lvlhsh_t *hash; - - njs_lvlhsh_each_init(&lhe, &njs_object_hash_proto); - hash = &object->hash; - - lhq.proto = &njs_object_hash_proto; - - length = 0; - - for ( ;; ) { - prop = njs_lvlhsh_each(hash, &lhe); - - if (prop == NULL) { - break; - } - - if (!njs_is_enumerable(&prop->name, type)) { - continue; - } - - njs_object_property_key_set(&lhq, &prop->name, lhe.key_hash); - - ext_prop = njs_object_exist_in_proto(parent, object, &lhq); - - if (ext_prop == NULL && prop->type != NJS_WHITEOUT - && (prop->enumerable || all)) - { - length++; - } - } - - njs_lvlhsh_each_init(&lhe, &njs_object_hash_proto); - hash = &object->shared_hash; - - for ( ;; ) { - prop = njs_lvlhsh_each(hash, &lhe); - - if (prop == NULL) { - break; - } - - if (!njs_is_enumerable(&prop->name, type)) { - continue; - } - - njs_object_property_key_set(&lhq, &prop->name, lhe.key_hash); - - ret = njs_lvlhsh_find(&object->hash, &lhq); - - if (ret != NJS_OK) { - ext_prop = njs_object_exist_in_proto(parent, object, &lhq); - - if (ext_prop == NULL && (prop->enumerable || all)) { - length++; - } - } - } - - return length; -} - - static njs_int_t njs_object_enumerate_array(njs_vm_t *vm, const njs_array_t *array, njs_array_t *items, njs_object_enum_t kind) { - uint32_t i; - njs_value_t *item; + njs_int_t ret; + njs_value_t *p, *start, *end; njs_array_t *entry; if (!array->object.fast_array) { return NJS_OK; } - item = items->start; + start = array->start; + + p = start; + end = p + array->length; switch (kind) { case NJS_ENUM_KEYS: - for (i = 0; i < array->length; i++) { - if (njs_is_valid(&array->start[i])) { - njs_uint32_to_string(item++, i); + while (p < end) { + if (njs_is_valid(p)) { + ret = njs_array_expand(vm, items, 0, 1); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + njs_uint32_to_string(&items->start[items->length++], p - start); } + + p++; } break; case NJS_ENUM_VALUES: - for (i = 0; i < array->length; i++) { - if (njs_is_valid(&array->start[i])) { - /* GC: retain. */ - *item++ = array->start[i]; + while (p < end) { + if (njs_is_valid(p)) { + ret = njs_array_add(vm, items, p); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } } + + p++; } break; case NJS_ENUM_BOTH: - for (i = 0; i < array->length; i++) { - if (njs_is_valid(&array->start[i])) { - + while (p < end) { + if (njs_is_valid(p)) { entry = njs_array_alloc(vm, 0, 2, 0); if (njs_slow_path(entry == NULL)) { return NJS_ERROR; } - njs_uint32_to_string(&entry->start[0], i); - - /* GC: retain. */ - entry->start[1] = array->start[i]; - - njs_set_array(item, entry); - - item++; + njs_uint32_to_string(&entry->start[0], p - start); + entry->start[1] = *p; + + ret = njs_array_expand(vm, items, 0, 1); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + njs_set_array(&items->start[items->length++], entry); } + + p++; } break; } - items->start = item; - return NJS_OK; } @@ -824,12 +640,19 @@ njs_object_enumerate_typed_array(njs_vm_ njs_array_t *items, njs_object_enum_t kind) { uint32_t i, length; + njs_int_t ret; njs_value_t *item; njs_array_t *entry; - item = items->start; length = njs_typed_array_length(array); + ret = njs_array_expand(vm, items, 0, length); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + item = &items->start[items->length]; + switch (kind) { case NJS_ENUM_KEYS: for (i = 0; i < length; i++) { @@ -861,7 +684,7 @@ njs_object_enumerate_typed_array(njs_vm_ break; } - items->start = item; + items->length += length; return NJS_OK; } @@ -873,14 +696,21 @@ njs_object_enumerate_string(njs_vm_t *vm { u_char *begin; uint32_t i, len, size; + njs_int_t ret; njs_value_t *item, *string; njs_array_t *entry; const u_char *src, *end; njs_string_prop_t str_prop; - item = items->start; len = (uint32_t) njs_string_prop(&str_prop, value); + ret = njs_array_expand(vm, items, 0, len); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + item = &items->start[items->length]; + switch (kind) { case NJS_ENUM_KEYS: for (i = 0; i < len; i++) { @@ -980,7 +810,7 @@ njs_object_enumerate_string(njs_vm_t *vm break; } - items->start = item; + items->length += len; return NJS_OK; } @@ -1022,20 +852,18 @@ njs_object_own_enumerate_object(njs_vm_t njs_object_enum_type_t type, njs_bool_t all) { njs_int_t ret; - njs_value_t *item; + njs_value_t value; njs_array_t *entry; njs_lvlhsh_each_t lhe; njs_object_prop_t *prop, *ext_prop; njs_lvlhsh_query_t lhq; const njs_lvlhsh_t *hash; + lhq.proto = &njs_object_hash_proto; + njs_lvlhsh_each_init(&lhe, &njs_object_hash_proto); - - item = items->start; hash = &object->hash; - lhq.proto = &njs_object_hash_proto; - switch (kind) { case NJS_ENUM_KEYS: for ( ;; ) { @@ -1056,7 +884,10 @@ njs_object_own_enumerate_object(njs_vm_t if (ext_prop == NULL && prop->type != NJS_WHITEOUT && (prop->enumerable || all)) { - njs_string_copy(item++, &prop->name); + ret = njs_array_add(vm, items, &prop->name); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } } } @@ -1082,7 +913,10 @@ njs_object_own_enumerate_object(njs_vm_t ext_prop = njs_object_exist_in_proto(parent, object, &lhq); if (ext_prop == NULL && (prop->enumerable || all)) { - njs_string_copy(item++, &prop->name); + ret = njs_array_add(vm, items, &prop->name); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } } } } @@ -1108,8 +942,10 @@ njs_object_own_enumerate_object(njs_vm_t if (ext_prop == NULL && prop->type != NJS_WHITEOUT && (prop->enumerable || all)) { - /* GC: retain. */ - *item++ = prop->value; + ret = njs_array_add(vm, items, &prop->value); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } } } @@ -1135,7 +971,10 @@ njs_object_own_enumerate_object(njs_vm_t ext_prop = njs_object_exist_in_proto(parent, object, &lhq); if (ext_prop == NULL && (prop->enumerable || all)) { - *item++ = prop->value; + ret = njs_array_add(vm, items, &prop->value); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } } } } @@ -1167,13 +1006,14 @@ njs_object_own_enumerate_object(njs_vm_t } njs_string_copy(&entry->start[0], &prop->name); - - /* GC: retain. */ entry->start[1] = prop->value; - njs_set_array(item, entry); - - item++; + njs_set_array(&value, entry); + + ret = njs_array_add(vm, items, &value); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } } } @@ -1205,13 +1045,14 @@ njs_object_own_enumerate_object(njs_vm_t } njs_string_copy(&entry->start[0], &prop->name); - - /* GC: retain. */ entry->start[1] = prop->value; - njs_set_array(item, entry); - - item++; + njs_set_array(&value, entry); + + ret = njs_array_add(vm, items, &value); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } } } } @@ -1219,8 +1060,6 @@ njs_object_own_enumerate_object(njs_vm_t break; } - items->start = item; - return NJS_OK; } From xeioex at nginx.com Wed Mar 18 15:30:04 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 18 Mar 2020 15:30:04 +0000 Subject: [njs] Stream: fixed typo in the log message introduced in bbec3cdb747b. Message-ID: details: https://hg.nginx.org/njs/rev/224494c53bbf branches: changeset: 1357:224494c53bbf user: Dmitry Volyntsev date: Wed Mar 18 18:29:17 2020 +0300 description: Stream: fixed typo in the log message introduced in bbec3cdb747b. diffstat: nginx/ngx_stream_js_module.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r dee85b788982 -r 224494c53bbf nginx/ngx_stream_js_module.c --- a/nginx/ngx_stream_js_module.c Wed Mar 18 14:50:46 2020 +0300 +++ b/nginx/ngx_stream_js_module.c Wed Mar 18 18:29:17 2020 +0300 @@ -411,7 +411,7 @@ ngx_stream_js_phase_handler(ngx_stream_s c = s->connection; ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, - "http js phase call \"%V\"", name); + "stream js phase call \"%V\"", name); ctx = ngx_stream_get_module_ctx(s, ngx_stream_js_module); From xeioex at nginx.com Fri Mar 20 14:56:40 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 20 Mar 2020 14:56:40 +0000 Subject: [njs] Refactored externals. Message-ID: details: https://hg.nginx.org/njs/rev/573d264cb7e7 branches: changeset: 1358:573d264cb7e7 user: Dmitry Volyntsev date: Fri Mar 20 17:33:06 2020 +0300 description: Refactored externals. This closes #16 issue on Github. diffstat: nginx/ngx_http_js_module.c | 1115 +++++++++++++++++++------------------- nginx/ngx_stream_js_module.c | 473 +++++++--------- src/njs.h | 122 +++- src/njs_array.c | 5 +- src/njs_array.h | 5 +- src/njs_array_buffer.c | 1 + src/njs_crypto.c | 1 + src/njs_date.c | 1 + src/njs_error.c | 2 + src/njs_extern.c | 529 ++++++++--------- src/njs_extern.h | 45 - src/njs_function.c | 2 +- src/njs_function.h | 2 +- src/njs_json.c | 17 +- src/njs_main.h | 1 - src/njs_module.c | 1 + src/njs_object.c | 9 +- src/njs_object_prop.c | 32 +- src/njs_promise.c | 1 + src/njs_regexp.c | 1 + src/njs_shell.c | 185 ++--- src/njs_symbol.h | 19 - src/njs_value.c | 225 +------ src/njs_value.h | 74 +- src/njs_vm.c | 41 +- src/njs_vm.h | 11 - src/test/njs_benchmark.c | 45 +- src/test/njs_externals_test.c | 705 +++++++++++++----------- src/test/njs_externals_test.h | 3 +- src/test/njs_interactive_test.c | 6 +- src/test/njs_unit_test.c | 535 +++++++++++------- test/njs_expect_test.exp | 26 +- 32 files changed, 2120 insertions(+), 2120 deletions(-) diffs (truncated from 6020 to 1000 lines): diff -r 224494c53bbf -r 573d264cb7e7 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Wed Mar 18 18:29:17 2020 +0300 +++ b/nginx/ngx_http_js_module.c Fri Mar 20 17:33:06 2020 +0300 @@ -13,34 +13,34 @@ typedef struct { - njs_vm_t *vm; - ngx_array_t *paths; - const njs_extern_t *req_proto; + njs_vm_t *vm; + ngx_array_t *paths; + njs_external_proto_t req_proto; } ngx_http_js_main_conf_t; typedef struct { - ngx_str_t content; + ngx_str_t content; } ngx_http_js_loc_conf_t; typedef struct { - njs_vm_t *vm; - ngx_log_t *log; - ngx_uint_t done; - ngx_int_t status; - njs_opaque_value_t request; - njs_opaque_value_t request_body; - ngx_str_t redirect_uri; - njs_opaque_value_t promise_callbacks[2]; + njs_vm_t *vm; + ngx_log_t *log; + ngx_uint_t done; + ngx_int_t status; + njs_opaque_value_t request; + njs_opaque_value_t request_body; + ngx_str_t redirect_uri; + njs_opaque_value_t promise_callbacks[2]; } ngx_http_js_ctx_t; typedef struct { - ngx_http_request_t *request; - njs_vm_event_t vm_event; - void *unused; - ngx_int_t ident; + ngx_http_request_t *request; + njs_vm_event_t vm_event; + void *unused; + ngx_int_t ident; } ngx_http_js_event_t; @@ -55,24 +55,20 @@ static ngx_int_t ngx_http_js_init_vm(ngx static void ngx_http_js_cleanup_ctx(void *data); static void ngx_http_js_cleanup_vm(void *data); -static njs_int_t ngx_http_js_ext_get_string(njs_vm_t *vm, njs_value_t *value, - void *obj, uintptr_t data); -static njs_int_t ngx_http_js_ext_keys_header(njs_vm_t *vm, void *obj, +static njs_int_t ngx_http_js_ext_get_string(njs_vm_t *vm, + njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); +static njs_int_t ngx_http_js_ext_keys_header(njs_vm_t *vm, njs_value_t *value, njs_value_t *keys, uintptr_t data); static ngx_table_elt_t *ngx_http_js_get_header(ngx_list_part_t *part, u_char *data, size_t len); -static njs_int_t ngx_http_js_ext_get_header_out(njs_vm_t *vm, - njs_value_t *value, void *obj, uintptr_t data); -static njs_int_t ngx_http_js_ext_set_header_out(njs_vm_t *vm, void *obj, - uintptr_t data, njs_str_t *value); -static njs_int_t ngx_http_js_ext_delete_header_out(njs_vm_t *vm, void *obj, - uintptr_t data, njs_bool_t delete); -static njs_int_t ngx_http_js_ext_keys_header_out(njs_vm_t *vm, void *obj, - njs_value_t *keys); /*FIXME*/ -static njs_int_t ngx_http_js_ext_get_status(njs_vm_t *vm, njs_value_t *value, - void *obj, uintptr_t data); -static njs_int_t ngx_http_js_ext_set_status(njs_vm_t *vm, void *obj, - uintptr_t data, njs_str_t *value); +static njs_int_t ngx_http_js_ext_header_out(njs_vm_t *vm, + njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); +static njs_int_t ngx_http_js_ext_keys_header_out(njs_vm_t *vm, + njs_value_t *value, njs_value_t *keys); +static njs_int_t ngx_http_js_ext_status(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_http_js_ext_send_header(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused); static njs_int_t ngx_http_js_ext_send(njs_vm_t *vm, njs_value_t *args, @@ -85,32 +81,30 @@ static njs_int_t ngx_http_js_ext_interna njs_value_t *args, njs_uint_t nargs, njs_index_t unused); static njs_int_t ngx_http_js_ext_log(njs_vm_t *vm, njs_value_t *args, - njs_uint_t nargs, njs_index_t unused); -static njs_int_t ngx_http_js_ext_warn(njs_vm_t *vm, njs_value_t *args, - njs_uint_t nargs, njs_index_t unused); -static njs_int_t ngx_http_js_ext_error(njs_vm_t *vm, njs_value_t *args, - njs_uint_t nargs, njs_index_t unused); -static njs_int_t ngx_http_js_ext_log_core(njs_vm_t *vm, njs_value_t *args, - njs_uint_t nargs, ngx_uint_t level); + njs_uint_t nargs, njs_index_t level); static njs_int_t ngx_http_js_ext_get_http_version(njs_vm_t *vm, - njs_value_t *value, void *obj, uintptr_t data); + njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); static njs_int_t ngx_http_js_ext_get_remote_address(njs_vm_t *vm, - njs_value_t *value, void *obj, uintptr_t data); + njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); static njs_int_t ngx_http_js_ext_get_request_body(njs_vm_t *vm, - njs_value_t *value, void *obj, uintptr_t data); -static njs_int_t ngx_http_js_ext_get_header_in(njs_vm_t *vm, njs_value_t *value, - void *obj, uintptr_t data); -static njs_int_t ngx_http_js_ext_keys_header_in(njs_vm_t *vm, void *obj, - njs_value_t *keys); /*FIXME*/ -static njs_int_t ngx_http_js_ext_get_arg(njs_vm_t *vm, njs_value_t *value, - void *obj, uintptr_t data); -static njs_int_t ngx_http_js_ext_keys_arg(njs_vm_t *vm, void *obj, + njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); +static njs_int_t ngx_http_js_ext_get_header_in(njs_vm_t *vm, + njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); +static njs_int_t ngx_http_js_ext_keys_header_in(njs_vm_t *vm, + njs_value_t *value, njs_value_t *keys); +static njs_int_t ngx_http_js_ext_get_arg(njs_vm_t *vm, + njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); +static njs_int_t ngx_http_js_ext_keys_arg(njs_vm_t *vm, njs_value_t *value, njs_value_t *keys); -static njs_int_t ngx_http_js_ext_get_variable(njs_vm_t *vm, njs_value_t *value, - void *obj, uintptr_t data); -static njs_int_t ngx_http_js_ext_set_variable(njs_vm_t *vm, void *obj, - uintptr_t data, njs_str_t *value); +static njs_int_t ngx_http_js_ext_variables(njs_vm_t *vm, + njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); static njs_int_t ngx_http_js_ext_subrequest(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused); static ngx_int_t ngx_http_js_subrequest(ngx_http_request_t *r, @@ -118,10 +112,12 @@ static ngx_int_t ngx_http_js_subrequest( ngx_http_request_t **sr); static ngx_int_t ngx_http_js_subrequest_done(ngx_http_request_t *r, void *data, ngx_int_t rc); -static njs_int_t ngx_http_js_ext_get_parent(njs_vm_t *vm, njs_value_t *value, - void *obj, uintptr_t data); -static njs_int_t ngx_http_js_ext_get_reply_body(njs_vm_t *vm, - njs_value_t *value, void *obj, uintptr_t data); +static njs_int_t ngx_http_js_ext_get_parent(njs_vm_t *vm, + njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); +static njs_int_t ngx_http_js_ext_get_response_body(njs_vm_t *vm, + njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); static njs_host_event_t ngx_http_js_set_timer(njs_external_ptr_t external, uint64_t delay, njs_vm_event_t vm_event); @@ -211,251 +207,234 @@ ngx_module_t ngx_http_js_module = { static njs_external_t ngx_http_js_ext_request[] = { - { njs_str("uri"), - NJS_EXTERN_PROPERTY, - NULL, - 0, - ngx_http_js_ext_get_string, - NULL, - NULL, - NULL, - NULL, - offsetof(ngx_http_request_t, uri) }, - - { njs_str("method"), - NJS_EXTERN_PROPERTY, - NULL, - 0, - ngx_http_js_ext_get_string, - NULL, - NULL, - NULL, - NULL, - offsetof(ngx_http_request_t, method_name) }, - - { njs_str("httpVersion"), - NJS_EXTERN_PROPERTY, - NULL, - 0, - ngx_http_js_ext_get_http_version, - NULL, - NULL, - NULL, - NULL, - 0 }, - - { njs_str("remoteAddress"), - NJS_EXTERN_PROPERTY, - NULL, - 0, - ngx_http_js_ext_get_remote_address, - NULL, - NULL, - NULL, - NULL, - 0 }, - - { njs_str("parent"), - NJS_EXTERN_PROPERTY, - NULL, - 0, - ngx_http_js_ext_get_parent, - NULL, - NULL, - NULL, - NULL, - 0 }, - - { njs_str("requestBody"), - NJS_EXTERN_PROPERTY, - NULL, - 0, - ngx_http_js_ext_get_request_body, - NULL, - NULL, - NULL, - NULL, - 0 }, - - { njs_str("responseBody"), - NJS_EXTERN_PROPERTY, - NULL, - 0, - ngx_http_js_ext_get_reply_body, - NULL, - NULL, - NULL, - NULL, - 0 }, - - { njs_str("headersIn"), - NJS_EXTERN_OBJECT, - NULL, - 0, - ngx_http_js_ext_get_header_in, - NULL, - NULL, - ngx_http_js_ext_keys_header_in, - NULL, - 0 }, - - { njs_str("args"), - NJS_EXTERN_OBJECT, - NULL, - 0, - ngx_http_js_ext_get_arg, - NULL, - NULL, - ngx_http_js_ext_keys_arg, - NULL, - 0 }, - - { njs_str("variables"), - NJS_EXTERN_OBJECT, - NULL, - 0, - ngx_http_js_ext_get_variable, - ngx_http_js_ext_set_variable, - NULL, - NULL, - NULL, - 0 }, - - { njs_str("status"), - NJS_EXTERN_PROPERTY, - NULL, - 0, - ngx_http_js_ext_get_status, - ngx_http_js_ext_set_status, - NULL, - NULL, - NULL, - 0 }, - - { njs_str("headersOut"), - NJS_EXTERN_OBJECT, - NULL, - 0, - ngx_http_js_ext_get_header_out, - ngx_http_js_ext_set_header_out, - ngx_http_js_ext_delete_header_out, - ngx_http_js_ext_keys_header_out, - NULL, - 0 }, - - { njs_str("subrequest"), - NJS_EXTERN_METHOD, - NULL, - 0, - NULL, - NULL, - NULL, - NULL, - ngx_http_js_ext_subrequest, - 0 }, - - { njs_str("log"), - NJS_EXTERN_METHOD, - NULL, - 0, - NULL, - NULL, - NULL, - NULL, - ngx_http_js_ext_log, - 0 }, - - { njs_str("warn"), - NJS_EXTERN_METHOD, - NULL, - 0, - NULL, - NULL, - NULL, - NULL, - ngx_http_js_ext_warn, - 0 }, - - { njs_str("error"), - NJS_EXTERN_METHOD, - NULL, - 0, - NULL, - NULL, - NULL, - NULL, - ngx_http_js_ext_error, - 0 }, - - { njs_str("sendHeader"), - NJS_EXTERN_METHOD, - NULL, - 0, - NULL, - NULL, - NULL, - NULL, - ngx_http_js_ext_send_header, - 0 }, - - { njs_str("send"), - NJS_EXTERN_METHOD, - NULL, - 0, - NULL, - NULL, - NULL, - NULL, - ngx_http_js_ext_send, - 0 }, - - { njs_str("finish"), - NJS_EXTERN_METHOD, - NULL, - 0, - NULL, - NULL, - NULL, - NULL, - ngx_http_js_ext_finish, - 0 }, - - { njs_str("return"), - NJS_EXTERN_METHOD, - NULL, - 0, - NULL, - NULL, - NULL, - NULL, - ngx_http_js_ext_return, - 0 }, - - { njs_str("internalRedirect"), - NJS_EXTERN_METHOD, - NULL, - 0, - NULL, - NULL, - NULL, - NULL, - ngx_http_js_ext_internal_redirect, - 0 }, -}; - - -static njs_external_t ngx_http_js_externals[] = { - - { njs_str("request"), - NJS_EXTERN_OBJECT, - ngx_http_js_ext_request, - njs_nitems(ngx_http_js_ext_request), - NULL, - NULL, - NULL, - NULL, - NULL, - 0 }, + { + .flags = NJS_EXTERN_PROPERTY | NJS_EXTERN_SYMBOL, + .name.symbol = NJS_SYMBOL_TO_STRING_TAG, + .u.property = { + .value = "Request", + } + }, + + { + .flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("uri"), + .enumerable = 1, + .u.property = { + .handler = ngx_http_js_ext_get_string, + .magic32 = offsetof(ngx_http_request_t, uri), + } + }, + + { + .flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("method"), + .enumerable = 1, + .u.property = { + .handler = ngx_http_js_ext_get_string, + .magic32 = offsetof(ngx_http_request_t, method_name), + } + }, + + { + .flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("httpVersion"), + .enumerable = 1, + .u.property = { + .handler = ngx_http_js_ext_get_http_version, + } + }, + + { + .flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("remoteAddress"), + .enumerable = 1, + .u.property = { + .handler = ngx_http_js_ext_get_remote_address, + } + }, + + { + .flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("requestBody"), + .enumerable = 1, + .u.property = { + .handler = ngx_http_js_ext_get_request_body, + } + }, + + { + .flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("parent"), + .u.property = { + .handler = ngx_http_js_ext_get_parent, + } + }, + + { + .flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("responseBody"), + .enumerable = 1, + .u.property = { + .handler = ngx_http_js_ext_get_response_body, + } + }, + + { + .flags = NJS_EXTERN_OBJECT, + .name.string = njs_str("headersIn"), + .enumerable = 1, + .u.object = { + .enumerable = 1, + .prop_handler = ngx_http_js_ext_get_header_in, + .keys = ngx_http_js_ext_keys_header_in, + } + }, + + { + .flags = NJS_EXTERN_OBJECT, + .name.string = njs_str("args"), + .enumerable = 1, + .u.object = { + .enumerable = 1, + .prop_handler = ngx_http_js_ext_get_arg, + .keys = ngx_http_js_ext_keys_arg, + } + }, + + { + .flags = NJS_EXTERN_OBJECT, + .name.string = njs_str("variables"), + .u.object = { + .writable = 1, + .prop_handler = ngx_http_js_ext_variables, + } + }, + + { + .flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("status"), + .writable = 1, + .enumerable = 1, + .u.property = { + .handler = ngx_http_js_ext_status, + } + }, + + { + .flags = NJS_EXTERN_OBJECT, + .name.string = njs_str("headersOut"), + .enumerable = 1, + .u.object = { + .writable = 1, + .configurable = 1, + .enumerable = 1, + .prop_handler = ngx_http_js_ext_header_out, + .keys = ngx_http_js_ext_keys_header_out, + } + }, + + { + .flags = NJS_EXTERN_METHOD, + .name.string = njs_str("subrequest"), + .writable = 1, + .configurable = 1, + .enumerable = 1, + .u.method = { + .native = ngx_http_js_ext_subrequest, + } + }, + + { + .flags = NJS_EXTERN_METHOD, + .name.string = njs_str("log"), + .writable = 1, + .configurable = 1, + .enumerable = 1, + .u.method = { + .native = ngx_http_js_ext_log, + .magic8 = NGX_LOG_INFO, + } + }, + + { + .flags = NJS_EXTERN_METHOD, + .name.string = njs_str("warn"), + .writable = 1, + .configurable = 1, + .enumerable = 1, + .u.method = { + .native = ngx_http_js_ext_log, + .magic8 = NGX_LOG_WARN, + } + }, + + { + .flags = NJS_EXTERN_METHOD, + .name.string = njs_str("error"), + .writable = 1, + .configurable = 1, + .enumerable = 1, + .u.method = { + .native = ngx_http_js_ext_log, + .magic8 = NGX_LOG_ERR, + } + }, + + { + .flags = NJS_EXTERN_METHOD, + .name.string = njs_str("sendHeader"), + .writable = 1, + .configurable = 1, + .enumerable = 1, + .u.method = { + .native = ngx_http_js_ext_send_header, + } + }, + + { + .flags = NJS_EXTERN_METHOD, + .name.string = njs_str("send"), + .writable = 1, + .configurable = 1, + .enumerable = 1, + .u.method = { + .native = ngx_http_js_ext_send, + } + }, + + { + .flags = NJS_EXTERN_METHOD, + .name.string = njs_str("finish"), + .writable = 1, + .configurable = 1, + .enumerable = 1, + .u.method = { + .native = ngx_http_js_ext_finish, + } + }, + + { + .flags = NJS_EXTERN_METHOD, + .name.string = njs_str("return"), + .writable = 1, + .configurable = 1, + .enumerable = 1, + .u.method = { + .native = ngx_http_js_ext_return, + } + }, + + { + .flags = NJS_EXTERN_METHOD, + .name.string = njs_str("internalRedirect"), + .writable = 1, + .configurable = 1, + .enumerable = 1, + .u.method = { + .native = ngx_http_js_ext_internal_redirect, + } + }, + }; @@ -745,7 +724,7 @@ ngx_http_js_init_vm(ngx_http_request_t * } rc = njs_vm_external_create(ctx->vm, njs_value_arg(&ctx->request), - jmcf->req_proto, r); + jmcf->req_proto, r, 0); if (rc != NJS_OK) { return NGX_ERROR; } @@ -777,29 +756,32 @@ ngx_http_js_cleanup_vm(void *data) static njs_int_t -ngx_http_js_ext_get_string(njs_vm_t *vm, njs_value_t *value, void *obj, - uintptr_t data) +ngx_http_js_ext_get_string(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { - char *p = obj; - + char *p; ngx_str_t *field; - field = (ngx_str_t *) (p + data); - - return njs_vm_value_string_set(vm, value, field->data, field->len); + p = njs_vm_external(vm, value); + if (p == NULL) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } + + field = (ngx_str_t *) (p + njs_vm_prop_magic32(prop)); + + return njs_vm_value_string_set(vm, retval, field->data, field->len); } static njs_int_t -ngx_http_js_ext_keys_header(njs_vm_t *vm, void *obj, njs_value_t *keys, +ngx_http_js_ext_keys_header(njs_vm_t *vm, njs_value_t *value, njs_value_t *keys, uintptr_t data) { - char *p = obj; - + char *p; njs_int_t rc, cookie, x_for; ngx_uint_t item; ngx_list_t *headers; - njs_value_t *value; ngx_list_part_t *part; ngx_table_elt_t *header, *h; @@ -808,6 +790,11 @@ ngx_http_js_ext_keys_header(njs_vm_t *vm return NJS_ERROR; } + p = njs_vm_external(vm, value); + if (p == NULL) { + return NJS_OK; + } + headers = (ngx_list_t *) (p + data); part = &headers->part; item = 0; @@ -903,78 +890,96 @@ ngx_http_js_get_header(ngx_list_part_t * static njs_int_t -ngx_http_js_ext_get_header_out(njs_vm_t *vm, njs_value_t *value, void *obj, - uintptr_t data) +ngx_http_js_ext_header_out(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { u_char *p, *start; - njs_str_t *v; + njs_int_t rc; + ngx_int_t n; + njs_str_t *v, s, name; ngx_str_t *hdr; ngx_table_elt_t *h; ngx_http_request_t *r; u_char content_len[NGX_OFF_T_LEN]; - r = (ngx_http_request_t *) obj; - v = (njs_str_t *) data; + r = njs_vm_external(vm, value); + if (r == NULL) { + if (retval != NULL) { + njs_value_undefined_set(retval); + } + + return NJS_DECLINED; + } + + rc = njs_vm_prop_name(vm, prop, &name); + if (rc != NJS_OK) { + if (retval != NULL) { + njs_value_undefined_set(retval); + } + + return NJS_DECLINED; + } + + v = &name; + + if (retval != NULL && setval == NULL) { + if (v->length == njs_length("Content-Type") + && ngx_strncasecmp(v->start, (u_char *) "Content-Type", + v->length) == 0) + { + hdr = &r->headers_out.content_type; + return njs_vm_value_string_set(vm, retval, hdr->data, hdr->len); + } + + if (v->length == njs_length("Content-Length") + && ngx_strncasecmp(v->start, (u_char *) "Content-Length", + v->length) == 0) + { + if (r->headers_out.content_length == NULL + && r->headers_out.content_length_n >= 0) + { + p = ngx_sprintf(content_len, "%O", + r->headers_out.content_length_n); + + start = njs_vm_value_string_alloc(vm, retval, p - content_len); + if (start == NULL) { + return NJS_ERROR; + } + + ngx_memcpy(start, content_len, p - content_len); + + return NJS_OK; + } + } + + h = ngx_http_js_get_header(&r->headers_out.headers.part, v->start, + v->length); + if (h == NULL) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } + + return njs_vm_value_string_set(vm, retval, h->value.data, h->value.len); + } + + if (setval != NULL) { + rc = ngx_http_js_string(vm, setval, &s); + if (rc != NJS_OK) { + return NJS_ERROR; + } + + } else { + s.length = 0; + s.start = NULL; + } if (v->length == njs_length("Content-Type") && ngx_strncasecmp(v->start, (u_char *) "Content-Type", v->length) == 0) { - hdr = &r->headers_out.content_type; - return njs_vm_value_string_set(vm, value, hdr->data, hdr->len); - } - - if (v->length == njs_length("Content-Length") - && ngx_strncasecmp(v->start, (u_char *) "Content-Length", - v->length) == 0) - { - if (r->headers_out.content_length == NULL - && r->headers_out.content_length_n >= 0) - { - p = ngx_sprintf(content_len, "%O", r->headers_out.content_length_n); - - start = njs_vm_value_string_alloc(vm, value, p - content_len); - if (start == NULL) { - return NJS_ERROR; - } - - ngx_memcpy(start, content_len, p - content_len); - - return NJS_OK; - } - } - - h = ngx_http_js_get_header(&r->headers_out.headers.part, v->start, - v->length); - if (h == NULL) { - njs_value_undefined_set(value); - return NJS_OK; - } - - return njs_vm_value_string_set(vm, value, h->value.data, h->value.len); -} - - -static njs_int_t -ngx_http_js_ext_set_header_out(njs_vm_t *vm, void *obj, uintptr_t data, - njs_str_t *value) -{ - u_char *p; - ngx_int_t n; - njs_str_t *v; - ngx_table_elt_t *h; - ngx_http_request_t *r; - - r = (ngx_http_request_t *) obj; - v = (njs_str_t *) data; - - if (v->length == njs_length("Content-Type") - && ngx_strncasecmp(v->start, (u_char *) "Content-Type", - v->length) == 0) - { - r->headers_out.content_type.len = value->length; + r->headers_out.content_type.len = s.length; r->headers_out.content_type_len = r->headers_out.content_type.len; - r->headers_out.content_type.data = value->start; + r->headers_out.content_type.data = s.start; r->headers_out.content_type_lowcase = NULL; return NJS_OK; @@ -983,12 +988,12 @@ ngx_http_js_ext_set_header_out(njs_vm_t h = ngx_http_js_get_header(&r->headers_out.headers.part, v->start, v->length); - if (h != NULL && value->length == 0) { + if (h != NULL && s.length == 0) { h->hash = 0; h = NULL; } - if (h == NULL && value->length != 0) { + if (h == NULL && s.length != 0) { h = ngx_list_push(&r->headers_out.headers); if (h == NULL) { return NJS_ERROR; @@ -1006,15 +1011,15 @@ ngx_http_js_ext_set_header_out(njs_vm_t } if (h != NULL) { - p = ngx_pnalloc(r->pool, value->length); + p = ngx_pnalloc(r->pool, s.length); if (p == NULL) { return NJS_ERROR; } - ngx_memcpy(p, value->start, value->length); + ngx_memcpy(p, s.start, s.length); h->value.data = p; - h->value.len = value->length; + h->value.len = s.length; h->hash = 1; } @@ -1030,7 +1035,7 @@ ngx_http_js_ext_set_header_out(njs_vm_t v->length) == 0) { if (h != NULL) { - n = ngx_atoi(value->start, value->length); + n = ngx_atoi(s.start, s.length); if (n == NGX_ERROR) { h->hash = 0; njs_vm_error(vm, "failed converting argument to integer"); @@ -1050,53 +1055,44 @@ ngx_http_js_ext_set_header_out(njs_vm_t static njs_int_t -ngx_http_js_ext_delete_header_out(njs_vm_t *vm, void *obj, uintptr_t data, - njs_bool_t unused) +ngx_http_js_ext_keys_header_out(njs_vm_t *vm, njs_value_t *value, + njs_value_t *keys) { - njs_str_t value; - - value = njs_str_value(""); - - return ngx_http_js_ext_set_header_out(vm, obj, data, &value); -} - - -static njs_int_t -ngx_http_js_ext_keys_header_out(njs_vm_t *vm, void *obj, njs_value_t *keys) -{ - return ngx_http_js_ext_keys_header(vm, obj, keys, + return ngx_http_js_ext_keys_header(vm, value, keys, offsetof(ngx_http_request_t, headers_out.headers)); } static njs_int_t -ngx_http_js_ext_get_status(njs_vm_t *vm, njs_value_t *value, void *obj, - uintptr_t data) +ngx_http_js_ext_status(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) { + njs_int_t rc; + ngx_int_t n; + njs_str_t s; ngx_http_request_t *r; - r = (ngx_http_request_t *) obj; - - njs_value_number_set(value, r->headers_out.status); - - return NJS_OK; -} - - -static njs_int_t -ngx_http_js_ext_set_status(njs_vm_t *vm, void *obj, uintptr_t data, - njs_str_t *value) -{ - ngx_int_t n; - ngx_http_request_t *r; - - n = ngx_atoi(value->start, value->length); + r = njs_vm_external(vm, value); + if (r == NULL) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } + + if (setval == NULL) { + njs_value_number_set(retval, r->headers_out.status); + return NJS_OK; + } + + rc = ngx_http_js_string(vm, setval, &s); + if (rc != NJS_OK) { + return NJS_ERROR; + } + + n = ngx_atoi(s.start, s.length); if (n == NGX_ERROR) { return NJS_ERROR; } - r = (ngx_http_request_t *) obj; - r->headers_out.status = n; return NJS_OK; @@ -1110,7 +1106,8 @@ ngx_http_js_ext_send_header(njs_vm_t *vm ngx_http_request_t *r; r = njs_vm_external(vm, njs_arg(args, nargs, 0)); - if (njs_slow_path(r == NULL)) { + if (r == NULL) { + njs_vm_error(vm, "\"this\" is not an external"); return NJS_ERROR; } @@ -1139,7 +1136,8 @@ ngx_http_js_ext_send(njs_vm_t *vm, njs_v ngx_http_request_t *r; r = njs_vm_external(vm, njs_arg(args, nargs, 0)); - if (njs_slow_path(r == NULL)) { + if (r == NULL) { + njs_vm_error(vm, "\"this\" is not an external"); return NJS_ERROR; From xeioex at nginx.com Fri Mar 20 14:56:43 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 20 Mar 2020 14:56:43 +0000 Subject: [njs] HTTP: returning undefined value when "responseBody" is unavailable. Message-ID: details: https://hg.nginx.org/njs/rev/83c9c195a8e2 branches: changeset: 1359:83c9c195a8e2 user: Dmitry Volyntsev date: Fri Mar 20 17:33:10 2020 +0300 description: HTTP: returning undefined value when "responseBody" is unavailable. Missed in b758915e2406. diffstat: nginx/ngx_http_js_module.c | 7 ++++++- 1 files changed, 6 insertions(+), 1 deletions(-) diffs (17 lines): diff -r 573d264cb7e7 -r 83c9c195a8e2 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Fri Mar 20 17:33:06 2020 +0300 +++ b/nginx/ngx_http_js_module.c Fri Mar 20 17:33:10 2020 +0300 @@ -2196,7 +2196,12 @@ ngx_http_js_ext_get_response_body(njs_vm b = r->out ? r->out->buf : NULL; - len = b ? b->last - b->pos : 0; + if (b == NULL) { + njs_value_undefined_set(retval); + return NJS_OK; + } + + len = b->last - b->pos; p = njs_vm_value_string_alloc(vm, retval, len); if (p == NULL) { From xeioex at nginx.com Fri Mar 20 14:56:44 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 20 Mar 2020 14:56:44 +0000 Subject: [njs] Removed outdated commentary after ccfa84cea2b3. Message-ID: details: https://hg.nginx.org/njs/rev/9b20edb591c4 branches: changeset: 1360:9b20edb591c4 user: Dmitry Volyntsev date: Fri Mar 20 17:33:10 2020 +0300 description: Removed outdated commentary after ccfa84cea2b3. diffstat: src/njs_value.c | 3 --- 1 files changed, 0 insertions(+), 3 deletions(-) diffs (13 lines): diff -r 83c9c195a8e2 -r 9b20edb591c4 src/njs_value.c --- a/src/njs_value.c Fri Mar 20 17:33:10 2020 +0300 +++ b/src/njs_value.c Fri Mar 20 17:33:10 2020 +0300 @@ -486,9 +486,6 @@ njs_value_is_function(const njs_value_t * if pq->lhq.value != NULL it contains retval of type * njs_object_prop_t * where prop->type is NJS_WHITEOUT * NJS_ERROR exception has been thrown. - * - * TODO: - * Object.defineProperty([1,2], '1', {configurable:false}) */ njs_int_t From xeioex at nginx.com Mon Mar 23 14:16:07 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 23 Mar 2020 14:16:07 +0000 Subject: [njs] Lexer: fixed handling of no-newline at the end of the script. Message-ID: details: https://hg.nginx.org/njs/rev/603a21fabf8d branches: changeset: 1361:603a21fabf8d user: Dmitry Volyntsev date: Mon Mar 23 17:15:46 2020 +0300 description: Lexer: fixed handling of no-newline at the end of the script. diffstat: src/njs_lexer.c | 4 +--- src/njs_shell.c | 13 ++++++++++--- src/test/njs_unit_test.c | 26 ++++++++++++++++++-------- 3 files changed, 29 insertions(+), 14 deletions(-) diffs (106 lines): diff -r 9b20edb591c4 -r 603a21fabf8d src/njs_lexer.c --- a/src/njs_lexer.c Fri Mar 20 17:33:10 2020 +0300 +++ b/src/njs_lexer.c Mon Mar 23 17:15:46 2020 +0300 @@ -903,13 +903,11 @@ njs_lexer_division(njs_lexer_t *lexer, n c = lexer->start[0]; if (c == '/') { - token->type = NJS_TOKEN_END; - lexer->start++; for (p = lexer->start; p < lexer->end; p++) { - if (*p == '\n') { + if (*p == '\n' || (p + 1) == lexer->end) { lexer->start = p + 1; lexer->line++; diff -r 9b20edb591c4 -r 603a21fabf8d src/njs_shell.c --- a/src/njs_shell.c Fri Mar 20 17:33:10 2020 +0300 +++ b/src/njs_shell.c Mon Mar 23 17:15:46 2020 +0300 @@ -801,17 +801,24 @@ static njs_int_t njs_process_script(njs_opts_t *opts, njs_console_t *console, const njs_str_t *script) { - u_char *start; + u_char *start, *end; njs_vm_t *vm; njs_int_t ret; vm = console->vm; start = script->start; + end = start + script->length; - ret = njs_vm_compile(vm, &start, start + script->length); + ret = njs_vm_compile(vm, &start, end); if (ret == NJS_OK) { - ret = njs_vm_start(vm); + if (start == end) { + ret = njs_vm_start(vm); + + } else { + njs_vm_error(vm, "Extra characters at the end of the script"); + ret = NJS_ERROR; + } } njs_output(opts, vm, ret); diff -r 9b20edb591c4 -r 603a21fabf8d src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Fri Mar 20 17:33:10 2020 +0300 +++ b/src/test/njs_unit_test.c Mon Mar 23 17:15:46 2020 +0300 @@ -35,6 +35,9 @@ static njs_unit_test_t njs_test[] = { njs_str("/***/1/*\n**/"), njs_str("1") }, + { njs_str("/***/1// "), + njs_str("1") }, + { njs_str(">"), njs_str("SyntaxError: Unexpected token \">\" in 1") }, @@ -17080,7 +17083,7 @@ static njs_int_t njs_unit_test(njs_unit_test_t tests[], size_t num, const char *name, njs_opts_t *opts, njs_stat_t *stat) { - u_char *start; + u_char *start, *end; njs_vm_t *vm, *nvm; njs_int_t ret; njs_str_t s; @@ -17123,10 +17126,11 @@ njs_unit_test(njs_unit_test_t tests[], s } start = tests[i].script.start; - - ret = njs_vm_compile(vm, &start, start + tests[i].script.length); - - if (ret == NJS_OK) { + end = start + tests[i].script.length; + + ret = njs_vm_compile(vm, &start, end); + + if (ret == NJS_OK && start == end) { if (opts->disassemble) { njs_disassembler(vm); } @@ -17160,9 +17164,15 @@ njs_unit_test(njs_unit_test_t tests[], s } } else { - if (njs_vm_retval_string(vm, &s) != NJS_OK) { - njs_printf("njs_vm_retval_string() failed\n"); - goto done; + if (ret != NJS_OK) { + if (njs_vm_retval_string(vm, &s) != NJS_OK) { + njs_printf("njs_vm_retval_string() failed\n"); + goto done; + } + + } else { + s = njs_str_value("Error: " + "Extra characters at the end of the script"); } } From xeioex at nginx.com Mon Mar 23 17:00:48 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 23 Mar 2020 17:00:48 +0000 Subject: [njs] Fixed "PROP NEXT" instruction. Message-ID: details: https://hg.nginx.org/njs/rev/a7ca9fc28b0b branches: changeset: 1362:a7ca9fc28b0b user: Dmitry Volyntsev date: Mon Mar 23 19:52:02 2020 +0300 description: Fixed "PROP NEXT" instruction. The proper way to access array's elements is "start" field whereas "data" is an allocation field. While currently they are numerically indentical it may change in the future. diffstat: src/njs_vmcode.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 603a21fabf8d -r a7ca9fc28b0b src/njs_vmcode.c --- a/src/njs_vmcode.c Mon Mar 23 17:15:46 2020 +0300 +++ b/src/njs_vmcode.c Mon Mar 23 19:52:02 2020 +0300 @@ -788,7 +788,7 @@ next: next = value2->data.u.next; if (next->index < next->array->length) { - *retval = next->array->data[next->index++]; + *retval = next->array->start[next->index++]; ret = pnext->offset; break; From xeioex at nginx.com Mon Mar 23 17:00:50 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 23 Mar 2020 17:00:50 +0000 Subject: [njs] Fixed instructions jump offset output. Message-ID: details: https://hg.nginx.org/njs/rev/94d6774e0c03 branches: changeset: 1363:94d6774e0c03 user: Dmitry Volyntsev date: Mon Mar 23 19:58:50 2020 +0300 description: Fixed instructions jump offset output. Previously jump offsets were rendered as unsigned integers whereas jump offsets can be negative. diffstat: src/njs_disassembler.c | 42 +++++++++++++++++++----------------------- test/njs_expect_test.exp | 2 +- 2 files changed, 20 insertions(+), 24 deletions(-) diffs (179 lines): diff -r a7ca9fc28b0b -r 94d6774e0c03 src/njs_disassembler.c --- a/src/njs_disassembler.c Mon Mar 23 19:52:02 2020 +0300 +++ b/src/njs_disassembler.c Mon Mar 23 19:58:50 2020 +0300 @@ -162,7 +162,6 @@ njs_disassemble(u_char *start, u_char *e u_char *p; njs_str_t *name; njs_uint_t n; - const char *sign; njs_code_name_t *code_name; njs_vmcode_jump_t *jump; njs_vmcode_1addr_t *code1; @@ -210,10 +209,9 @@ njs_disassemble(u_char *start, u_char *e if (operation == NJS_VMCODE_IF_TRUE_JUMP) { cond_jump = (njs_vmcode_cond_jump_t *) p; - sign = (cond_jump->offset >= 0) ? "+" : ""; - njs_printf("%05uz JUMP IF TRUE %04Xz %s%uz\n", - p - start, (size_t) cond_jump->cond, sign, + njs_printf("%05uz JUMP IF TRUE %04Xz %z\n", + p - start, (size_t) cond_jump->cond, (size_t) cond_jump->offset); p += sizeof(njs_vmcode_cond_jump_t); @@ -223,10 +221,9 @@ njs_disassemble(u_char *start, u_char *e if (operation == NJS_VMCODE_IF_FALSE_JUMP) { cond_jump = (njs_vmcode_cond_jump_t *) p; - sign = (cond_jump->offset >= 0) ? "+" : ""; - njs_printf("%05uz JUMP IF FALSE %04Xz %s%uz\n", - p - start, (size_t) cond_jump->cond, sign, + njs_printf("%05uz JUMP IF FALSE %04Xz %z\n", + p - start, (size_t) cond_jump->cond, (size_t) cond_jump->offset); p += sizeof(njs_vmcode_cond_jump_t); @@ -236,10 +233,9 @@ njs_disassemble(u_char *start, u_char *e if (operation == NJS_VMCODE_JUMP) { jump = (njs_vmcode_jump_t *) p; - sign = (jump->offset >= 0) ? "+" : ""; - njs_printf("%05uz JUMP %s%uz\n", - p - start, sign, (size_t) jump->offset); + njs_printf("%05uz JUMP %z\n", + p - start, (size_t) jump->offset); p += sizeof(njs_vmcode_jump_t); @@ -249,7 +245,7 @@ njs_disassemble(u_char *start, u_char *e if (operation == NJS_VMCODE_IF_EQUAL_JUMP) { equal = (njs_vmcode_equal_jump_t *) p; - njs_printf("%05uz JUMP IF EQUAL %04Xz %04Xz +%uz\n", + njs_printf("%05uz JUMP IF EQUAL %04Xz %04Xz %z\n", p - start, (size_t) equal->value1, (size_t) equal->value2, (size_t) equal->offset); @@ -261,7 +257,7 @@ njs_disassemble(u_char *start, u_char *e if (operation == NJS_VMCODE_TEST_IF_TRUE) { test_jump = (njs_vmcode_test_jump_t *) p; - njs_printf("%05uz TEST IF TRUE %04Xz %04Xz +%uz\n", + njs_printf("%05uz TEST IF TRUE %04Xz %04Xz %z\n", p - start, (size_t) test_jump->retval, (size_t) test_jump->value, (size_t) test_jump->offset); @@ -273,7 +269,7 @@ njs_disassemble(u_char *start, u_char *e if (operation == NJS_VMCODE_TEST_IF_FALSE) { test_jump = (njs_vmcode_test_jump_t *) p; - njs_printf("%05uz TEST IF FALSE %04Xz %04Xz +%uz\n", + njs_printf("%05uz TEST IF FALSE %04Xz %04Xz %z\n", p - start, (size_t) test_jump->retval, (size_t) test_jump->value, (size_t) test_jump->offset); @@ -285,7 +281,7 @@ njs_disassemble(u_char *start, u_char *e if (operation == NJS_VMCODE_COALESCE) { test_jump = (njs_vmcode_test_jump_t *) p; - njs_printf("%05uz COALESCE %04Xz %04Xz +%uz\n", + njs_printf("%05uz COALESCE %04Xz %04Xz %z\n", p - start, (size_t) test_jump->retval, (size_t) test_jump->value, (size_t) test_jump->offset); @@ -321,7 +317,7 @@ njs_disassemble(u_char *start, u_char *e if (operation == NJS_VMCODE_PROPERTY_FOREACH) { prop_foreach = (njs_vmcode_prop_foreach_t *) p; - njs_printf("%05uz PROP FOREACH %04Xz %04Xz +%uz\n", + njs_printf("%05uz PROP FOREACH %04Xz %04Xz %z\n", p - start, (size_t) prop_foreach->next, (size_t) prop_foreach->object, (size_t) prop_foreach->offset); @@ -333,7 +329,7 @@ njs_disassemble(u_char *start, u_char *e if (operation == NJS_VMCODE_PROPERTY_NEXT) { prop_next = (njs_vmcode_prop_next_t *) p; - njs_printf("%05uz PROP NEXT %04Xz %04Xz %04Xz %uz\n", + njs_printf("%05uz PROP NEXT %04Xz %04Xz %04Xz %z\n", p - start, (size_t) prop_next->retval, (size_t) prop_next->object, (size_t) prop_next->next, (size_t) prop_next->offset); @@ -362,7 +358,7 @@ njs_disassemble(u_char *start, u_char *e if (operation == NJS_VMCODE_TRY_START) { try_start = (njs_vmcode_try_start_t *) p; - njs_printf("%05uz TRY START %04Xz %04Xz +%uz\n", + njs_printf("%05uz TRY START %04Xz %04Xz %z\n", p - start, (size_t) try_start->exception_value, (size_t) try_start->exit_value, (size_t) try_start->offset); @@ -375,7 +371,7 @@ njs_disassemble(u_char *start, u_char *e if (operation == NJS_VMCODE_TRY_BREAK) { try_tramp = (njs_vmcode_try_trampoline_t *) p; - njs_printf("%05uz TRY BREAK %04Xz %uz\n", + njs_printf("%05uz TRY BREAK %04Xz %z\n", p - start, (size_t) try_tramp->exit_value, (size_t) try_tramp->offset); @@ -387,7 +383,7 @@ njs_disassemble(u_char *start, u_char *e if (operation == NJS_VMCODE_TRY_CONTINUE) { try_tramp = (njs_vmcode_try_trampoline_t *) p; - njs_printf("%05uz TRY CONTINUE %04Xz %uz\n", + njs_printf("%05uz TRY CONTINUE %04Xz %z\n", p - start, (size_t) try_tramp->exit_value, (size_t) try_tramp->offset); @@ -399,7 +395,7 @@ njs_disassemble(u_char *start, u_char *e if (operation == NJS_VMCODE_TRY_RETURN) { try_return = (njs_vmcode_try_return_t *) p; - njs_printf("%05uz TRY RETURN %04Xz %04Xz +%uz\n", + njs_printf("%05uz TRY RETURN %04Xz %04Xz %z\n", p - start, (size_t) try_return->save, (size_t) try_return->retval, (size_t) try_return->offset); @@ -412,7 +408,7 @@ njs_disassemble(u_char *start, u_char *e if (operation == NJS_VMCODE_CATCH) { catch = (njs_vmcode_catch_t *) p; - njs_printf("%05uz CATCH %04Xz +%uz\n", + njs_printf("%05uz CATCH %04Xz %z\n", p - start, (size_t) catch->exception, (size_t) catch->offset); @@ -424,7 +420,7 @@ njs_disassemble(u_char *start, u_char *e if (operation == NJS_VMCODE_TRY_END) { try_end = (njs_vmcode_try_end_t *) p; - njs_printf("%05uz TRY END +%uz\n", + njs_printf("%05uz TRY END %z\n", p - start, (size_t) try_end->offset); p += sizeof(njs_vmcode_try_end_t); @@ -435,7 +431,7 @@ njs_disassemble(u_char *start, u_char *e if (operation == NJS_VMCODE_FINALLY) { finally = (njs_vmcode_finally_t *) p; - njs_printf("%05uz TRY FINALLY %04Xz %04Xz +%uz +%uz\n", + njs_printf("%05uz TRY FINALLY %04Xz %04Xz %z %z\n", p - start, (size_t) finally->retval, (size_t) finally->exit_value, (size_t) finally->continue_offset, diff -r a7ca9fc28b0b -r 94d6774e0c03 test/njs_expect_test.exp --- a/test/njs_expect_test.exp Mon Mar 23 19:52:02 2020 +0300 +++ b/test/njs_expect_test.exp Mon Mar 23 19:58:50 2020 +0300 @@ -818,7 +818,7 @@ njs_test { {"1+1\r\n" "00000 ADD*\r\n*2"} {"for (var n in [1]) {try {break} finally{}}\r\n" - "00000 ARRAY*\r\n*TRY BREAK*STOP*\r\n\r\nundefined"} + "00000 ARRAY*\r\n*TRY BREAK*PROP NEXT*-*\r\n\r\nundefined"} {"(function() {try {return} finally{}})()\r\n" "00000 TRY START*\r\n*TRY RETURN*STOP*\r\n\r\nundefined"} } "-d" From sangdeuk.kwon at quantil.com Wed Mar 25 07:05:37 2020 From: sangdeuk.kwon at quantil.com (Sangdeuk Kwon) Date: Wed, 25 Mar 2020 16:05:37 +0900 Subject: [PATCH] When cache file is expired, nginx can make a lot of upstream requests. Message-ID: # HG changeset patch # User Sangdeuk Kwon # Date 1585118845 -32400 # Wed Mar 25 15:47:25 2020 +0900 # Node ID fe5988cefe615bb0f2a8936221c8464a6664916e # Parent 0cb942c1c1aa98118076e72e0b89940e85e6291c When cache file is expired, nginx can make a lot of upstream requests. In cache miss case, nginx makes only one upstream request if "proxy_cache_lock" is "on". When cache file is expired, nginx can make a lot of upstream requests even though "proxy_cache_lock" is "on". If origin's content is changed, this simultaneous upstream requests can make "too long header" error log. diff -r 0cb942c1c1aa -r fe5988cefe61 src/http/ngx_http_cache.h --- a/src/http/ngx_http_cache.h Fri Mar 13 02:12:10 2020 +0300 +++ b/src/http/ngx_http_cache.h Wed Mar 25 15:47:25 2020 +0900 @@ -188,6 +188,7 @@ ngx_int_t ngx_http_file_cache_create(ngx_http_request_t *r); void ngx_http_file_cache_create_key(ngx_http_request_t *r); ngx_int_t ngx_http_file_cache_open(ngx_http_request_t *r); +ngx_int_t ngx_http_file_cache_handle_updating(ngx_http_request_t *r); ngx_int_t ngx_http_file_cache_set_header(ngx_http_request_t *r, u_char *buf); void ngx_http_file_cache_update(ngx_http_request_t *r, ngx_temp_file_t *tf); void ngx_http_file_cache_update_header(ngx_http_request_t *r); diff -r 0cb942c1c1aa -r fe5988cefe61 src/http/ngx_http_file_cache.c --- a/src/http/ngx_http_file_cache.c Fri Mar 13 02:12:10 2020 +0300 +++ b/src/http/ngx_http_file_cache.c Wed Mar 25 15:47:25 2020 +0900 @@ -522,6 +522,28 @@ } +ngx_int_t +ngx_http_file_cache_handle_updating(ngx_http_request_t *r) +{ + ngx_http_cache_t *c; + ngx_http_file_cache_t *cache; + ngx_int_t updating; + + c = r->cache; + cache = c->file_cache; + + ngx_shmtx_lock(&cache->shpool->mutex); + updating = c->node->updating; + ngx_shmtx_unlock(&cache->shpool->mutex); + + if (!updating) { + return NGX_OK; + } + + return ngx_http_file_cache_lock(r, c); +} + + static ngx_int_t ngx_http_file_cache_read(ngx_http_request_t *r, ngx_http_cache_t *c) { diff -r 0cb942c1c1aa -r fe5988cefe61 src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c Fri Mar 13 02:12:10 2020 +0300 +++ b/src/http/ngx_http_upstream.c Wed Mar 25 15:47:25 2020 +0900 @@ -906,6 +906,10 @@ } else { rc = NGX_ERROR; } + } else { + if (ngx_http_file_cache_handle_updating(r) == NGX_AGAIN) { + rc = NGX_BUSY; + } } break; @@ -919,7 +923,11 @@ rc = NGX_OK; } else { - rc = NGX_HTTP_CACHE_STALE; + if (ngx_http_file_cache_handle_updating(r) == NGX_AGAIN) { + rc = NGX_BUSY; + } else { + rc = NGX_HTTP_CACHE_STALE; + } } break; -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Thu Mar 26 00:30:55 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 26 Mar 2020 03:30:55 +0300 Subject: [PATCH] When cache file is expired, nginx can make a lot of upstream requests. In-Reply-To: References: Message-ID: <20200326003055.GA3546@mdounin.ru> Hello! On Wed, Mar 25, 2020 at 04:05:37PM +0900, Sangdeuk Kwon wrote: > # HG changeset patch > # User Sangdeuk Kwon > # Date 1585118845 -32400 > # Wed Mar 25 15:47:25 2020 +0900 > # Node ID fe5988cefe615bb0f2a8936221c8464a6664916e > # Parent 0cb942c1c1aa98118076e72e0b89940e85e6291c > When cache file is expired, nginx can make a lot of upstream requests. > > In cache miss case, nginx makes only one upstream request > if "proxy_cache_lock" is "on". > When cache file is expired, nginx can make a lot of upstream requests > even though "proxy_cache_lock" is "on". That's expected behaviour. Citing the "proxy_cache_lock" directive description in the documentation (http://nginx.org/r/proxy_cache_lock): : When enabled, only one request at a time will be allowed to : populate a new cache element identified according to the : proxy_cache_key directive by passing a request to a proxied : server. Note "a new cache element" part. To limit load on backends when updating existing cache elements, "proxy_cache_use_stale updating" can be used. See http://nginx.org/r/proxy_cache_use_stale for details. > If origin's content is changed, this simultaneous upstream requests > can make "too long header" error log. And this claim seems to be incorrect and, even if it is correct, irrelevant to the expected behaviour described above. Summing the above, it is completely unclear from the description what your patch tries to do. And the code seems to be completely wrong, too, but it's hard to tell without understanding what it is expected to do in the first place. -- Maxim Dounin http://mdounin.ru/ From dulmandakh at gmail.com Thu Mar 26 13:37:34 2020 From: dulmandakh at gmail.com (Dulmandakh Sukhbaatar) Date: Thu, 26 Mar 2020 21:37:34 +0800 Subject: Hardening nginx.service with systemd Message-ID: <3A2C245E-43CD-42AC-8244-03E1D6A54DDD@gmail.com> Hello, I would like to propose to harden nginx.service with systems configurations, and this change uses PrivateDevices=yes, PrivateTmp=yes and ProtectSystem=full configs. And here are excerpts from man systemd.exec man page. PrivateDevices=yes sets up a new /dev mount for the executed processes and only adds API pseudo devices such as /dev/null, /dev/zero or /dev/random (as well as the pseudo TTY subsystem) to it, but no physical devices such as /dev/sda, system memory /dev/mem, system ports /dev/port and others PrivateTmp=yes sets up a new file system namespace for the executed processes and mounts private /tmp and /var/tmp directories inside it that is not shared by processes outside of the namespace ProtectSystem=full mounts the /usr and /boot directories read-only for processes invoked by this unit. If set to "full", the /etc directory is mounted read-only, too I believe that these configs will harden nginx.service, thus protect OS from security bugs in nginx. https://www.freedesktop.org/software/systemd/man/systemd.exec.html -------------- next part -------------- A non-text attachment was scrubbed... Name: nginx.service.patch Type: application/octet-stream Size: 626 bytes Desc: not available URL: From xeioex at nginx.com Thu Mar 26 14:12:45 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 26 Mar 2020 14:12:45 +0000 Subject: [njs] Improved njs_object_length() and friends prototypes. Message-ID: details: https://hg.nginx.org/njs/rev/2a03cd71561a branches: changeset: 1364:2a03cd71561a user: Dmitry Volyntsev date: Thu Mar 26 17:12:16 2020 +0300 description: Improved njs_object_length() and friends prototypes. While object length is always non-negative it is simpler to work with signed value to avoid too many typecasts. diffstat: src/njs_array.c | 78 +++++++++++++++++++++------------------------ src/njs_function.c | 2 +- src/njs_json.c | 4 +- src/njs_number.c | 8 ++-- src/njs_number.h | 2 +- src/njs_object.c | 2 +- src/njs_object.h | 4 +- src/njs_regexp.c | 6 +- src/njs_string.c | 2 +- src/njs_typed_array.c | 8 ++-- src/njs_value.c | 5 +- src/njs_value.h | 10 ++-- src/njs_value_conversion.h | 2 +- 13 files changed, 65 insertions(+), 68 deletions(-) diffs (596 lines): diff -r 94d6774e0c03 -r 2a03cd71561a src/njs_array.c --- a/src/njs_array.c Mon Mar 23 19:58:50 2020 +0300 +++ b/src/njs_array.c Thu Mar 26 17:12:16 2020 +0300 @@ -24,7 +24,7 @@ typedef struct { typedef njs_int_t (*njs_array_iterator_handler_t)(njs_vm_t *vm, - njs_array_iterator_args_t *args, njs_value_t *entry, uint64_t n); + njs_array_iterator_args_t *args, njs_value_t *entry, int64_t n); static njs_int_t njs_array_prototype_slice_copy(njs_vm_t *vm, @@ -183,8 +183,8 @@ njs_array_length_set(njs_vm_t *vm, njs_v njs_object_prop_t *prev, njs_value_t *setval) { double num, idx; + int64_t prev_length; uint32_t i, length; - uint64_t prev_length; njs_int_t ret; njs_array_t *array, *keys; @@ -576,8 +576,7 @@ static njs_int_t njs_array_prototype_slice(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - int64_t start, end, length; - uint64_t object_length; + int64_t start, end, length, object_length; njs_int_t ret; njs_value_t *this; @@ -823,7 +822,7 @@ static njs_int_t njs_array_prototype_push(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - uint64_t length; + int64_t length; njs_int_t ret; njs_uint_t i; njs_array_t *array; @@ -889,7 +888,7 @@ static njs_int_t njs_array_prototype_pop(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - uint64_t length; + int64_t length; njs_int_t ret; njs_array_t *array; njs_value_t *this, *entry; @@ -963,7 +962,7 @@ njs_array_prototype_unshift(njs_vm_t *vm njs_index_t unused) { double idx; - uint64_t from, to, length; + int64_t from, to, length; njs_int_t ret; njs_uint_t n; njs_array_t *array, *keys; @@ -1097,7 +1096,7 @@ static njs_int_t njs_array_prototype_shift(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - uint64_t i, length; + int64_t i, length; njs_int_t ret; njs_array_t *array; njs_value_t *this, *item, entry; @@ -1301,7 +1300,7 @@ static njs_int_t njs_array_prototype_reverse(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - uint64_t length; + int64_t length; njs_int_t ret; njs_uint_t i, n; njs_value_t value, *this; @@ -1382,8 +1381,7 @@ njs_array_prototype_join(njs_vm_t *vm, n njs_index_t unused) { u_char *p, *last; - int64_t size, length; - uint64_t i, len; + int64_t i, size, len, length; njs_int_t ret; njs_chb_t chain; njs_utf8_t utf8; @@ -1602,7 +1600,7 @@ njs_array_indices(njs_vm_t *vm, njs_valu njs_inline njs_int_t njs_array_object_handler(njs_vm_t *vm, njs_array_iterator_handler_t handler, - njs_array_iterator_args_t *args, njs_value_t *key, uint64_t i) + njs_array_iterator_args_t *args, njs_value_t *key, int64_t i) { njs_int_t ret; njs_value_t prop, *entry; @@ -1640,7 +1638,7 @@ njs_array_iterator(njs_vm_t *vm, njs_arr njs_array_iterator_handler_t handler) { double idx; - uint64_t length, i, from, to; + int64_t length, i, from, to; njs_int_t ret; njs_array_t *array, *keys; njs_value_t *value, *entry, prop, character, string_obj; @@ -1712,7 +1710,7 @@ njs_array_iterator(njs_vm_t *vm, njs_arr p = string_prop.start; end = p + string_prop.size; - if (length == string_prop.size) { + if ((size_t) length == string_prop.size) { /* Byte or ASCII string. */ for (i = from; i < to; i++) { @@ -1802,7 +1800,7 @@ njs_array_reverse_iterator(njs_vm_t *vm, njs_array_iterator_handler_t handler) { double idx; - uint64_t i, from, to, length; + int64_t i, from, to, length; njs_int_t ret; njs_array_t *array, *keys; njs_value_t *entry, *value, prop, character, string_obj; @@ -1874,7 +1872,7 @@ njs_array_reverse_iterator(njs_vm_t *vm, length = njs_string_prop(&string_prop, value); end = string_prop.start + string_prop.size; - if (length == string_prop.size) { + if ((size_t) length == string_prop.size) { /* Byte or ASCII string. */ p = string_prop.start + from; @@ -2005,8 +2003,9 @@ njs_array_prototype_concat(njs_vm_t *vm, njs_index_t unused) { double idx; - uint64_t i, k, len, length; + int64_t k, len, length; njs_int_t ret; + njs_uint_t i; njs_value_t this, retval, *value, *e; njs_array_t *array, *keys; @@ -2158,7 +2157,7 @@ njs_array_prototype_concat(njs_vm_t *vm, static njs_int_t njs_array_handler_index_of(njs_vm_t *vm, njs_array_iterator_args_t *args, - njs_value_t *entry, uint64_t n) + njs_value_t *entry, int64_t n) { if (njs_values_strict_equal(args->argument, entry)) { njs_set_number(&vm->retval, n); @@ -2174,8 +2173,7 @@ static njs_int_t njs_array_prototype_index_of(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - int64_t from; - uint64_t length; + int64_t from, length; njs_int_t ret; njs_array_iterator_args_t iargs; @@ -2230,8 +2228,7 @@ static njs_int_t njs_array_prototype_last_index_of(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - int64_t from; - uint64_t length; + int64_t from, length; njs_int_t ret; njs_array_iterator_args_t iargs; @@ -2264,7 +2261,7 @@ njs_array_prototype_last_index_of(njs_vm } if (from >= 0) { - from = njs_min((uint64_t) from, length - 1); + from = njs_min(from, length - 1); } else if (from < 0) { from += length; @@ -2292,7 +2289,7 @@ not_found: static njs_int_t njs_array_handler_includes(njs_vm_t *vm, njs_array_iterator_args_t *args, - njs_value_t *entry, uint64_t n) + njs_value_t *entry, int64_t n) { if (!njs_is_valid(entry)) { entry = njs_value_arg(&njs_value_undefined); @@ -2312,8 +2309,7 @@ static njs_int_t njs_array_prototype_includes(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - int64_t from; - uint64_t length; + int64_t from, length; njs_int_t ret; njs_array_iterator_args_t iargs; @@ -2387,7 +2383,7 @@ njs_array_prototype_fill(njs_vm_t *vm, n length = array->length; } else { - ret = njs_object_length(vm, this, (uint64_t *) &length); + ret = njs_object_length(vm, this, &length); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } @@ -2469,7 +2465,7 @@ njs_array_validate_args(njs_vm_t *vm, nj return ret; } - ret = njs_value_length(vm, iargs->value, (uint64_t *) &iargs->to); + ret = njs_value_length(vm, iargs->value, &iargs->to); if (njs_slow_path(ret != NJS_OK)) { return ret; } @@ -2494,7 +2490,7 @@ failed: static njs_int_t njs_array_handler_for_each(njs_vm_t *vm, njs_array_iterator_args_t *args, - njs_value_t *entry, uint64_t n) + njs_value_t *entry, int64_t n) { if (njs_is_valid(entry)) { return njs_array_iterator_call(vm, args, entry, n); @@ -2529,7 +2525,7 @@ njs_array_prototype_for_each(njs_vm_t *v static njs_int_t njs_array_handler_some(njs_vm_t *vm, njs_array_iterator_args_t *args, - njs_value_t *entry, uint64_t n) + njs_value_t *entry, int64_t n) { njs_int_t ret; @@ -2577,7 +2573,7 @@ njs_array_prototype_some(njs_vm_t *vm, n static njs_int_t njs_array_handler_every(njs_vm_t *vm, njs_array_iterator_args_t *args, - njs_value_t *entry, uint64_t n) + njs_value_t *entry, int64_t n) { njs_int_t ret; @@ -2625,7 +2621,7 @@ njs_array_prototype_every(njs_vm_t *vm, static njs_int_t njs_array_handler_filter(njs_vm_t *vm, njs_array_iterator_args_t *args, - njs_value_t *entry, uint64_t n) + njs_value_t *entry, int64_t n) { njs_int_t ret; njs_value_t copy; @@ -2681,7 +2677,7 @@ njs_array_prototype_filter(njs_vm_t *vm, static njs_int_t njs_array_handler_find(njs_vm_t *vm, njs_array_iterator_args_t *args, - njs_value_t *entry, uint64_t n) + njs_value_t *entry, int64_t n) { njs_int_t ret; njs_value_t copy; @@ -2735,7 +2731,7 @@ njs_array_prototype_find(njs_vm_t *vm, n static njs_int_t njs_array_handler_find_index(njs_vm_t *vm, njs_array_iterator_args_t *args, - njs_value_t *entry, uint64_t n) + njs_value_t *entry, int64_t n) { njs_int_t ret; njs_value_t copy; @@ -2789,7 +2785,7 @@ njs_array_prototype_find_index(njs_vm_t static njs_int_t njs_array_handler_map(njs_vm_t *vm, njs_array_iterator_args_t *args, - njs_value_t *entry, uint64_t n) + njs_value_t *entry, int64_t n) { njs_int_t ret; njs_array_t *retval; @@ -2830,7 +2826,7 @@ static njs_int_t njs_array_prototype_map(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - uint64_t length, i; + int64_t i, length; njs_int_t ret; njs_array_t *array; njs_value_t *this; @@ -2896,7 +2892,7 @@ unexpected_args: njs_inline njs_int_t njs_array_iterator_reduce(njs_vm_t *vm, njs_array_iterator_args_t *args, - njs_value_t *entry, uint64_t n) + njs_value_t *entry, int64_t n) { njs_value_t arguments[5]; @@ -2914,7 +2910,7 @@ njs_array_iterator_reduce(njs_vm_t *vm, static njs_int_t njs_array_handler_reduce(njs_vm_t *vm, njs_array_iterator_args_t *args, - njs_value_t *entry, uint64_t n) + njs_value_t *entry, int64_t n) { njs_int_t ret; @@ -2986,7 +2982,7 @@ njs_array_prototype_reduce_right(njs_vm_ return ret; } - ret = njs_value_length(vm, iargs.value, (uint64_t *) &iargs.from); + ret = njs_value_length(vm, iargs.value, &iargs.from); if (njs_slow_path(ret != NJS_OK)) { return ret; } @@ -3080,7 +3076,7 @@ static njs_int_t njs_array_prototype_sort(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - uint64_t n, index, length, current; + int64_t n, index, length, current; njs_int_t ret; njs_array_t *array; njs_value_t retval, value, *this, *start, arguments[3]; @@ -3205,7 +3201,7 @@ njs_array_prototype_copy_within(njs_vm_t return ret; } - ret = njs_value_length(vm, this, (uint64_t *) &length); + ret = njs_value_length(vm, this, &length); if (njs_slow_path(ret != NJS_OK)) { return ret; } diff -r 94d6774e0c03 -r 2a03cd71561a src/njs_function.c --- a/src/njs_function.c Mon Mar 23 19:58:50 2020 +0300 +++ b/src/njs_function.c Thu Mar 26 17:12:16 2020 +0300 @@ -1076,7 +1076,7 @@ static njs_int_t njs_function_prototype_apply(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - uint64_t i, length; + int64_t i, length; njs_int_t ret; njs_frame_t *frame; njs_value_t *this, *arr_like; diff -r 94d6774e0c03 -r 2a03cd71561a src/njs_json.c --- a/src/njs_json.c Mon Mar 23 19:58:50 2020 +0300 +++ b/src/njs_json.c Thu Mar 26 17:12:16 2020 +0300 @@ -28,8 +28,8 @@ typedef struct { NJS_JSON_ARRAY, } type:8; - uint64_t index; - uint64_t length; + int64_t index; + int64_t length; njs_array_t *keys; njs_value_t *key; njs_object_prop_t *prop; diff -r 94d6774e0c03 -r 2a03cd71561a src/njs_number.c --- a/src/njs_number.c Mon Mar 23 19:58:50 2020 +0300 +++ b/src/njs_number.c Thu Mar 26 17:12:16 2020 +0300 @@ -230,24 +230,24 @@ njs_number_to_string(njs_vm_t *vm, njs_v njs_int_t -njs_uint64_to_string(njs_vm_t *vm, njs_value_t *value, uint64_t u64) +njs_int64_to_string(njs_vm_t *vm, njs_value_t *value, int64_t i64) { size_t size; u_char *dst, *p; u_char buf[128]; - if (njs_fast_path(u64 < 0x3fffffffffffULL)) { + if (njs_fast_path(i64 >= 0 && i64 < 0x3fffffffffffLL)) { /* Fits to short_string. */ dst = njs_string_short_start(value); - p = njs_sprintf(dst, dst + NJS_STRING_SHORT, "%uL", u64); + p = njs_sprintf(dst, dst + NJS_STRING_SHORT, "%L", i64); njs_string_short_set(value, p - dst, p - dst); return NJS_OK; } - size = njs_dtoa(u64, (char *) buf); + size = njs_dtoa(i64, (char *) buf); return njs_string_new(vm, value, buf, size, size); } diff -r 94d6774e0c03 -r 2a03cd71561a src/njs_number.h --- a/src/njs_number.h Mon Mar 23 19:58:50 2020 +0300 +++ b/src/njs_number.h Thu Mar 26 17:12:16 2020 +0300 @@ -8,7 +8,7 @@ #define _NJS_NUMBER_H_INCLUDED_ -#define NJS_MAX_LENGTH (0x1fffffffffffffULL) +#define NJS_MAX_LENGTH (0x1fffffffffffffLL) double njs_key_to_index(const njs_value_t *value); diff -r 94d6774e0c03 -r 2a03cd71561a src/njs_object.c --- a/src/njs_object.c Mon Mar 23 19:58:50 2020 +0300 +++ b/src/njs_object.c Thu Mar 26 17:12:16 2020 +0300 @@ -2628,7 +2628,7 @@ const njs_object_init_t njs_object_prot njs_int_t -njs_object_length(njs_vm_t *vm, njs_value_t *value, uint64_t *length) +njs_object_length(njs_vm_t *vm, njs_value_t *value, int64_t *length) { njs_int_t ret; njs_value_t value_length; diff -r 94d6774e0c03 -r 2a03cd71561a src/njs_object.h --- a/src/njs_object.h Mon Mar 23 19:58:50 2020 +0300 +++ b/src/njs_object.h Thu Mar 26 17:12:16 2020 +0300 @@ -67,7 +67,7 @@ njs_value_t *njs_property_constructor_cr njs_value_t *constructor); njs_int_t njs_object_prototype_to_string(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused); -njs_int_t njs_object_length(njs_vm_t *vm, njs_value_t *value, uint64_t *dst); +njs_int_t njs_object_length(njs_vm_t *vm, njs_value_t *value, int64_t *dst); njs_int_t njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq); njs_object_prop_t *njs_object_prop_alloc(njs_vm_t *vm, const njs_value_t *name, @@ -226,7 +226,7 @@ njs_key_string_get(njs_vm_t *vm, njs_val njs_inline njs_int_t -njs_object_length_set(njs_vm_t *vm, njs_value_t *value, uint64_t length) +njs_object_length_set(njs_vm_t *vm, njs_value_t *value, int64_t length) { njs_value_t index; diff -r 94d6774e0c03 -r 2a03cd71561a src/njs_regexp.c --- a/src/njs_regexp.c Mon Mar 23 19:58:50 2020 +0300 +++ b/src/njs_regexp.c Thu Mar 26 17:12:16 2020 +0300 @@ -871,7 +871,7 @@ njs_regexp_prototype_test(njs_vm_t *vm, njs_index_t unused) { int *captures; - uint64_t last_index; + int64_t last_index; njs_int_t ret, match; njs_uint_t n; njs_regex_t *regex; @@ -963,7 +963,7 @@ njs_int_t njs_regexp_prototype_exec(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - uint64_t last_index; + int64_t last_index; njs_int_t ret; njs_utf8_t utf8; njs_value_t *value, lvalue; @@ -1002,7 +1002,7 @@ njs_regexp_prototype_exec(njs_vm_t *vm, (void) njs_string_prop(&string, value); - if (string.size >= last_index) { + if (string.size >= (size_t) last_index) { utf8 = NJS_STRING_BYTE; type = NJS_REGEXP_BYTE; diff -r 94d6774e0c03 -r 2a03cd71561a src/njs_string.c --- a/src/njs_string.c Mon Mar 23 19:58:50 2020 +0300 +++ b/src/njs_string.c Thu Mar 26 17:12:16 2020 +0300 @@ -1608,8 +1608,8 @@ static njs_int_t njs_string_bytes_from_array_like(njs_vm_t *vm, njs_value_t *value) { u_char *p; + int64_t length; uint32_t u32; - uint64_t length; njs_int_t ret; njs_array_t *array; njs_value_t *octet, index, prop; diff -r 94d6774e0c03 -r 2a03cd71561a src/njs_typed_array.c --- a/src/njs_typed_array.c Mon Mar 23 19:58:50 2020 +0300 +++ b/src/njs_typed_array.c Thu Mar 26 17:12:16 2020 +0300 @@ -13,8 +13,9 @@ njs_typed_array_constructor(njs_vm_t *vm njs_index_t magic) { double num; + int64_t i, length; uint32_t element_size; - uint64_t i, length, size, offset; + uint64_t size, offset; njs_int_t ret; njs_value_t *value, prop; njs_array_t *src_array; @@ -360,8 +361,7 @@ njs_typed_array_prototype_set(njs_vm_t * njs_uint_t nargs, njs_index_t unused) { double num; - uint32_t i; - int64_t length, src_length, offset; + int64_t i, length, src_length, offset; njs_int_t ret; njs_value_t *this, *src, *value, prop; njs_array_t *array; @@ -436,7 +436,7 @@ njs_typed_array_prototype_set(njs_vm_t * return ret; } - ret = njs_object_length(vm, src, (uint64_t *) &src_length); + ret = njs_object_length(vm, src, &src_length); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } diff -r 94d6774e0c03 -r 2a03cd71561a src/njs_value.c --- a/src/njs_value.c Mon Mar 23 19:58:50 2020 +0300 +++ b/src/njs_value.c Thu Mar 26 17:12:16 2020 +0300 @@ -261,7 +261,7 @@ njs_value_own_enumerate(njs_vm_t *vm, nj njs_int_t -njs_value_length(njs_vm_t *vm, njs_value_t *value, uint64_t *length) +njs_value_length(njs_vm_t *vm, njs_value_t *value, int64_t *length) { njs_string_prop_t string_prop; @@ -697,7 +697,8 @@ static njs_int_t njs_array_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_array_t *array, uint32_t index) { - uint64_t size, length; + int64_t length; + uint64_t size; njs_int_t ret; njs_value_t *setval, value; njs_object_prop_t *prop; diff -r 94d6774e0c03 -r 2a03cd71561a src/njs_value.h --- a/src/njs_value.h Mon Mar 23 19:58:50 2020 +0300 +++ b/src/njs_value.h Thu Mar 26 17:12:16 2020 +0300 @@ -1002,7 +1002,7 @@ njs_array_t *njs_value_enumerate(njs_vm_ njs_object_enum_t kind, njs_object_enum_type_t type, njs_bool_t all); njs_array_t *njs_value_own_enumerate(njs_vm_t *vm, njs_value_t *value, njs_object_enum_t kind, njs_object_enum_type_t type, njs_bool_t all); -njs_int_t njs_value_length(njs_vm_t *vm, njs_value_t *value, uint64_t *dst); +njs_int_t njs_value_length(njs_vm_t *vm, njs_value_t *value, int64_t *dst); const char *njs_type_string(njs_value_type_t type); njs_int_t njs_primitive_value_to_string(njs_vm_t *vm, njs_value_t *dst, @@ -1010,7 +1010,7 @@ njs_int_t njs_primitive_value_to_string( njs_int_t njs_primitive_value_to_chain(njs_vm_t *vm, njs_chb_t *chain, const njs_value_t *src); double njs_string_to_number(const njs_value_t *value, njs_bool_t parse_float); -njs_int_t njs_uint64_to_string(njs_vm_t *vm, njs_value_t *value, uint64_t u64); +njs_int_t njs_int64_to_string(njs_vm_t *vm, njs_value_t *value, int64_t i64); njs_bool_t njs_string_eq(const njs_value_t *v1, const njs_value_t *v2); @@ -1041,7 +1041,7 @@ njs_value_property_i64(njs_vm_t *vm, njs /* FIXME: False-positive in MSAN?. */ njs_msan_unpoison(&key, sizeof(njs_value_t)); - ret = njs_uint64_to_string(vm, &key, index); + ret = njs_int64_to_string(vm, &key, index); if (njs_slow_path(ret != NJS_OK)) { return ret; } @@ -1060,7 +1060,7 @@ njs_value_property_i64_set(njs_vm_t *vm, /* FIXME: False-positive in MSAN?. */ njs_msan_unpoison(&key, sizeof(njs_value_t)); - ret = njs_uint64_to_string(vm, &key, index); + ret = njs_int64_to_string(vm, &key, index); if (njs_slow_path(ret != NJS_OK)) { return ret; } @@ -1079,7 +1079,7 @@ njs_value_property_i64_delete(njs_vm_t * /* FIXME: False-positive in MSAN?. */ njs_msan_unpoison(&key, sizeof(njs_value_t)); - ret = njs_uint64_to_string(vm, &key, index); + ret = njs_int64_to_string(vm, &key, index); if (njs_slow_path(ret != NJS_OK)) { return ret; } diff -r 94d6774e0c03 -r 2a03cd71561a src/njs_value_conversion.h --- a/src/njs_value_conversion.h Mon Mar 23 19:58:50 2020 +0300 +++ b/src/njs_value_conversion.h Thu Mar 26 17:12:16 2020 +0300 @@ -80,7 +80,7 @@ njs_value_to_integer(njs_vm_t *vm, njs_v njs_inline njs_int_t -njs_value_to_length(njs_vm_t *vm, njs_value_t *value, uint64_t *dst) +njs_value_to_length(njs_vm_t *vm, njs_value_t *value, int64_t *dst) { double num; njs_int_t ret; From jan.prachar at gmail.com Thu Mar 26 19:08:01 2020 From: jan.prachar at gmail.com (Jan =?UTF-8?Q?Pracha=C5=99?=) Date: Thu, 26 Mar 2020 20:08:01 +0100 Subject: incorrect upstream max_fails behaviour Message-ID: Hello, the upstream module documentation says: max_fails=number sets the number of unsuccessful attempts to communicate with the server that should happen in the duration set by the fail_timeout parameter to consider the server unavailable for a duration also set by the fail_timeout parameter. And also: fail_timeout=time sets the time during which the specified number of unsuccessful attempts to communicate with the server should happen to consider the server unavailable; Load balancing documentation at http://nginx.org/en/docs/http/load_balancing.html says: The max_fails directive sets the number of consecutive unsuccessful attempts to communicate with the server that should happen during fail_timeout. But I have found that the actual nginx behaviour is different. Every time an upstream fails, peer->accessed and peer->checked is set to now and peers->fails is incremented. peer->checked is set to now also before connecting to upstream, if now - peer->checked > peer->fail_timeout. (1) peer->fails is set to 0 only for sucessful request if peer->accessed < peer->checked, which can happen only if condition (1) was fulfilled. Therefore, peers->fails is set to zero only if no upstream error happens during fail_timeout interval. So for example, if upstream fails once every fail_timeout, after max_fails*fail_timeout will be marked as unavailable. Or if there are no succesful requests to an upstream, peers->fails is incremented with every request independetly on fail_timeout settings. My test confirms that nginx indeed behaves like this. Is the documented behavior only part of the commercial subscription, or am I missing somthing? Best regards, Jan Pracha? From mdounin at mdounin.ru Fri Mar 27 15:04:16 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 27 Mar 2020 18:04:16 +0300 Subject: incorrect upstream max_fails behaviour In-Reply-To: References: Message-ID: <20200327150416.GD3546@mdounin.ru> Hello! On Thu, Mar 26, 2020 at 08:08:01PM +0100, Jan Pracha? wrote: > Hello, > > the upstream module documentation says: > > > max_fails=number > sets the number of unsuccessful attempts to communicate with the server > that should happen in the duration set by the fail_timeout parameter to > consider the server unavailable for a duration also set by the > fail_timeout parameter. > > > And also: > > > fail_timeout=time > sets > the time during which the specified number of unsuccessful attempts to > communicate with the server should happen to consider the server > unavailable; > > > Load balancing documentation at > http://nginx.org/en/docs/http/load_balancing.html says: > > > The max_fails directive sets the number of consecutive unsuccessful > attempts to communicate with the server that should happen during > fail_timeout. > > > But I have found that the actual nginx behaviour is different. Every > time an upstream fails, peer->accessed and peer->checked is set to now > and peers->fails is incremented. peer->checked is set to now also > before connecting to upstream, if > > now - peer->checked > peer->fail_timeout. (1) > > peer->fails is set to 0 only for sucessful request if peer->accessed < > peer->checked, which can happen only if condition (1) was fulfilled. > Therefore, peers->fails is set to zero only if no upstream error > happens during fail_timeout interval. So for example, if upstream fails > once every fail_timeout, after max_fails*fail_timeout will be marked as > unavailable. > > Or if there are no succesful requests to an upstream, peers->fails is > incremented with every request independetly on fail_timeout settings. > My test confirms that nginx indeed behaves like this. > > Is the documented behavior only part of the commercial subscription, or > am I missing somthing? Documentation somewhat oversimplifies things. The fail_timeout setting is essentially a session timeout, and things work as follows: 1. As long as there are failures, the fails counter is incremented. If fail_timeout passes since last failure, the fails counter is reset to 0 on the next successful request. 2. If the fails counter reaches max_fails, no more requests are routed to the peer for fail_timeout time. After fail_timeout passes, one request is allowed. If the request is successful, the fails counter is reset to 0, and further requests to the peer are allowed without any limits. -- Maxim Dounin http://mdounin.ru/ From arut at nginx.com Mon Mar 30 12:36:11 2020 From: arut at nginx.com (Roman Arutyunyan) Date: Mon, 30 Mar 2020 15:36:11 +0300 Subject: [PATCH] Mirror directive supports variable In-Reply-To: References: Message-ID: <20200330123611.l47zqd636rxrht6i@Romans-MacBook-Pro.local> Hello, On Fri, Mar 13, 2020 at 11:29:51PM +0800, ???????? wrote: > # HG changeset patch > # User agile6v > # Date 1584110606 -28800 > # Fri Mar 13 22:43:26 2020 +0800 > # Node ID e4a0277cab79865fde6fefeed9374154449e6948 > # Parent 4eb606b4a5b521603c23223cf8863f3999df743c > mirror directive supports variable. > > diff -r 4eb606b4a5b5 -r e4a0277cab79 src/http/modules/ngx_http_mirror_module.c > --- a/src/http/modules/ngx_http_mirror_module.c Tue Mar 03 18:04:21 2020 +0300 > +++ b/src/http/modules/ngx_http_mirror_module.c Fri Mar 13 22:43:26 2020 +0800 > @@ -149,17 +149,28 @@ > static ngx_int_t > ngx_http_mirror_handler_internal(ngx_http_request_t *r) > { > - ngx_str_t *name; > + ngx_str_t val; > ngx_uint_t i; > ngx_http_request_t *sr; > ngx_http_mirror_loc_conf_t *mlcf; > + ngx_http_complex_value_t *pcv; > > mlcf = ngx_http_get_module_loc_conf(r, ngx_http_mirror_module); > > - name = mlcf->mirror->elts; > + pcv = mlcf->mirror->elts; > > for (i = 0; i < mlcf->mirror->nelts; i++) { > - if (ngx_http_subrequest(r, &name[i], &r->args, &sr, NULL, > + if (ngx_http_complex_value(r, &pcv[i], &val) != NGX_OK) { > + return NGX_HTTP_INTERNAL_SERVER_ERROR; > + } > + > + if (val.len == 0 > + || (val.len == 3 && ngx_strncmp(val.data, "off", 3) == 0)) There's one issue with this line which introduces inconsistency. Currently specifying "off" disables inheriting mirrors on a certain level. Also it cannot be specified together with other mirror directives. But now, if "off" is evaluated from a complex value, the behavior is very different, this mirror is just ignored in runtime, but other mirrors work fine. > + { > + continue; > + } > + > + if (ngx_http_subrequest(r, &val, &r->args, &sr, NULL, > NGX_HTTP_SUBREQUEST_BACKGROUND) > != NGX_OK) > { > @@ -208,9 +219,10 @@ > static char * > ngx_http_mirror(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) > { > - ngx_http_mirror_loc_conf_t *mlcf = conf; > - > - ngx_str_t *value, *s; > + ngx_http_mirror_loc_conf_t *mlcf = conf; > + ngx_http_complex_value_t *pcv, cv; > + ngx_http_compile_complex_value_t ccv; > + ngx_str_t *value; > > value = cf->args->elts; > > @@ -227,19 +239,30 @@ > return "is duplicate"; > } > > + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); > + > + ccv.cf = cf; > + ccv.value = &value[1]; > + ccv.complex_value = &cv; > + > + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { > + return NGX_CONF_ERROR; > + } > + > if (mlcf->mirror == NGX_CONF_UNSET_PTR) { > - mlcf->mirror = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t)); > + mlcf->mirror = ngx_array_create(cf->pool, 4, > + sizeof(ngx_http_complex_value_t)); > if (mlcf->mirror == NULL) { > return NGX_CONF_ERROR; > } > } > > - s = ngx_array_push(mlcf->mirror); > - if (s == NULL) { > + pcv = ngx_array_push(mlcf->mirror); > + if (pcv == NULL) { > return NGX_CONF_ERROR; > } > > - *s = value[1]; > + *pcv = cv; > > return NGX_CONF_OK; > } > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -- Roman Arutyunyan From sangdeuk.kwon at quantil.com Tue Mar 31 04:59:31 2020 From: sangdeuk.kwon at quantil.com (Sangdeuk Kwon) Date: Tue, 31 Mar 2020 13:59:31 +0900 Subject: [PATCH] When cache file is expired, nginx can make a lot of upstream requests. Message-ID: Thank you for your explanation I have a question. Are there any directives for preventing multiple upstream and serving new content? expect case: 1st request: get new content from origin and serve new content. 2nd request: serve new content. 3rd request: serve new content. "proxy_cache_use stale updating" and "proxy_cache_background_update off" case: 1st request: get new content from origin and serve new content. 2nd request: serve stale content. finish 1st request's upstream. 3rd request: serve new content. "proxy_cache_use stale updating" and "proxy_cache_background_update on" case: 1st request: serve stale content and make subrequest for getting new content. 2nd request: serve stale content. finish 1st request's subrequest. 3rd request: serve new content. -------------- next part -------------- An HTML attachment was scrubbed... URL: From arut at nginx.com Tue Mar 31 06:02:37 2020 From: arut at nginx.com (Roman Arutyunyan) Date: Tue, 31 Mar 2020 09:02:37 +0300 Subject: [PATCH] Mirror directive supports variable In-Reply-To: <20200330123611.l47zqd636rxrht6i@Romans-MacBook-Pro.local> References: <20200330123611.l47zqd636rxrht6i@Romans-MacBook-Pro.local> Message-ID: <20200331060237.amviji4g3tlf73h5@Romans-MacBook-Pro.local> On Mon, Mar 30, 2020 at 03:36:11PM +0300, Roman Arutyunyan wrote: > Hello, > > On Fri, Mar 13, 2020 at 11:29:51PM +0800, ???????? wrote: > > # HG changeset patch > > # User agile6v > > # Date 1584110606 -28800 > > # Fri Mar 13 22:43:26 2020 +0800 > > # Node ID e4a0277cab79865fde6fefeed9374154449e6948 > > # Parent 4eb606b4a5b521603c23223cf8863f3999df743c > > mirror directive supports variable. Also, what is the reason why you need variables in the mirror directive? You can do the same thing by creating a static mirror and using rewrite to change uri. [..] -- Roman Arutyunyan From thresh at nginx.com Tue Mar 31 10:52:52 2020 From: thresh at nginx.com (Konstantin Pavlov) Date: Tue, 31 Mar 2020 13:52:52 +0300 Subject: Hardening nginx.service with systemd In-Reply-To: <3A2C245E-43CD-42AC-8244-03E1D6A54DDD@gmail.com> References: <3A2C245E-43CD-42AC-8244-03E1D6A54DDD@gmail.com> Message-ID: <94b11f76-bed0-1ba0-6d2e-3e80860499fe@nginx.com> Hi, Thank you for your contribution! 26.03.2020 16:37, Dulmandakh Sukhbaatar wrote: > Hello, > > I would like to propose to harden nginx.service with systems configurations, and this change uses PrivateDevices=yes, PrivateTmp=yes and ProtectSystem=full configs. And here are excerpts from man systemd.exec man page. > > PrivateDevices=yes > sets up a new /dev mount for the executed processes and only adds API pseudo devices such as /dev/null, /dev/zero or /dev/random (as well as the pseudo TTY subsystem) to it, but no physical devices such as /dev/sda, system memory /dev/mem, system ports /dev/port and others On my Debian system: $ id nginx uid=112(nginx) gid=121(nginx) groups=121(nginx) $ /bin/ls -la /dev/mem /dev/sda /dev/port crw-r----- 1 root kmem 1, 1 Mar 30 20:26 /dev/mem crw-r----- 1 root kmem 1, 4 Mar 30 20:26 /dev/port brw-rw---- 1 root disk 8, 0 Mar 30 20:26 /dev/sda As nginx workers run as unprivileged user, that hardening is already applied as a part of a standard operating system privilege separation. By default nginx master process indeed starts as a root user, but does not do a lot of things which might have a potential security impact. > PrivateTmp=yes > sets up a new file system namespace for the executed processes and mounts private /tmp and /var/tmp directories inside it that is not shared by processes outside of the namespace We already had that enabled some time ago, and it caused non-obvious issues with configurations that use /tmp to store temporary files for different reasons. > ProtectSystem=full > mounts the /usr and /boot directories read-only for processes invoked by this unit. If set to "full", the /etc directory is mounted read-only, too It's effectively read-only as nginx worker processes run under non-privileged users even without that systemd flag, same as for PrivateDevices. > I believe that these configs will harden nginx.service, thus protect OS from security bugs in nginx. All in all, I believe that kind of configuration hardening might make sense in the specific scenarios, but not something we can enforce on all our users by default. -- Konstantin Pavlov https://www.nginx.com/