From mat999 at gmail.com Fri Feb 1 00:04:50 2019 From: mat999 at gmail.com (Mathew Heard) Date: Fri, 1 Feb 2019 11:04:50 +1100 Subject: SO_REUSEPORT Message-ID: Hi All, Hit a rather strange issue today on a production service where during a configuration reload (evident by the worker processes in the process of being shutdown). During this reload a percentage of connections were not getting accepted (and hence not processed). I was able to confirm that none of the processes were accepting the connections. Our configuration includes the reuseport option so my theory was that for some reason connections were still being routed to the shutting down worker, which was not accepting new connections. This has a striking resemblance to the HAProxy issues in previous years with connections received during live configuration reloads. Software Versions: nginx version: nginx/1.15.8 linux kernel: 4.9.2 Does anyone have an idea of where to look for this issue? Or have you see anything like it before? I am aware the kernel is a bit on the older side, anyone seen any relevant issues / patches? Regards, Mathew -------------- next part -------------- An HTML attachment was scrubbed... URL: From vbart at nginx.com Fri Feb 1 14:04:06 2019 From: vbart at nginx.com (Valentin V. Bartenev) Date: Fri, 01 Feb 2019 17:04:06 +0300 Subject: SO_REUSEPORT In-Reply-To: References: Message-ID: <5826888.2P5O6QZTls@vbart-workstation> On Friday 01 February 2019 11:04:50 Mathew Heard wrote: > Hi All, > > Hit a rather strange issue today on a production service where during a > configuration reload (evident by the worker processes in the process of > being shutdown). During this reload a percentage of connections were not > getting accepted (and hence not processed). I was able to confirm that none > of the processes were accepting the connections. > > Our configuration includes the reuseport option so my theory was that for > some reason connections were still being routed to the shutting down > worker, which was not accepting new connections. > > This has a striking resemblance to the HAProxy issues in previous years > with connections received during live configuration reloads. HAProxy case is irrelevant here, as nginx uses SO_REUSEPORT for another purpose and in a different way. > > Software Versions: > nginx version: nginx/1.15.8 > linux kernel: 4.9.2 > > Does anyone have an idea of where to look for this issue? Or have you see > anything like it before? > > I am aware the kernel is a bit on the older side, anyone seen any relevant > issues / patches? > [..] Have you changed the number of worker processes? If you're using SO_REUSEPORT and has decreased the number of workers, then it's expected that some connections will be lost on Linux during reload. wbr, Valentin V. Bartenev From mat999 at gmail.com Fri Feb 1 14:06:46 2019 From: mat999 at gmail.com (Mathew Heard) Date: Sat, 2 Feb 2019 01:06:46 +1100 Subject: SO_REUSEPORT In-Reply-To: <5826888.2P5O6QZTls@vbart-workstation> References: <5826888.2P5O6QZTls@vbart-workstation> Message-ID: No I did not change the number of workers, or anything core. The configuration change would have been related to a specific server block (add/remove/update) as carried out by our tooling. On Sat, Feb 2, 2019 at 1:04 AM Valentin V. Bartenev wrote: > On Friday 01 February 2019 11:04:50 Mathew Heard wrote: > > Hi All, > > > > Hit a rather strange issue today on a production service where during a > > configuration reload (evident by the worker processes in the process of > > being shutdown). During this reload a percentage of connections were not > > getting accepted (and hence not processed). I was able to confirm that > none > > of the processes were accepting the connections. > > > > Our configuration includes the reuseport option so my theory was that for > > some reason connections were still being routed to the shutting down > > worker, which was not accepting new connections. > > > > This has a striking resemblance to the HAProxy issues in previous years > > with connections received during live configuration reloads. > > HAProxy case is irrelevant here, as nginx uses SO_REUSEPORT for another > purpose and in a different way. > > > > > Software Versions: > > nginx version: nginx/1.15.8 > > linux kernel: 4.9.2 > > > > Does anyone have an idea of where to look for this issue? Or have you see > > anything like it before? > > > > I am aware the kernel is a bit on the older side, anyone seen any > relevant > > issues / patches? > > > [..] > > Have you changed the number of worker processes? > > If you're using SO_REUSEPORT and has decreased the number of workers, > then it's expected that some connections will be lost on Linux during > reload. > > wbr, Valentin V. Bartenev > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Fri Feb 1 14:13:32 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 1 Feb 2019 17:13:32 +0300 Subject: SO_REUSEPORT In-Reply-To: References: Message-ID: <20190201141331.GT1877@mdounin.ru> Hello! On Fri, Feb 01, 2019 at 11:04:50AM +1100, Mathew Heard wrote: > Hit a rather strange issue today on a production service where during a > configuration reload (evident by the worker processes in the process of > being shutdown). During this reload a percentage of connections were not > getting accepted (and hence not processed). I was able to confirm that none > of the processes were accepting the connections. > > Our configuration includes the reuseport option so my theory was that for > some reason connections were still being routed to the shutting down > worker, which was not accepting new connections. With "listen ... reuseport" nginx creates a listening socket for each worker process. And on configuration reload these sockets are passed to the new worker processes, so there shouldn't be problems. The only "risky" case is reducing the number of worker process. Reducing the number of worker process means that some of the listening sockets will be closed, and on Linux this can result in rejecting some of the connection requests sitting in these sockets when these sockets are closed. (AFAIK, this is properly handled only on DragonFly BSD, where connection requests are redistributed to other sockets in such a case.) This is, however, not about "a percentage of connections", but about a small number of connections sitting in the listening socket when old worker process is instructed to exit gracefully and closes the listening socket. If you've changed the number of worker processes and seen several connections dropped - this may be the case. If you've seen a percentage of connections being dropped for some time - likely there is another problem elsewhere. In particular, one common caveat with "listen ... reuseport" is that listening socket no longer prevents multiple instances of nginx (or event different servers) from running on the same port. As a result, accidentally starting another nginx instance can easily screw up things. -- Maxim Dounin http://mdounin.ru/ From mat999 at gmail.com Fri Feb 1 14:21:12 2019 From: mat999 at gmail.com (Mathew Heard) Date: Sat, 2 Feb 2019 01:21:12 +1100 Subject: SO_REUSEPORT In-Reply-To: <20190201141331.GT1877@mdounin.ru> References: <20190201141331.GT1877@mdounin.ru> Message-ID: >> If you've seen a >> percentage of connections being dropped for some time - likely >> there is another problem elsewhere. That's definitely what I observed. It was around 50% of this customers connections and strace on all workers (including the shutting down worker) did not show the missed connections at the accept level (grep on unique testing IP). The only thing strange I was able to note was the one process remaining in "worker is shutting down state" (it's not uncommon for us to have a few workers hanging around for a while due to websocket or similar connections keeping workers open). This is why I formulated this theory. Further reloads did not resolve the issue, it took a restart of the nginx process to get everything back to normal. As far as I am aware no other nginx process was started on the server (systemd manages nginx). On Sat, Feb 2, 2019 at 1:13 AM Maxim Dounin wrote: > Hello! > > On Fri, Feb 01, 2019 at 11:04:50AM +1100, Mathew Heard wrote: > > > Hit a rather strange issue today on a production service where during a > > configuration reload (evident by the worker processes in the process of > > being shutdown). During this reload a percentage of connections were not > > getting accepted (and hence not processed). I was able to confirm that > none > > of the processes were accepting the connections. > > > > Our configuration includes the reuseport option so my theory was that for > > some reason connections were still being routed to the shutting down > > worker, which was not accepting new connections. > > With "listen ... reuseport" nginx creates a listening socket for > each worker process. And on configuration reload these sockets > are passed to the new worker processes, so there shouldn't be > problems. > > The only "risky" case is reducing the number of worker process. > Reducing the number of worker process means that some of the > listening sockets will be closed, and on Linux this can result > in rejecting some of the connection requests sitting in these > sockets when these sockets are closed. (AFAIK, this is properly > handled only on DragonFly BSD, where connection requests are > redistributed to other sockets in such a case.) > > This is, however, not about "a percentage of connections", but > about a small number of connections sitting in the listening > socket when old worker process is instructed to exit gracefully > and closes the listening socket. > > If you've changed the number of worker processes and seen several > connections dropped - this may be the case. If you've seen a > percentage of connections being dropped for some time - likely > there is another problem elsewhere. > > In particular, one common caveat with "listen ... reuseport" is > that listening socket no longer prevents multiple instances of > nginx (or event different servers) from running on the same port. > As a result, accidentally starting another nginx instance can > easily screw up things. > > -- > Maxim Dounin > http://mdounin.ru/ > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Fri Feb 1 14:41:03 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 1 Feb 2019 17:41:03 +0300 Subject: GeoIP dependency on GeoIP Legacy databases? In-Reply-To: <21a2e216-60b4-9dc3-ee72-9c362e766b0d@thomas-ward.net> References: <154896928899.7316.14645247001036849529.reportbug@noether.olasd.eu> <21a2e216-60b4-9dc3-ee72-9c362e766b0d@thomas-ward.net> Message-ID: <20190201144103.GU1877@mdounin.ru> Hello! On Thu, Jan 31, 2019 at 04:34:58PM -0500, Thomas Ward wrote: > A bug report originated on Debian [1] about the GeoIP module that's > shipped with NGINX's source code. > > It makes note that the GeoIP database in Legacy format is not available, > deprecated in 2018 and discontinued as of 2019.? This means that > non-paying customers can't get the database files.? [2] > > Does this impact the geoip module shipped with NGINX as the Legacy > databases are no longer available and discontinued?? If so, does NGINX > have a timeline to replace this or provide alternate mechanisms? Obviously enough, there are no plans to remove the geoip module, as legacy databases are still available to paying customers. Likely at some point the geoip module will be adapted to work with new databases as well, though there are no certain plans yet. Note well that there is the geo module, and databases in the CSV format can be easily converted to the format understood by the geo module. -- Maxim Dounin http://mdounin.ru/ From xeioex at nginx.com Fri Feb 1 14:43:33 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 01 Feb 2019 14:43:33 +0000 Subject: [njs] Simplified parser builtin function. Message-ID: details: https://hg.nginx.org/njs/rev/05379e4d6844 branches: changeset: 749:05379e4d6844 user: hongzhidao date: Fri Feb 01 19:48:30 2019 +0800 description: Simplified parser builtin function. diffstat: njs/njs_parser.c | 4 ---- njs/njs_variable.c | 1 - 2 files changed, 0 insertions(+), 5 deletions(-) diffs (32 lines): diff -r 9f2779de4cdd -r 05379e4d6844 njs/njs_parser.c --- a/njs/njs_parser.c Tue Jan 29 16:30:13 2019 +0800 +++ b/njs/njs_parser.c Fri Feb 01 19:48:30 2019 +0800 @@ -2095,8 +2095,6 @@ njs_parser_builtin_object(njs_vm_t *vm, return NJS_TOKEN_ERROR; } - node->scope = parser->scope; - parser->node = node; return njs_parser_token(parser); @@ -2139,8 +2137,6 @@ njs_parser_builtin_function(njs_vm_t *vm return NJS_TOKEN_ERROR; } - node->scope = parser->scope; - parser->node = node; return njs_parser_token(parser); diff -r 9f2779de4cdd -r 05379e4d6844 njs/njs_variable.c --- a/njs/njs_variable.c Tue Jan 29 16:30:13 2019 +0800 +++ b/njs/njs_variable.c Fri Feb 01 19:48:30 2019 +0800 @@ -132,7 +132,6 @@ njs_variable_reference(njs_vm_t *vm, njs ret = njs_name_copy(vm, &vr->name, name); if (nxt_fast_path(ret == NXT_OK)) { - node->scope = scope; vr->hash = hash; vr->type = type; From xeioex at nginx.com Fri Feb 1 15:26:48 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 01 Feb 2019 15:26:48 +0000 Subject: [njs] Fixed parsing object literals. Message-ID: details: https://hg.nginx.org/njs/rev/94fc00372558 branches: changeset: 750:94fc00372558 user: Dmitry Volyntsev date: Fri Feb 01 18:09:02 2019 +0300 description: Fixed parsing object literals. diffstat: njs/njs_parser.c | 15 ++++++++++----- njs/test/njs_unit_test.c | 12 ++++++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) diffs (56 lines): diff -r 05379e4d6844 -r 94fc00372558 njs/njs_parser.c --- a/njs/njs_parser.c Fri Feb 01 19:48:30 2019 +0800 +++ b/njs/njs_parser.c Fri Feb 01 18:09:02 2019 +0300 @@ -2163,9 +2163,18 @@ njs_parser_object(njs_vm_t *vm, njs_pars token = njs_parser_property_name(vm, parser, token); break; - default: + case NJS_TOKEN_NUMBER: + case NJS_TOKEN_STRING: + case NJS_TOKEN_ESCAPE_STRING: token = njs_parser_terminal(vm, parser, token); break; + + default: + return NJS_TOKEN_ILLEGAL; + } + + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return token; } object = njs_parser_node_new(vm, parser, NJS_TOKEN_OBJECT_VALUE); @@ -2183,10 +2192,6 @@ njs_parser_object(njs_vm_t *vm, njs_pars propref->left = object; propref->right = parser->node; - if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { - return token; - } - token = njs_parser_match(vm, parser, token, NJS_TOKEN_COLON); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; diff -r 05379e4d6844 -r 94fc00372558 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Fri Feb 01 19:48:30 2019 +0800 +++ b/njs/test/njs_unit_test.c Fri Feb 01 18:09:02 2019 +0300 @@ -2816,6 +2816,18 @@ static njs_unit_test_t njs_test[] = { nxt_string("var o = Object.create({a:1}); o.a = 2; delete o.a; o.a"), nxt_string("1") }, + { nxt_string("njs.dump({break:1,3:2,'a':4,\"b\":2,true:1,null:0})"), + nxt_string("{break:1,3:2,a:4,b:2,true:1,null:0}") }, + + { nxt_string("var o1 = {a:1,b:2}, o2 = {c:3}; o1.a + o2.c"), + nxt_string("4") }, + + { nxt_string("({[]:1})"), + nxt_string("SyntaxError: Unexpected token \"[\" in 1") }, + + { nxt_string("({'AB\n\\cd':1})['AB\n\\cd']"), + nxt_string("1") }, + /* Inheritance. */ { nxt_string("function Foo() {this.bar = 10;}; Foo.prototype.bar = 42; " From xeioex at nginx.com Fri Feb 1 15:26:48 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 01 Feb 2019 15:26:48 +0000 Subject: [njs] Improved parsing object literals. Message-ID: details: https://hg.nginx.org/njs/rev/476bb5ed52e8 branches: changeset: 751:476bb5ed52e8 user: Dmitry Volyntsev date: Fri Feb 01 18:26:18 2019 +0300 description: Improved parsing object literals. diffstat: njs/njs_parser.c | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-) diffs (31 lines): diff -r 94fc00372558 -r 476bb5ed52e8 njs/njs_parser.c --- a/njs/njs_parser.c Fri Feb 01 18:09:02 2019 +0300 +++ b/njs/njs_parser.c Fri Feb 01 18:26:18 2019 +0300 @@ -2151,6 +2151,13 @@ njs_parser_object(njs_vm_t *vm, njs_pars left = NULL; + object = njs_parser_node_new(vm, parser, NJS_TOKEN_OBJECT_VALUE); + if (nxt_slow_path(object == NULL)) { + return NJS_TOKEN_ERROR; + } + + object->u.object = obj; + for ( ;; ) { token = njs_parser_property_token(parser); @@ -2177,13 +2184,6 @@ njs_parser_object(njs_vm_t *vm, njs_pars return token; } - object = njs_parser_node_new(vm, parser, NJS_TOKEN_OBJECT_VALUE); - if (nxt_slow_path(object == NULL)) { - return NJS_TOKEN_ERROR; - } - - object->u.object = obj; - propref = njs_parser_node_new(vm, parser, NJS_TOKEN_PROPERTY); if (nxt_slow_path(propref == NULL)) { return NJS_TOKEN_ERROR; From mdounin at mdounin.ru Fri Feb 1 15:48:22 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 1 Feb 2019 18:48:22 +0300 Subject: SO_REUSEPORT In-Reply-To: References: <20190201141331.GT1877@mdounin.ru> Message-ID: <20190201154822.GV1877@mdounin.ru> Hello! On Sat, Feb 02, 2019 at 01:21:12AM +1100, Mathew Heard wrote: > >> If you've seen a > >> percentage of connections being dropped for some time - likely > >> there is another problem elsewhere. > > That's definitely what I observed. It was around 50% of this customers > connections and strace on all workers (including the shutting down worker) > did not show the missed connections at the accept level (grep on unique > testing IP). On Linux, "ss -nltp" can show important details on listening sockets and how they are handled, including the number of connectionion requests in each socket's backlog, as well as processes having the socket open (note: run under root to get the list). You may want to use it next time you'll see a problem. > The only thing strange I was able to note was the one process remaining in > "worker is shutting down state" (it's not uncommon for us to have a few > workers hanging around for a while due to websocket or similar connections > keeping workers open). This is why I formulated this theory. > > Further reloads did not resolve the issue, it took a restart of the nginx > process to get everything back to normal. > > As far as I am aware no other nginx process was started on the server > (systemd manages nginx). Well, "ps -alx | grep nginx" output is much more definitive than "systemd manages nginx". Depending on the actual systemd configuration used, it certainly can easily result in multiple nginx instances being started. Not to mention that starting another instance directly is certainly possible too. -- Maxim Dounin http://mdounin.ru/ From xeioex at nginx.com Sat Feb 2 15:48:18 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Sat, 02 Feb 2019 15:48:18 +0000 Subject: [njs] Improved njs_parser_statement_chain(). Message-ID: details: https://hg.nginx.org/njs/rev/596d26bb5fea branches: changeset: 752:596d26bb5fea user: hongzhidao date: Sat Feb 02 14:21:26 2019 +0800 description: Improved njs_parser_statement_chain(). diffstat: njs/njs_generator.c | 4 +- njs/njs_parser.c | 63 +++++++++++++++++++++++++++++++++------------------- njs/njs_parser.h | 2 +- 3 files changed, 43 insertions(+), 26 deletions(-) diffs (208 lines): diff -r 476bb5ed52e8 -r 596d26bb5fea njs/njs_generator.c --- a/njs/njs_generator.c Fri Feb 01 18:26:18 2019 +0300 +++ b/njs/njs_generator.c Sat Feb 02 14:21:26 2019 +0800 @@ -2348,12 +2348,12 @@ njs_generate_scope(njs_vm_t *vm, njs_gen generator->code_start = p; generator->code_end = p; - ret = njs_generate_argument_closures(vm, generator, scope->node); + ret = njs_generate_argument_closures(vm, generator, scope->top); if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; } - if (nxt_slow_path(njs_generator(vm, generator, scope->node) != NXT_OK)) { + if (nxt_slow_path(njs_generator(vm, generator, scope->top) != NXT_OK)) { return NXT_ERROR; } diff -r 476bb5ed52e8 -r 596d26bb5fea njs/njs_parser.c --- a/njs/njs_parser.c Fri Feb 01 18:26:18 2019 +0300 +++ b/njs/njs_parser.c Sat Feb 02 14:21:26 2019 +0800 @@ -14,7 +14,7 @@ static njs_ret_t njs_parser_scope_begin( njs_scope_t type); static void njs_parser_scope_end(njs_vm_t *vm, njs_parser_t *parser); static njs_token_t njs_parser_statement_chain(njs_vm_t *vm, - njs_parser_t *parser, njs_token_t token); + njs_parser_t *parser, njs_token_t token, njs_parser_node_t **dest); static njs_token_t njs_parser_statement(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token); static njs_token_t njs_parser_block_statement(njs_vm_t *vm, @@ -66,6 +66,16 @@ static njs_token_t njs_parser_unexpected njs_parser_t *parser, njs_token_t token); +#define njs_parser_chain_current(parser) \ + ((parser)->node) + +#define njs_parser_chain_top(parser) \ + ((parser)->scope->top) + +#define njs_parser_chain_top_set(parser, node) \ + (parser)->scope->top = node + + nxt_int_t njs_parser(njs_vm_t *vm, njs_parser_t *parser, njs_parser_t *prev) { @@ -118,7 +128,8 @@ njs_parser(njs_vm_t *vm, njs_parser_t *p while (token != NJS_TOKEN_END) { - token = njs_parser_statement_chain(vm, parser, token); + token = njs_parser_statement_chain(vm, parser, token, + &njs_parser_chain_top(parser)); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return NXT_ERROR; } @@ -129,7 +140,7 @@ njs_parser(njs_vm_t *vm, njs_parser_t *p } } - node = parser->node; + node = njs_parser_chain_top(parser); if (node == NULL) { /* Empty string, just semicolons or variables declarations. */ @@ -138,12 +149,12 @@ njs_parser(njs_vm_t *vm, njs_parser_t *p if (nxt_slow_path(node == NULL)) { return NXT_ERROR; } + + njs_parser_chain_top_set(parser, node); } node->token = NJS_TOKEN_END; - parser->scope->node = node; - return NXT_OK; } @@ -183,6 +194,7 @@ njs_parser_scope_begin(njs_vm_t *vm, njs } scope->type = type; + scope->top = NULL; if (type == NJS_SCOPE_FUNCTION) { scope->next_index[0] = type; @@ -249,11 +261,11 @@ njs_parser_scope_end(njs_vm_t *vm, njs_p static njs_token_t njs_parser_statement_chain(njs_vm_t *vm, njs_parser_t *parser, - njs_token_t token) + njs_token_t token, njs_parser_node_t **dest) { njs_parser_node_t *node, *last; - last = parser->node; + last = *dest; token = njs_parser_statement(vm, parser, token); @@ -269,7 +281,7 @@ njs_parser_statement_chain(njs_vm_t *vm, node->left = last; node->right = parser->node; - parser->node = node; + *dest = node; while (token == NJS_TOKEN_SEMICOLON) { token = njs_parser_token(parser); @@ -407,7 +419,8 @@ njs_parser_block_statement(njs_vm_t *vm, parser->node = NULL; while (token != NJS_TOKEN_CLOSE_BRACE) { - token = njs_parser_statement_chain(vm, parser, token); + token = njs_parser_statement_chain(vm, parser, token, + &njs_parser_chain_current(parser)); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -625,7 +638,7 @@ njs_parser_function_lambda(njs_vm_t *vm, njs_ret_t ret; njs_index_t index; njs_variable_t *arg; - njs_parser_node_t *node, *body, *last, *parent; + njs_parser_node_t *node, *body, *last, *parent, *return_node; ret = njs_parser_scope_begin(vm, parser, NJS_SCOPE_FUNCTION); if (nxt_slow_path(ret != NXT_OK)) { @@ -707,7 +720,8 @@ njs_parser_function_lambda(njs_vm_t *vm, parser->node = NULL; while (token != NJS_TOKEN_CLOSE_BRACE) { - token = njs_parser_statement_chain(vm, parser, token); + token = njs_parser_statement_chain(vm, parser, token, + &njs_parser_chain_top(parser)); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -719,7 +733,7 @@ njs_parser_function_lambda(njs_vm_t *vm, } last = NULL; - body = parser->node; + body = njs_parser_chain_top(parser); if (body != NULL) { /* Take the last function body statement. */ @@ -739,23 +753,25 @@ njs_parser_function_lambda(njs_vm_t *vm, * There is no function body or the last function body * body statement is not "return" statement. */ + return_node = njs_parser_node_new(vm, parser, NJS_TOKEN_RETURN); + if (nxt_slow_path(return_node == NULL)) { + return NJS_TOKEN_ERROR; + } + node = njs_parser_node_new(vm, parser, NJS_TOKEN_STATEMENT); if (nxt_slow_path(node == NULL)) { return NJS_TOKEN_ERROR; } - node->left = parser->node; - node->right = njs_parser_node_new(vm, parser, NJS_TOKEN_RETURN); - if (nxt_slow_path(node->right == NULL)) { - return NJS_TOKEN_ERROR; - } - - parser->node = node; + node->left = body; + node->right = return_node; + + njs_parser_chain_top_set(parser, node); + + body = node; } - parent->right = parser->node; - - parser->scope->node = parser->node; + parent->right = body; parser->node = parent; @@ -1066,7 +1082,8 @@ njs_parser_switch_statement(njs_vm_t *vm return NJS_TOKEN_ILLEGAL; } - token = njs_parser_statement_chain(vm, parser, token); + token = njs_parser_statement_chain(vm, parser, token, + &njs_parser_chain_current(parser)); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } diff -r 476bb5ed52e8 -r 596d26bb5fea njs/njs_parser.h --- a/njs/njs_parser.h Fri Feb 01 18:26:18 2019 +0300 +++ b/njs/njs_parser.h Sat Feb 02 14:21:26 2019 +0800 @@ -232,7 +232,7 @@ typedef struct { struct njs_parser_scope_s { - njs_parser_node_t *node; + njs_parser_node_t *top; nxt_queue_link_t link; nxt_queue_t nested; From xeioex at nginx.com Sun Feb 3 09:40:49 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Sun, 03 Feb 2019 09:40:49 +0000 Subject: [njs] Introduced njs_vm_invoke(). Message-ID: details: https://hg.nginx.org/njs/rev/d57755edf40b branches: changeset: 753:d57755edf40b user: hongzhidao date: Sat Feb 02 16:01:39 2019 +0800 description: Introduced njs_vm_invoke(). diffstat: njs/njs.c | 19 ++++++++++++++++--- 1 files changed, 16 insertions(+), 3 deletions(-) diffs (46 lines): diff -r 596d26bb5fea -r d57755edf40b njs/njs.c --- a/njs/njs.c Sat Feb 02 14:21:26 2019 +0800 +++ b/njs/njs.c Sat Feb 02 16:01:39 2019 +0800 @@ -10,6 +10,8 @@ static nxt_int_t njs_vm_init(njs_vm_t *vm); +static nxt_int_t njs_vm_invoke(njs_vm_t *vm, njs_function_t *function, + const njs_value_t *args, nxt_uint_t nargs, njs_index_t retval); static nxt_int_t njs_vm_handle_events(njs_vm_t *vm); @@ -455,6 +457,14 @@ nxt_int_t njs_vm_call(njs_vm_t *vm, njs_function_t *function, const njs_value_t *args, nxt_uint_t nargs) { + return njs_vm_invoke(vm, function, args, nargs, NJS_INDEX_GLOBAL_RETVAL); +} + + +static nxt_int_t +njs_vm_invoke(njs_vm_t *vm, njs_function_t *function, const njs_value_t *args, + nxt_uint_t nargs, njs_index_t retval) +{ u_char *current; njs_ret_t ret; njs_value_t *this; @@ -465,12 +475,15 @@ njs_vm_call(njs_vm_t *vm, njs_function_t vm->current = (u_char *) njs_continuation_nexus; - ret = njs_function_activate(vm, function, this, args, nargs, - NJS_INDEX_GLOBAL_RETVAL, + ret = njs_function_activate(vm, function, this, args, nargs, retval, sizeof(njs_vmcode_generic_t)); if (nxt_fast_path(ret == NJS_APPLIED)) { - ret = njs_vm_start(vm); + ret = njs_vmcode_interpreter(vm); + + if (ret == NJS_STOP) { + ret = NXT_OK; + } } vm->current = current; From xeioex at nginx.com Mon Feb 4 07:35:37 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 04 Feb 2019 07:35:37 +0000 Subject: [njs] Improved exception creation. Message-ID: details: https://hg.nginx.org/njs/rev/83581029a022 branches: changeset: 754:83581029a022 user: hongzhidao date: Mon Feb 04 05:26:42 2019 +0800 description: Improved exception creation. diffstat: njs/njs.c | 2 +- njs/njs_error.c | 55 ++++++++++++++++++++++++++++++------------------------- njs/njs_error.h | 4 +++- njs/njs_vm.c | 2 +- 4 files changed, 35 insertions(+), 28 deletions(-) diffs (138 lines): diff -r d57755edf40b -r 83581029a022 njs/njs.c --- a/njs/njs.c Sat Feb 02 16:01:39 2019 +0800 +++ b/njs/njs.c Mon Feb 04 05:26:42 2019 +0800 @@ -652,7 +652,7 @@ njs_vm_retval_set(njs_vm_t *vm, const nj nxt_noinline void njs_vm_memory_error(njs_vm_t *vm) { - njs_set_memory_error(vm, &vm->retval); + njs_memory_error_set(vm, &vm->retval); } diff -r d57755edf40b -r 83581029a022 njs/njs_error.c --- a/njs/njs_error.c Sat Feb 02 16:01:39 2019 +0800 +++ b/njs/njs_error.c Mon Feb 04 05:26:42 2019 +0800 @@ -15,38 +15,43 @@ static const njs_value_t njs_error_name void +njs_error_new(njs_vm_t *vm, njs_value_type_t type, u_char *start, size_t size) +{ + nxt_int_t ret; + njs_value_t string; + njs_object_t *error; + + ret = njs_string_new(vm, &string, start, size, size); + if (nxt_slow_path(ret != NXT_OK)) { + return; + } + + error = njs_error_alloc(vm, type, NULL, &string); + + if (nxt_fast_path(error != NULL)) { + vm->retval.data.u.object = error; + vm->retval.type = type; + vm->retval.data.truth = 1; + } +} + + +void njs_exception_error_create(njs_vm_t *vm, njs_value_type_t type, const char* fmt, ...) { - size_t size; - va_list args; - nxt_int_t ret; - njs_value_t string; - njs_object_t *error; - u_char buf[256], *p; + va_list args; + u_char buf[256], *p; + + p = buf; if (fmt != NULL) { va_start(args, fmt); p = nxt_vsprintf(buf, buf + sizeof(buf), fmt, args); va_end(args); - - size = p - buf; - - } else { - size = 0; } - ret = njs_string_new(vm, &string, (const u_char *) buf, size, size); - if (nxt_slow_path(ret != NXT_OK)) { - return; - } - - error = njs_error_alloc(vm, type, NULL, &string); - if (nxt_fast_path(error != NULL)) { - vm->retval.data.u.object = error; - vm->retval.type = type; - vm->retval.data.truth = 1; - } + njs_error_new(vm, type, buf, p - buf); } @@ -467,7 +472,7 @@ const njs_object_init_t njs_uri_error_c void -njs_set_memory_error(njs_vm_t *vm, njs_value_t *value) +njs_memory_error_set(njs_vm_t *vm, njs_value_t *value) { njs_object_t *object; njs_object_prototype_t *prototypes; @@ -497,7 +502,7 @@ njs_set_memory_error(njs_vm_t *vm, njs_v void njs_memory_error(njs_vm_t *vm) { - njs_set_memory_error(vm, &vm->retval); + njs_memory_error_set(vm, &vm->retval); } @@ -505,7 +510,7 @@ njs_ret_t njs_memory_error_constructor(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) { - njs_set_memory_error(vm, &vm->retval); + njs_memory_error_set(vm, &vm->retval); return NXT_OK; } diff -r d57755edf40b -r 83581029a022 njs/njs_error.h --- a/njs/njs_error.h Sat Feb 02 16:01:39 2019 +0800 +++ b/njs/njs_error.h Mon Feb 04 05:26:42 2019 +0800 @@ -26,11 +26,13 @@ #define njs_uri_error(vm, fmt, ...) \ njs_exception_error_create(vm, NJS_OBJECT_URI_ERROR, fmt, ##__VA_ARGS__) +void njs_error_new(njs_vm_t *vm, njs_value_type_t type, u_char *start, + size_t size); void njs_exception_error_create(njs_vm_t *vm, njs_value_type_t type, const char* fmt, ...); void njs_memory_error(njs_vm_t *vm); -void njs_set_memory_error(njs_vm_t *vm, njs_value_t *value); +void njs_memory_error_set(njs_vm_t *vm, njs_value_t *value); njs_object_t *njs_error_alloc(njs_vm_t *vm, njs_value_type_t type, const njs_value_t *name, const njs_value_t *message); diff -r d57755edf40b -r 83581029a022 njs/njs_vm.c --- a/njs/njs_vm.c Sat Feb 02 16:01:39 2019 +0800 +++ b/njs/njs_vm.c Mon Feb 04 05:26:42 2019 +0800 @@ -3358,7 +3358,7 @@ njs_value_error_set(njs_vm_t *vm, njs_va memory_error: - njs_set_memory_error(vm, value); + njs_memory_error_set(vm, value); } From xeioex at nginx.com Mon Feb 4 08:33:53 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 04 Feb 2019 08:33:53 +0000 Subject: [njs] Reporting filename in parser errors. Message-ID: details: https://hg.nginx.org/njs/rev/06e1b1790f9a branches: changeset: 755:06e1b1790f9a user: hongzhidao date: Mon Feb 04 05:33:19 2019 +0800 description: Reporting filename in parser errors. diffstat: njs/njs.c | 1 + njs/njs.h | 1 + njs/njs_parser.c | 69 ++++++++++++++++++++++++++++++++++--------------------- njs/njs_parser.h | 14 ++++++++--- njs/njs_shell.c | 5 ++++ nxt/nxt_types.h | 2 + 6 files changed, 61 insertions(+), 31 deletions(-) diffs (173 lines): diff -r 83581029a022 -r 06e1b1790f9a njs/njs.c --- a/njs/njs.c Mon Feb 04 05:26:42 2019 +0800 +++ b/njs/njs.c Mon Feb 04 05:33:19 2019 +0800 @@ -244,6 +244,7 @@ njs_vm_compile(njs_vm_t *vm, u_char **st lexer->start = *start; lexer->end = end; lexer->line = 1; + lexer->file = vm->options.file; lexer->keywords_hash = vm->shared->keywords_hash; if (vm->backtrace != NULL) { diff -r 83581029a022 -r 06e1b1790f9a njs/njs.h --- a/njs/njs.h Mon Feb 04 05:26:42 2019 +0800 +++ b/njs/njs.h Mon Feb 04 05:33:19 2019 +0800 @@ -141,6 +141,7 @@ typedef struct { njs_external_ptr_t external; njs_vm_shared_t *shared; njs_vm_ops_t *ops; + nxt_str_t file; uint8_t trailer; /* 1 bit */ uint8_t init; /* 1 bit */ diff -r 83581029a022 -r 06e1b1790f9a njs/njs_parser.c --- a/njs/njs_parser.c Mon Feb 04 05:26:42 2019 +0800 +++ b/njs/njs_parser.c Mon Feb 04 05:33:19 2019 +0800 @@ -2604,9 +2604,10 @@ u_char * njs_parser_trace_handler(nxt_trace_t *trace, nxt_trace_data_t *td, u_char *start) { - u_char *p; - size_t size; - njs_vm_t *vm; + u_char *p; + size_t size; + njs_vm_t *vm; + njs_lexer_t *lexer; size = nxt_length("InternalError: "); memcpy(start, "InternalError: ", size); @@ -2618,7 +2619,15 @@ njs_parser_trace_handler(nxt_trace_t *tr p = trace->handler(trace, td, p); if (vm->parser != NULL) { - njs_internal_error(vm, "%s in %uD", start, vm->parser->lexer->line); + lexer = vm->parser->lexer; + + if (lexer->file.start != NULL) { + njs_internal_error(vm, "%s in %V:%uD", start, &lexer->file, + lexer->line); + } else { + njs_internal_error(vm, "%s in %uD", start, lexer->line); + } + } else { njs_internal_error(vm, "%s", start); } @@ -2628,30 +2637,36 @@ njs_parser_trace_handler(nxt_trace_t *tr void -njs_parser_syntax_error(njs_vm_t *vm, njs_parser_t *parser, const char* fmt, - ...) -{ - va_list args; - u_char buf[256], *end; +njs_parser_error(njs_vm_t *vm, njs_parser_t *parser, njs_value_type_t type, + const char *fmt, ...) + { + size_t width; + u_char *p, *end; + u_char msg[NXT_MAX_ERROR_STR]; + va_list args; + njs_lexer_t *lexer; + + p = msg; + end = msg + NXT_MAX_ERROR_STR; va_start(args, fmt); - end = nxt_vsprintf(buf, buf + sizeof(buf), fmt, args); + p = nxt_vsprintf(p, end, fmt, args); va_end(args); - njs_syntax_error(vm, "%*s in %uD", end - buf, buf, parser->lexer->line); -} - - -void -njs_parser_ref_error(njs_vm_t *vm, njs_parser_t *parser, const char* fmt, - ...) -{ - va_list args; - u_char buf[256], *end; - - va_start(args, fmt); - end = nxt_vsprintf(buf, buf + sizeof(buf), fmt, args); - va_end(args); - - njs_reference_error(vm, "%*s in %uD", end - buf, buf, parser->lexer->line); -} + lexer = parser->lexer; + + width = nxt_length(" in ") + lexer->file.length + NXT_INT_T_LEN; + + if (p > end - width) { + p = end - width; + } + + if (lexer->file.start != NULL) { + p = nxt_sprintf(p, end, " in %V:%uD", &lexer->file, lexer->line); + + } else { + p = nxt_sprintf(p, end, " in %uD", lexer->line); + } + + njs_error_new(vm, type, msg, p - msg); + } diff -r 83581029a022 -r 06e1b1790f9a njs/njs_parser.h --- a/njs/njs_parser.h Mon Feb 04 05:26:42 2019 +0800 +++ b/njs/njs_parser.h Mon Feb 04 05:33:19 2019 +0800 @@ -221,6 +221,8 @@ typedef struct { nxt_lvlhsh_t keywords_hash; + nxt_str_t file; + u_char *start; u_char *prev_start; u_char *end; @@ -327,10 +329,14 @@ njs_index_t njs_variable_index(njs_vm_t nxt_bool_t njs_parser_has_side_effect(njs_parser_node_t *node); u_char *njs_parser_trace_handler(nxt_trace_t *trace, nxt_trace_data_t *td, u_char *start); -void njs_parser_syntax_error(njs_vm_t *vm, njs_parser_t *parser, - const char* fmt, ...); -void njs_parser_ref_error(njs_vm_t *vm, njs_parser_t *parser, const char* fmt, - ...); +void njs_parser_error(njs_vm_t *vm, njs_parser_t *parser, + njs_value_type_t type, const char *fmt, ...); + +#define njs_parser_syntax_error(vm, parser, fmt, ...) \ + njs_parser_error(vm, parser, NJS_OBJECT_SYNTAX_ERROR, fmt, ##__VA_ARGS__) + +#define njs_parser_ref_error(vm, parser, fmt, ...) \ + njs_parser_error(vm, parser, NJS_OBJECT_REF_ERROR, fmt, ##__VA_ARGS__) nxt_inline njs_parser_node_t * diff -r 83581029a022 -r 06e1b1790f9a njs/njs_shell.c --- a/njs/njs_shell.c Mon Feb 04 05:26:42 2019 +0800 +++ b/njs/njs_shell.c Mon Feb 04 05:33:19 2019 +0800 @@ -215,6 +215,11 @@ main(int argc, char **argv) nxt_memzero(&vm_options, sizeof(njs_vm_opt_t)); + if (opts.file != NULL) { + vm_options.file.start = (u_char *) opts.file; + vm_options.file.length = strlen(opts.file); + } + vm_options.init = !opts.interactive; vm_options.accumulative = opts.interactive; vm_options.backtrace = 1; diff -r 83581029a022 -r 06e1b1790f9a nxt/nxt_types.h --- a/nxt/nxt_types.h Mon Feb 04 05:26:42 2019 +0800 +++ b/nxt/nxt_types.h Mon Feb 04 05:33:19 2019 +0800 @@ -116,5 +116,7 @@ typedef pid_t nxt_pid_t; #define NXT_DOUBLE_LEN (1 + DBL_MAX_10_EXP) +#define NXT_MAX_ERROR_STR 2048 + #endif /* _NXT_TYPES_H_INCLUDED_ */ From xeioex at nginx.com Mon Feb 4 08:33:54 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 04 Feb 2019 08:33:54 +0000 Subject: [njs] Renaming njs_exception_error_create() with njs_error_fmt_new(). Message-ID: details: https://hg.nginx.org/njs/rev/db4c9c8efff5 branches: changeset: 756:db4c9c8efff5 user: hongzhidao date: Mon Feb 04 06:22:51 2019 +0800 description: Renaming njs_exception_error_create() with njs_error_fmt_new(). diffstat: njs/njs_error.c | 5 ++--- njs/njs_error.h | 18 +++++++++--------- 2 files changed, 11 insertions(+), 12 deletions(-) diffs (56 lines): diff -r 06e1b1790f9a -r db4c9c8efff5 njs/njs_error.c --- a/njs/njs_error.c Mon Feb 04 05:33:19 2019 +0800 +++ b/njs/njs_error.c Mon Feb 04 06:22:51 2019 +0800 @@ -37,11 +37,10 @@ njs_error_new(njs_vm_t *vm, njs_value_ty void -njs_exception_error_create(njs_vm_t *vm, njs_value_type_t type, - const char* fmt, ...) +njs_error_fmt_new(njs_vm_t *vm, njs_value_type_t type, const char* fmt, ...) { va_list args; - u_char buf[256], *p; + u_char buf[NXT_MAX_ERROR_STR], *p; p = buf; diff -r 06e1b1790f9a -r db4c9c8efff5 njs/njs_error.h --- a/njs/njs_error.h Mon Feb 04 05:33:19 2019 +0800 +++ b/njs/njs_error.h Mon Feb 04 06:22:51 2019 +0800 @@ -9,26 +9,26 @@ #define njs_error(vm, fmt, ...) \ - njs_exception_error_create(vm, NJS_OBJECT_ERROR, fmt, ##__VA_ARGS__) + njs_error_fmt_new(vm, NJS_OBJECT_ERROR, fmt, ##__VA_ARGS__) #define njs_eval_error(vm, fmt, ...) \ - njs_exception_error_create(vm, NJS_OBJECT_EVAL_ERROR, fmt, ##__VA_ARGS__) + njs_error_fmt_new(vm, NJS_OBJECT_EVAL_ERROR, fmt, ##__VA_ARGS__) #define njs_internal_error(vm, fmt, ...) \ - njs_exception_error_create(vm, NJS_OBJECT_INTERNAL_ERROR, fmt, \ + njs_error_fmt_new(vm, NJS_OBJECT_INTERNAL_ERROR, fmt, \ ##__VA_ARGS__) #define njs_range_error(vm, fmt, ...) \ - njs_exception_error_create(vm, NJS_OBJECT_RANGE_ERROR, fmt, ##__VA_ARGS__) + njs_error_fmt_new(vm, NJS_OBJECT_RANGE_ERROR, fmt, ##__VA_ARGS__) #define njs_reference_error(vm, fmt, ...) \ - njs_exception_error_create(vm, NJS_OBJECT_REF_ERROR, fmt, ##__VA_ARGS__) + njs_error_fmt_new(vm, NJS_OBJECT_REF_ERROR, fmt, ##__VA_ARGS__) #define njs_syntax_error(vm, fmt, ...) \ - njs_exception_error_create(vm, NJS_OBJECT_SYNTAX_ERROR, fmt, ##__VA_ARGS__) + njs_error_fmt_new(vm, NJS_OBJECT_SYNTAX_ERROR, fmt, ##__VA_ARGS__) #define njs_type_error(vm, fmt, ...) \ - njs_exception_error_create(vm, NJS_OBJECT_TYPE_ERROR, fmt, ##__VA_ARGS__) + njs_error_fmt_new(vm, NJS_OBJECT_TYPE_ERROR, fmt, ##__VA_ARGS__) #define njs_uri_error(vm, fmt, ...) \ - njs_exception_error_create(vm, NJS_OBJECT_URI_ERROR, fmt, ##__VA_ARGS__) + njs_error_fmt_new(vm, NJS_OBJECT_URI_ERROR, fmt, ##__VA_ARGS__) void njs_error_new(njs_vm_t *vm, njs_value_type_t type, u_char *start, size_t size); -void njs_exception_error_create(njs_vm_t *vm, njs_value_type_t type, +void njs_error_fmt_new(njs_vm_t *vm, njs_value_type_t type, const char* fmt, ...); void njs_memory_error(njs_vm_t *vm); From xeioex at nginx.com Mon Feb 4 09:09:51 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 04 Feb 2019 09:09:51 +0000 Subject: [njs] Fixed building with Apple clang. Message-ID: details: https://hg.nginx.org/njs/rev/6c66f34a89b9 branches: changeset: 757:6c66f34a89b9 user: Dmitry Volyntsev date: Mon Feb 04 11:45:24 2019 +0300 description: Fixed building with Apple clang. This closes #89 issue on Github. diffstat: njs/njs_shell.c | 1 - nxt/nxt_time.c | 1 + 2 files changed, 1 insertions(+), 1 deletions(-) diffs (22 lines): diff -r db4c9c8efff5 -r 6c66f34a89b9 njs/njs_shell.c --- a/njs/njs_shell.c Mon Feb 04 06:22:51 2019 +0800 +++ b/njs/njs_shell.c Mon Feb 04 11:45:24 2019 +0300 @@ -14,7 +14,6 @@ #include #include #include -#include #include #include diff -r db4c9c8efff5 -r 6c66f34a89b9 nxt/nxt_time.c --- a/nxt/nxt_time.c Mon Feb 04 06:22:51 2019 +0800 +++ b/nxt/nxt_time.c Mon Feb 04 11:45:24 2019 +0300 @@ -10,6 +10,7 @@ #include #include +#include uint64_t nxt_time(void) From pluknet at nginx.com Mon Feb 4 13:32:31 2019 From: pluknet at nginx.com (Sergey Kandaurov) Date: Mon, 04 Feb 2019 13:32:31 +0000 Subject: [njs] Removed a surplus argument to the parser exception macro. Message-ID: details: https://hg.nginx.org/njs/rev/e8cd6be6d57e branches: changeset: 758:e8cd6be6d57e user: Sergey Kandaurov date: Mon Feb 04 16:30:27 2019 +0300 description: Removed a surplus argument to the parser exception macro. While here, fixed nearby style. diffstat: njs/njs_parser_expression.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff -r 6c66f34a89b9 -r e8cd6be6d57e njs/njs_parser_expression.c --- a/njs/njs_parser_expression.c Mon Feb 04 11:45:24 2019 +0300 +++ b/njs/njs_parser_expression.c Mon Feb 04 16:30:27 2019 +0300 @@ -648,8 +648,8 @@ njs_parser_unary_expression(njs_vm_t *vm case NJS_TOKEN_NAME: case NJS_TOKEN_UNDEFINED: - njs_parser_syntax_error(vm, parser, - "Delete of an unqualified identifier", NULL); + njs_parser_syntax_error(vm, parser, + "Delete of an unqualified identifier"); return NJS_TOKEN_ILLEGAL; From nzt4567 at gmx.com Tue Feb 5 12:25:25 2019 From: nzt4567 at gmx.com (Tomas Kvasnicka) Date: Tue, 5 Feb 2019 13:25:25 +0100 Subject: SO_REUSEPORT In-Reply-To: <20190201154822.GV1877@mdounin.ru> References: <20190201141331.GT1877@mdounin.ru> <20190201154822.GV1877@mdounin.ru> Message-ID: Hi! I just wanted to add my 2 cents here?. - We are facing a very similar issue. During reloads of reuseport enabled configuration it sometimes happens that no workers accept new connections, bandwidth basically drops to 0 and it all reverts back to normal within few seconds. Hurts but not deadly. - Our nginx uses the Intel QAT card which allows only a limited number of user-space processes using the card at any given moment. Therefore, our HUP handler has been patched quite a bit to shutdown workers one-by-one and then use the ngx_reap_child to start a new worker with updated configuration. - We only use the reuseport option in combination with the QAT-based servers (servers with the patched HUP behaviour). Therefore, I am not yet sure if changes in the reload mechanism are the cause of the issue - still investigating. - Thanks a lot for the ?ss -nltp? tip. - Currently testing the ?iptables-drop-empty-ACKs? workaround. - No two nginx masters are running simultaneously. - Reducing the number of workers is also not happening, due to the changes described above - the new value of worker_processes will simply be ignored. Thanks, Tomas From fabio.ancona at gmail.com Tue Feb 5 13:02:32 2019 From: fabio.ancona at gmail.com (Fabio Ancona) Date: Tue, 5 Feb 2019 14:02:32 +0100 Subject: Add ".apk" file extension in "mime.types" file Message-ID: Hi all. As reported here "https://github.com/nginx/nginx/pull/39" the ".apk" file extension is not managed by nginx. Please add "application/vnd.android.package-archive apk;" to the "mime.types" file. I have tested it on my nginx/1.15.8 and .apk files are correctly downloaded. Before, without "apk" in mime.types, nginx sent .apk as "text". Thank you. Best Regards. Fabio Ancona -------------- next part -------------- An HTML attachment was scrubbed... URL: From xeioex at nginx.com Tue Feb 5 13:30:34 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 05 Feb 2019 13:30:34 +0000 Subject: [njs] Using nxt_sprintf() instead of sprintf() in backtraces. Message-ID: details: https://hg.nginx.org/njs/rev/1568a0d46b0d branches: changeset: 759:1568a0d46b0d user: hongzhidao date: Mon Feb 04 23:00:25 2019 +0800 description: Using nxt_sprintf() instead of sprintf() in backtraces. diffstat: njs/njs_builtin.c | 83 ++++++++++++++++-------------------------------------- njs/njs_extern.c | 7 +-- njs/njs_vm.c | 26 ++++++++-------- 3 files changed, 41 insertions(+), 75 deletions(-) diffs (218 lines): diff -r e8cd6be6d57e -r 1568a0d46b0d njs/njs_builtin.c --- a/njs/njs_builtin.c Mon Feb 04 16:30:27 2019 +0300 +++ b/njs/njs_builtin.c Mon Feb 04 23:00:25 2019 +0800 @@ -978,69 +978,32 @@ nxt_int_t njs_builtin_match_native_function(njs_vm_t *vm, njs_function_t *function, nxt_str_t *name) { - char *buf; size_t len; - nxt_str_t string; + nxt_str_t string, middle; nxt_int_t rc; const njs_object_init_t *obj, **p; const njs_object_prop_t *prop; const njs_function_init_t *fun; + middle = nxt_string_value("."); + rc = njs_builtin_match(njs_object_init, function, &prop, &obj); if (rc == NXT_OK) { - njs_string_get(&prop->name, &string); - len = obj->name.length + string.length + sizeof("."); - - buf = nxt_mp_zalloc(vm->mem_pool, len); - if (buf == NULL) { - return NXT_ERROR; - } - - snprintf(buf, len, "%s.%s", obj->name.start, string.start); - - name->length = len; - name->start = (u_char *) buf; - - return NXT_OK; + goto found; } rc = njs_builtin_match(njs_prototype_init, function, &prop, &obj); if (rc == NXT_OK) { - njs_string_get(&prop->name, &string); - len = obj->name.length + string.length + sizeof(".prototype."); - - buf = nxt_mp_zalloc(vm->mem_pool, len); - if (buf == NULL) { - return NXT_ERROR; - } - - snprintf(buf, len, "%s.prototype.%s", obj->name.start, string.start); - - name->length = len; - name->start = (u_char *) buf; - - return NXT_OK; + middle = nxt_string_value(".prototype."); + goto found; } rc = njs_builtin_match(njs_constructor_init, function, &prop, &obj); if (rc == NXT_OK) { - njs_string_get(&prop->name, &string); - len = obj->name.length + string.length + sizeof("."); - - buf = nxt_mp_zalloc(vm->mem_pool, len); - if (buf == NULL) { - return NXT_ERROR; - } - - snprintf(buf, len, "%s.%s", obj->name.start, string.start); - - name->length = len; - name->start = (u_char *) buf; - - return NXT_OK; + goto found; } fun = njs_native_functions; @@ -1056,23 +1019,27 @@ njs_builtin_match_native_function(njs_vm rc = njs_builtin_match(njs_module_init, function, &prop, &obj); if (rc == NXT_OK) { - njs_string_get(&prop->name, &string); - len = obj->name.length + string.length + sizeof("."); - - buf = nxt_mp_zalloc(vm->mem_pool, len); - if (buf == NULL) { - return NXT_ERROR; - } - - snprintf(buf, len, "%s.%s", obj->name.start, string.start); - - name->length = len; - name->start = (u_char *) buf; - - return NXT_OK; + goto found; } return NXT_DECLINED; + +found: + + njs_string_get(&prop->name, &string); + + len = obj->name.length + middle.length + string.length; + + name->length = len; + name->start = nxt_mp_zalloc(vm->mem_pool, len); + if (name->start == NULL) { + return NXT_ERROR; + } + + nxt_sprintf(name->start, name->start + len, + "%V%V%V", &obj->name, &middle, &string); + + return NXT_OK; } diff -r e8cd6be6d57e -r 1568a0d46b0d njs/njs_extern.c --- a/njs/njs_extern.c Mon Feb 04 16:30:27 2019 +0300 +++ b/njs/njs_extern.c Mon Feb 04 23:00:25 2019 +0800 @@ -326,7 +326,7 @@ static nxt_int_t njs_external_match(njs_vm_t *vm, njs_function_native_t func, njs_extern_t *ext, nxt_str_t *name, njs_extern_part_t *head, njs_extern_part_t *ppart) { - char *buf, *p; + u_char *buf, *p; size_t len; nxt_int_t ret; njs_extern_t *prop; @@ -374,12 +374,11 @@ found: p = buf; for (pr = head; pr != NULL; pr = pr->next) { - p += snprintf(p, buf + len - p, "%.*s.", (int) pr->str.length, - pr->str.start); + p = nxt_sprintf(p, buf + len, "%V.", &pr->str); } name->start = (u_char *) buf; - name->length = len; + name->length = len - 1; return NXT_OK; } diff -r e8cd6be6d57e -r 1568a0d46b0d njs/njs_vm.c --- a/njs/njs_vm.c Mon Feb 04 16:30:27 2019 +0300 +++ b/njs/njs_vm.c Mon Feb 04 23:00:25 2019 +0800 @@ -3049,7 +3049,7 @@ njs_ret_t njs_vm_value_to_ext_string(njs_vm_t *vm, nxt_str_t *dst, const njs_value_t *src, nxt_uint_t handle_exception) { - u_char *p, *start; + u_char *p, *start, *end; size_t len, size, count; njs_ret_t ret; nxt_uint_t i, exception; @@ -3135,16 +3135,17 @@ again: } else { if (count != 0) { - len += sizeof(" repeats times\n") + 10; + len += nxt_length(" repeats times\n") + + NXT_INT_T_LEN; count = 0; } if (be[i].line != 0) { - len += sizeof(" at (:)\n") + 10 + len += nxt_length(" at (:)\n") + NXT_INT_T_LEN + be[i].name.length; } else { - len += sizeof(" at (native)\n") + len += nxt_length(" at (native)\n") + be[i].name.length; } } @@ -3159,6 +3160,7 @@ again: } start = p; + end = start + len; p = nxt_cpymem(p, dst->start, dst->length); *p++ = '\n'; @@ -3174,20 +3176,18 @@ again: } else { if (count != 0) { - p += sprintf((char *) p, - " repeats %zu times\n", count); - count =0; + p = nxt_sprintf(p, end, + " repeats %uz times\n", count); + count = 0; } if (be[i].line != 0) { - p += sprintf((char *) p, " at %.*s (:%u)\n", - (int) be[i].name.length, - be[i].name.start, be[i].line); + p = nxt_sprintf(p, end, " at %V (:%uD)\n", + &be[i].name, be[i].line); } else { - p += sprintf((char *) p, " at %.*s (native)\n", - (int) be[i].name.length, - be[i].name.start); + p = nxt_sprintf(p, end, " at %V (native)\n", + &be[i].name); } } From thresh at nginx.com Tue Feb 5 15:52:42 2019 From: thresh at nginx.com (Konstantin Pavlov) Date: Tue, 5 Feb 2019 18:52:42 +0300 Subject: Add ".apk" file extension in "mime.types" file In-Reply-To: References: Message-ID: <16e4044b-d0a0-b6d0-f1d1-60260bd226d0@nginx.com> Hi Fabio, 05.02.2019 16:02, Fabio Ancona wrote: > Hi all. > As reported here "https://github.com/nginx/nginx/pull/39" the ".apk" > file extension is not managed by nginx. > Please add "application/vnd.android.package-archive? ? ? ? ? apk;" to > the "mime.types" file. > > I have tested it on my nginx/1.15.8 and .apk files are correctly > downloaded. Before, without "apk" in mime.types, nginx sent .apk as "text". > Thank you. > Best Regards. Wouldnt a simple "default_type application/octet-stream" be enough, which is a default for most nginx packages ? I've been personally running it for years on https://nightlies.videolan.org/ and never received a single complaint from the testers. Overall the consensus seems to be that the content type must be widely used on the internet to justify its addition. It's hard to judge the popularity for a delivery method predominatly used for closed-garden software shops, but what is the software of question that expects such a mime type? Thank you, -- Konstantin Pavlov https://www.nginx.com/ From xeioex at nginx.com Tue Feb 5 16:07:31 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 05 Feb 2019 16:07:31 +0000 Subject: [njs] Reporting filename in generator errors. Message-ID: details: https://hg.nginx.org/njs/rev/334b9d9e4357 branches: changeset: 760:334b9d9e4357 user: hongzhidao date: Tue Feb 05 00:53:18 2019 +0800 description: Reporting filename in generator errors. diffstat: njs/njs_generator.c | 42 +++++++++++++++++++++++++++++++----------- njs/njs_parser.c | 13 ++++++++++--- njs/njs_parser.h | 2 ++ 3 files changed, 43 insertions(+), 14 deletions(-) diffs (137 lines): diff -r 1568a0d46b0d -r 334b9d9e4357 njs/njs_generator.c --- a/njs/njs_generator.c Mon Feb 04 23:00:25 2019 +0800 +++ b/njs/njs_generator.c Tue Feb 05 00:53:18 2019 +0800 @@ -163,8 +163,8 @@ static nxt_int_t njs_generate_function_d njs_function_lambda_t *lambda, uint32_t line); -static void njs_generate_syntax_error(njs_vm_t *vm, uint32_t token_line, - const char* fmt, ...); +static void njs_generate_syntax_error(njs_vm_t *vm, njs_parser_node_t *node, + const char *fmt, ...); #define njs_generate_code(generator, type, code) \ @@ -1407,8 +1407,7 @@ njs_generate_continue_statement(njs_vm_t syntax_error: - njs_generate_syntax_error(vm, node->token_line, - "Illegal continue statement"); + njs_generate_syntax_error(vm, node, "Illegal continue statement"); return NXT_ERROR; } @@ -1456,7 +1455,7 @@ njs_generate_break_statement(njs_vm_t *v syntax_error: - njs_generate_syntax_error(vm, node->token_line, "Illegal break statement"); + njs_generate_syntax_error(vm, node, "Illegal break statement"); return NXT_ERROR; } @@ -3162,15 +3161,36 @@ njs_generate_function_debug(njs_vm_t *vm static void -njs_generate_syntax_error(njs_vm_t *vm, uint32_t token_line, - const char* fmt, ...) +njs_generate_syntax_error(njs_vm_t *vm, njs_parser_node_t *node, + const char *fmt, ...) { - va_list args; - u_char buf[256], *end; + size_t width; + u_char msg[NXT_MAX_ERROR_STR]; + u_char *p, *end; + va_list args; + njs_parser_scope_t *scope; + + p = msg; + end = msg + NXT_MAX_ERROR_STR; va_start(args, fmt); - end = nxt_vsprintf(buf, buf + sizeof(buf), fmt, args); + p = nxt_vsprintf(p, end, fmt, args); va_end(args); - njs_syntax_error(vm, "%*s in %uD", end - buf, buf, token_line); + scope = node->scope; + + width = nxt_length(" in ") + scope->file.length + NXT_INT_T_LEN; + + if (p > end - width) { + p = end - width; + } + + if (scope->file.start != NULL) { + p = nxt_sprintf(p, end, " in %V:%uD", &scope->file, node->token_line); + + } else { + p = nxt_sprintf(p, end, " in %uD", node->token_line); + } + + njs_error_new(vm, NJS_OBJECT_SYNTAX_ERROR, msg, p - msg); } diff -r 1568a0d46b0d -r 334b9d9e4357 njs/njs_parser.c --- a/njs/njs_parser.c Mon Feb 04 23:00:25 2019 +0800 +++ b/njs/njs_parser.c Tue Feb 05 00:53:18 2019 +0800 @@ -162,6 +162,7 @@ njs_parser(njs_vm_t *vm, njs_parser_t *p static njs_ret_t njs_parser_scope_begin(njs_vm_t *vm, njs_parser_t *parser, njs_scope_t type) { + nxt_int_t ret; nxt_uint_t nesting; nxt_array_t *values; njs_parser_scope_t *scope, *parent; @@ -188,13 +189,12 @@ njs_parser_scope_begin(njs_vm_t *vm, njs } } - scope = nxt_mp_alloc(vm->mem_pool, sizeof(njs_parser_scope_t)); + scope = nxt_mp_zalloc(vm->mem_pool, sizeof(njs_parser_scope_t)); if (nxt_slow_path(scope == NULL)) { return NXT_ERROR; } scope->type = type; - scope->top = NULL; if (type == NJS_SCOPE_FUNCTION) { scope->next_index[0] = type; @@ -230,6 +230,13 @@ njs_parser_scope_begin(njs_vm_t *vm, njs scope->values[0] = values; scope->values[1] = NULL; + if (parser->lexer->file.start != NULL) { + ret = njs_name_copy(vm, &scope->file, &parser->lexer->file); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } + } + parent = parser->scope; scope->parent = parent; parser->scope = scope; @@ -2639,7 +2646,7 @@ njs_parser_trace_handler(nxt_trace_t *tr void njs_parser_error(njs_vm_t *vm, njs_parser_t *parser, njs_value_type_t type, const char *fmt, ...) - { +{ size_t width; u_char *p, *end; u_char msg[NXT_MAX_ERROR_STR]; diff -r 1568a0d46b0d -r 334b9d9e4357 njs/njs_parser.h --- a/njs/njs_parser.h Mon Feb 04 23:00:25 2019 +0800 +++ b/njs/njs_parser.h Tue Feb 05 00:53:18 2019 +0800 @@ -249,6 +249,8 @@ struct njs_parser_scope_s { nxt_array_t *values[2]; /* Array of njs_value_t. */ njs_index_t next_index[2]; + nxt_str_t file; + njs_scope_t type:8; uint8_t nesting; /* 4 bits */ uint8_t argument_closures; From xeioex at nginx.com Tue Feb 5 16:07:31 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 05 Feb 2019 16:07:31 +0000 Subject: [njs] Reporting filename in runtime errors. Message-ID: details: https://hg.nginx.org/njs/rev/4dfc639287f0 branches: changeset: 761:4dfc639287f0 user: hongzhidao date: Tue Feb 05 01:07:45 2019 +0800 description: Reporting filename in runtime errors. diffstat: njs/njs_generator.c | 13 ++++++------- njs/njs_vm.c | 42 ++++++++++++++++++++++++------------------ njs/njs_vm.h | 6 ++++-- 3 files changed, 34 insertions(+), 27 deletions(-) diffs (166 lines): diff -r 334b9d9e4357 -r 4dfc639287f0 njs/njs_generator.c --- a/njs/njs_generator.c Tue Feb 05 00:53:18 2019 +0800 +++ b/njs/njs_generator.c Tue Feb 05 01:07:45 2019 +0800 @@ -160,8 +160,7 @@ static nxt_noinline nxt_int_t njs_genera njs_generator_t *generator, njs_index_t index); static nxt_int_t njs_generate_function_debug(njs_vm_t *vm, nxt_str_t *name, - njs_function_lambda_t *lambda, uint32_t line); - + njs_function_lambda_t *lambda, njs_parser_node_t *node); static void njs_generate_syntax_error(njs_vm_t *vm, njs_parser_node_t *node, const char *fmt, ...); @@ -1888,7 +1887,7 @@ njs_generate_function(njs_vm_t *vm, njs_ } if (vm->debug != NULL) { - ret = njs_generate_function_debug(vm, NULL, lambda, node->token_line); + ret = njs_generate_function_debug(vm, NULL, lambda, node); if (nxt_slow_path(ret != NXT_OK)) { return ret; } @@ -2269,8 +2268,7 @@ njs_generate_function_declaration(njs_vm } if (vm->debug != NULL) { - ret = njs_generate_function_debug(vm, &var->name, lambda, - node->token_line); + ret = njs_generate_function_debug(vm, &var->name, lambda, node); } return ret; @@ -3137,7 +3135,7 @@ njs_generate_index_release(njs_vm_t *vm, static nxt_int_t njs_generate_function_debug(njs_vm_t *vm, nxt_str_t *name, - njs_function_lambda_t *lambda, uint32_t line) + njs_function_lambda_t *lambda, njs_parser_node_t *node) { njs_function_debug_t *debug; @@ -3154,7 +3152,8 @@ njs_generate_function_debug(njs_vm_t *vm } debug->lambda = lambda; - debug->line = line; + debug->line = node->token_line; + debug->file = node->scope->file; return NXT_OK; } diff -r 334b9d9e4357 -r 4dfc639287f0 njs/njs_vm.c --- a/njs/njs_vm.c Tue Feb 05 00:53:18 2019 +0800 +++ b/njs/njs_vm.c Tue Feb 05 01:07:45 2019 +0800 @@ -3127,8 +3127,8 @@ again: be = backtrace->start; for (i = 0; i < backtrace->items; i++) { - if (i != 0 && prev->name.start == be[i].name.start - && prev->line == be[i].line) + if (i != 0 && prev->name.start == be->name.start + && prev->line == be->line) { count++; @@ -3140,17 +3140,18 @@ again: count = 0; } - if (be[i].line != 0) { - len += nxt_length(" at (:)\n") + NXT_INT_T_LEN - + be[i].name.length; + len += be->name.length + nxt_length(" at ()\n"); + + if (be->line != 0) { + len += be->file.length + NXT_INT_T_LEN + 1; } else { - len += nxt_length(" at (native)\n") - + be[i].name.length; + len += nxt_length("native"); } } - prev = &be[i]; + prev = be; + be++; } p = nxt_mp_alloc(vm->mem_pool, len); @@ -3168,30 +3169,34 @@ again: count = 0; prev = NULL; + be = backtrace->start; + for (i = 0; i < backtrace->items; i++) { - if (i != 0 && prev->name.start == be[i].name.start - && prev->line == be[i].line) + if (i != 0 && prev->name.start == be->name.start + && prev->line == be->line) { count++; } else { if (count != 0) { - p = nxt_sprintf(p, end, - " repeats %uz times\n", count); + p = nxt_sprintf(p, end, " repeats %uz times\n", + count); count = 0; } - if (be[i].line != 0) { - p = nxt_sprintf(p, end, " at %V (:%uD)\n", - &be[i].name, be[i].line); + p = nxt_sprintf(p, end, " at %V ", &be->name); + + if (be->line != 0) { + p = nxt_sprintf(p, end, "(%V:%uD)\n", &be->file, + be->line); } else { - p = nxt_sprintf(p, end, " at %V (native)\n", - &be[i].name); + p = nxt_sprintf(p, end, "(native)\n"); } } - prev = &be[i]; + prev = be; + be++; } dst->start = start; @@ -3549,6 +3554,7 @@ njs_vm_add_backtrace_entry(njs_vm_t *vm, be->name = entry_anonymous; } + be->file = debug_entry[i].file; be->line = debug_entry[i].line; return NXT_OK; diff -r 334b9d9e4357 -r 4dfc639287f0 njs/njs_vm.h --- a/njs/njs_vm.h Tue Feb 05 00:53:18 2019 +0800 +++ b/njs/njs_vm.h Tue Feb 05 01:07:45 2019 +0800 @@ -352,8 +352,9 @@ typedef union { typedef struct { - nxt_str_t name; - uint32_t line; + nxt_str_t name; + nxt_str_t file; + uint32_t line; } njs_backtrace_entry_t; @@ -1012,6 +1013,7 @@ typedef struct { typedef struct { uint32_t line; + nxt_str_t file; nxt_str_t name; njs_function_lambda_t *lambda; } njs_function_debug_t; From xeioex at nginx.com Tue Feb 5 16:41:21 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 05 Feb 2019 16:41:21 +0000 Subject: [njs] HTTP: setting default content type in sendHeader(). Message-ID: details: https://hg.nginx.org/njs/rev/3b8ea515add6 branches: changeset: 762:3b8ea515add6 user: Dmitry Volyntsev date: Tue Feb 05 19:27:24 2019 +0300 description: HTTP: setting default content type in sendHeader(). diffstat: nginx/ngx_http_js_module.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diffs (14 lines): diff -r 4dfc639287f0 -r 3b8ea515add6 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Tue Feb 05 01:07:45 2019 +0800 +++ b/nginx/ngx_http_js_module.c Tue Feb 05 19:27:24 2019 +0300 @@ -1035,6 +1035,10 @@ ngx_http_js_ext_send_header(njs_vm_t *vm return NJS_ERROR; } + if (ngx_http_set_content_type(r) != NGX_OK) { + return NJS_ERROR; + } + if (ngx_http_send_header(r) == NGX_ERROR) { return NJS_ERROR; } From xeioex at nginx.com Wed Feb 6 12:40:17 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 06 Feb 2019 12:40:17 +0000 Subject: [njs] Shell: improved filenames reporting in exceptions. Message-ID: details: https://hg.nginx.org/njs/rev/2c7a52ca206e branches: changeset: 763:2c7a52ca206e user: hongzhidao date: Wed Feb 06 12:27:41 2019 +0800 description: Shell: improved filenames reporting in exceptions. diffstat: Makefile | 2 ++ njs/njs_core.h | 1 + njs/njs_shell.c | 7 ++++--- njs/test/njs_expect_test.exp | 4 ++-- nxt/Makefile | 13 +++++++++++++ nxt/nxt_file.c | 33 +++++++++++++++++++++++++++++++++ nxt/nxt_file.h | 14 ++++++++++++++ 7 files changed, 69 insertions(+), 5 deletions(-) diffs (164 lines): diff -r 3b8ea515add6 -r 2c7a52ca206e Makefile --- a/Makefile Tue Feb 05 19:27:24 2019 +0300 +++ b/Makefile Wed Feb 06 12:27:41 2019 +0800 @@ -49,6 +49,7 @@ NXT_BUILDDIR = build $(NXT_BUILDDIR)/nxt_sha2.o \ $(NXT_BUILDDIR)/nxt_pcre.o \ $(NXT_BUILDDIR)/nxt_time.o \ + $(NXT_BUILDDIR)/nxt_file.o \ $(NXT_BUILDDIR)/nxt_malloc.o \ $(NXT_BUILDDIR)/nxt_mp.o \ $(NXT_BUILDDIR)/nxt_sprintf.o \ @@ -96,6 +97,7 @@ NXT_BUILDDIR = build $(NXT_BUILDDIR)/nxt_sha2.o \ $(NXT_BUILDDIR)/nxt_pcre.o \ $(NXT_BUILDDIR)/nxt_time.o \ + $(NXT_BUILDDIR)/nxt_file.o \ $(NXT_BUILDDIR)/nxt_malloc.o \ $(NXT_BUILDDIR)/nxt_mp.o \ $(NXT_BUILDDIR)/nxt_sprintf.o \ diff -r 3b8ea515add6 -r 2c7a52ca206e njs/njs_core.h --- a/njs/njs_core.h Tue Feb 05 19:27:24 2019 +0300 +++ b/njs/njs_core.h Wed Feb 06 12:27:41 2019 +0800 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include diff -r 3b8ea515add6 -r 2c7a52ca206e njs/njs_shell.c --- a/njs/njs_shell.c Tue Feb 05 19:27:24 2019 +0300 +++ b/njs/njs_shell.c Wed Feb 06 12:27:41 2019 +0800 @@ -215,8 +215,10 @@ main(int argc, char **argv) nxt_memzero(&vm_options, sizeof(njs_vm_opt_t)); if (opts.file != NULL) { - vm_options.file.start = (u_char *) opts.file; - vm_options.file.length = strlen(opts.file); + nxt_file_name(&vm_options.file, opts.file); + + } else { + vm_options.file = nxt_string_value("shell"); } vm_options.init = !opts.interactive; @@ -1071,4 +1073,3 @@ lvlhsh_pool_free(void *pool, void *p, si { nxt_mp_free(pool, p); } - diff -r 3b8ea515add6 -r 2c7a52ca206e njs/test/njs_expect_test.exp --- a/njs/test/njs_expect_test.exp Tue Feb 05 19:27:24 2019 +0300 +++ b/njs/test/njs_expect_test.exp Wed Feb 06 12:27:41 2019 +0800 @@ -269,7 +269,7 @@ njs_test { {"JSON.parse(Error())\r\n" "JSON.parse(Error())\r\nSyntaxError: Unexpected token at position 0*at JSON.parse (native)"} {"JSON.parse(Error()\r\n" - "JSON.parse(Error()\r\nSyntaxError: Unexpected token \"\" in 1"} + "JSON.parse(Error()\r\nSyntaxError: Unexpected token \"\" in shell:1"} } njs_test { @@ -281,7 +281,7 @@ njs_test { njs_test { {"(function() { throw 'test' })()\r\n" - "test\r\n at anonymous (:1)"} + "test\r\n at anonymous (shell:1)"} } # Non-ASCII characters diff -r 3b8ea515add6 -r 2c7a52ca206e nxt/Makefile --- a/nxt/Makefile Tue Feb 05 19:27:24 2019 +0300 +++ b/nxt/Makefile Wed Feb 06 12:27:41 2019 +0800 @@ -21,6 +21,7 @@ NXT_LIB = nxt $(NXT_BUILDDIR)/nxt_malloc.o \ $(NXT_BUILDDIR)/nxt_trace.o \ $(NXT_BUILDDIR)/nxt_time.o \ + $(NXT_BUILDDIR)/nxt_file.o \ $(NXT_BUILDDIR)/nxt_mp.o \ $(NXT_BUILDDIR)/nxt_sprintf.o \ @@ -40,6 +41,7 @@ NXT_LIB = nxt $(NXT_BUILDDIR)/nxt_pcre.o \ $(NXT_BUILDDIR)/nxt_malloc.o \ $(NXT_BUILDDIR)/nxt_time.o \ + $(NXT_BUILDDIR)/nxt_file.o \ $(NXT_BUILDDIR)/nxt_trace.o \ $(NXT_BUILDDIR)/nxt_mp.o \ $(NXT_BUILDDIR)/nxt_sprintf.o \ @@ -221,6 +223,17 @@ NXT_LIB = nxt -I$(NXT_LIB) \ $(NXT_LIB)/nxt_time.c +$(NXT_BUILDDIR)/nxt_file.o: \ + $(NXT_LIB)/nxt_auto_config.h \ + $(NXT_LIB)/nxt_types.h \ + $(NXT_LIB)/nxt_clang.h \ + $(NXT_LIB)/nxt_file.h \ + $(NXT_LIB)/nxt_file.c \ + + $(NXT_CC) -c -o $(NXT_BUILDDIR)/nxt_file.o $(NXT_CFLAGS) \ + -I$(NXT_LIB) \ + $(NXT_LIB)/nxt_file.c + $(NXT_BUILDDIR)/nxt_trace.o: \ $(NXT_LIB)/nxt_auto_config.h \ $(NXT_LIB)/nxt_types.h \ diff -r 3b8ea515add6 -r 2c7a52ca206e nxt/nxt_file.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nxt/nxt_file.c Wed Feb 06 12:27:41 2019 +0800 @@ -0,0 +1,33 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) NGINX, Inc. + */ + +#include +#include +#include +#include +#include + +#include + + +void +nxt_file_name(nxt_str_t *name, char *path) +{ + char *p; + size_t length; + + length = strlen(path); + + for (p = path + length; p >= path; p--) { + if (*p == '/') { + p++; + break; + } + } + + name->start = (u_char *) p; + name->length = length - (p - path); +} diff -r 3b8ea515add6 -r 2c7a52ca206e nxt/nxt_file.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nxt/nxt_file.h Wed Feb 06 12:27:41 2019 +0800 @@ -0,0 +1,14 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) NGINX, Inc. + */ + +#ifndef _NXT_FILE_H_INCLUDED_ +#define _NXT_FILE_H_INCLUDED_ + + +void nxt_file_name(nxt_str_t *name, char *path); + + +#endif /* _NXT_FILE_H_INCLUDED_ */ From xeioex at nginx.com Wed Feb 6 14:34:38 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 06 Feb 2019 14:34:38 +0000 Subject: [njs] Modules: reporting njs filenames in exceptions. Message-ID: details: https://hg.nginx.org/njs/rev/342aa58f4e65 branches: changeset: 764:342aa58f4e65 user: Dmitry Volyntsev date: Wed Feb 06 15:50:03 2019 +0300 description: Modules: reporting njs filenames in exceptions. diffstat: nginx/ngx_http_js_module.c | 4 ++++ nginx/ngx_stream_js_module.c | 4 ++++ 2 files changed, 8 insertions(+), 0 deletions(-) diffs (28 lines): diff -r 2c7a52ca206e -r 342aa58f4e65 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Wed Feb 06 12:27:41 2019 +0800 +++ b/nginx/ngx_http_js_module.c Wed Feb 06 15:50:03 2019 +0300 @@ -2116,6 +2116,10 @@ ngx_http_js_include(ngx_conf_t *cf, ngx_ options.backtrace = 1; options.ops = &ngx_http_js_ops; + file = value[1]; + options.file.start = file.data; + options.file.length = file.len; + jmcf->vm = njs_vm_create(&options); if (jmcf->vm == NULL) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "failed to create JS VM"); diff -r 2c7a52ca206e -r 342aa58f4e65 nginx/ngx_stream_js_module.c --- a/nginx/ngx_stream_js_module.c Wed Feb 06 12:27:41 2019 +0800 +++ b/nginx/ngx_stream_js_module.c Wed Feb 06 15:50:03 2019 +0300 @@ -1377,6 +1377,10 @@ ngx_stream_js_include(ngx_conf_t *cf, ng options.backtrace = 1; options.ops = &ngx_stream_js_ops; + file = value[1]; + options.file.start = file.data; + options.file.length = file.len; + jmcf->vm = njs_vm_create(&options); if (jmcf->vm == NULL) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "failed to create JS VM"); From xeioex at nginx.com Wed Feb 6 17:21:25 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 06 Feb 2019 17:21:25 +0000 Subject: [njs] HTTP: improved setting of special response headers. Message-ID: details: https://hg.nginx.org/njs/rev/9bd38c6bf046 branches: changeset: 765:9bd38c6bf046 user: Dmitry Volyntsev date: Wed Feb 06 19:22:18 2019 +0300 description: HTTP: improved setting of special response headers. diffstat: nginx/ngx_http_js_module.c | 27 ++++++++++++++++++++++++--- 1 files changed, 24 insertions(+), 3 deletions(-) diffs (47 lines): diff -r 342aa58f4e65 -r 9bd38c6bf046 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Wed Feb 06 15:50:03 2019 +0300 +++ b/nginx/ngx_http_js_module.c Wed Feb 06 19:22:18 2019 +0300 @@ -934,6 +934,18 @@ ngx_http_js_ext_set_header_out(njs_vm_t r = (ngx_http_request_t *) obj; v = (nxt_str_t *) data; + if (v->length == nxt_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 = r->headers_out.content_type.len; + r->headers_out.content_type.data = value->start; + r->headers_out.content_type_lowcase = NULL; + + return NJS_OK; + } + h = ngx_http_js_get_header(&r->headers_out.headers.part, v->start, v->length); @@ -965,12 +977,21 @@ ngx_http_js_ext_set_header_out(njs_vm_t h->value.data = p; h->value.len = value->length; - if (h->key.len == nxt_length("Content-Length") - && ngx_strncasecmp(h->key.data, (u_char *) "Content-Length", - nxt_length("Content-Length")) == 0) + if (v->length == nxt_length("Content-Encoding") + && ngx_strncasecmp(v->start, (u_char *) "Content-Encoding", + v->length) == 0) + { + r->headers_out.content_encoding = h; + } + + if (v->length == nxt_length("Content-Length") + && ngx_strncasecmp(v->start, (u_char *) "Content-Length", + v->length) == 0) { n = ngx_atoi(value->start, value->length); if (n == NGX_ERROR) { + h->hash = 0; + njs_vm_error(vm, "failed converting argument to integer"); return NJS_ERROR; } From xeioex at nginx.com Wed Feb 6 17:21:25 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 06 Feb 2019 17:21:25 +0000 Subject: [njs] HTTP: improved setting empty headers. Message-ID: details: https://hg.nginx.org/njs/rev/016d5d9077ef branches: changeset: 766:016d5d9077ef user: Dmitry Volyntsev date: Wed Feb 06 19:52:54 2019 +0300 description: HTTP: improved setting empty headers. Treating empty value as deleting. diffstat: nginx/ngx_http_js_module.c | 50 ++++++++++++++++++++++++++++----------------- 1 files changed, 31 insertions(+), 19 deletions(-) diffs (78 lines): diff -r 9bd38c6bf046 -r 016d5d9077ef nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Wed Feb 06 19:22:18 2019 +0300 +++ b/nginx/ngx_http_js_module.c Wed Feb 06 19:52:54 2019 +0300 @@ -949,7 +949,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 || h->hash == 0) { + if (h != NULL && value->length == 0) { + h->hash = 0; + h = NULL; + } + + if (h == NULL && value->length != 0) { h = ngx_list_push(&r->headers_out.headers); if (h == NULL) { return NJS_ERROR; @@ -964,19 +969,21 @@ ngx_http_js_ext_set_header_out(njs_vm_t h->key.data = p; h->key.len = v->length; + } + + if (h != NULL) { + p = ngx_pnalloc(r->pool, value->length); + if (p == NULL) { + return NJS_ERROR; + } + + ngx_memcpy(p, value->start, value->length); + + h->value.data = p; + h->value.len = value->length; h->hash = 1; } - p = ngx_pnalloc(r->pool, value->length); - if (p == NULL) { - return NJS_ERROR; - } - - ngx_memcpy(p, value->start, value->length); - - h->value.data = p; - h->value.len = value->length; - if (v->length == nxt_length("Content-Encoding") && ngx_strncasecmp(v->start, (u_char *) "Content-Encoding", v->length) == 0) @@ -988,15 +995,20 @@ ngx_http_js_ext_set_header_out(njs_vm_t && ngx_strncasecmp(v->start, (u_char *) "Content-Length", v->length) == 0) { - n = ngx_atoi(value->start, value->length); - if (n == NGX_ERROR) { - h->hash = 0; - njs_vm_error(vm, "failed converting argument to integer"); - return NJS_ERROR; + if (h != NULL) { + n = ngx_atoi(value->start, value->length); + if (n == NGX_ERROR) { + h->hash = 0; + njs_vm_error(vm, "failed converting argument to integer"); + return NJS_ERROR; + } + + r->headers_out.content_length = h; + r->headers_out.content_length_n = n; + + } else { + ngx_http_clear_content_length(r); } - - r->headers_out.content_length_n = n; - r->headers_out.content_length = h; } return NJS_OK; From kahing at cloudflare.com Wed Feb 6 21:19:06 2019 From: kahing at cloudflare.com (Ka-Hing Cheung) Date: Wed, 6 Feb 2019 13:19:06 -0800 Subject: cache: move open to thread pool In-Reply-To: References: <20180808181653.GX56558@mdounin.ru> <20180810113946.GG56558@mdounin.ru> <20180903160903.GI56558@mdounin.ru> <4ba7414a-0eba-6bd3-5a50-2eca591ac25e@nginx.com> <2a3577f6-4ad4-aa2d-80a2-7e9b715c070d@nginx.com> Message-ID: This has been running in our test colo for the past week with no ill effects. On Wed, Jan 23, 2019 at 4:39 AM Maxim Konovalov wrote: > > Hi Ka-Hing, > > Roman told me that the delta is because of your changes. > > Thanks for your time on that. Waiting for your testing results. > > Maxim > > On 22/01/2019 22:34, Ka-Hing Cheung via nginx-devel wrote: > > I spoke too soon, just realized our test colo is running the patches > > without aio_open on. Flipping that switch now. > > > > Also, including the patch that we applied on top in addition to the > > massaging we did to resolve conflicts. I haven't dug too deep to see > > if stock nginx also requires similar changes or they are only > > necessary because of our other nginx changes: > > > [...] > > -- > Maxim Konovalov From maxim at nginx.com Thu Feb 7 13:39:47 2019 From: maxim at nginx.com (Maxim Konovalov) Date: Thu, 7 Feb 2019 16:39:47 +0300 Subject: cache: move open to thread pool In-Reply-To: References: <20180808181653.GX56558@mdounin.ru> <20180810113946.GG56558@mdounin.ru> <20180903160903.GI56558@mdounin.ru> <4ba7414a-0eba-6bd3-5a50-2eca591ac25e@nginx.com> <2a3577f6-4ad4-aa2d-80a2-7e9b715c070d@nginx.com> Message-ID: Great. Thanks for the testing! Did you see any measurable perf. metrics changes comparing to your aio open implementation or comparing to nginx without aio open support? We are still waiting for additional input from another tester, who expressed interest before. Thanks, Maxim On 07/02/2019 00:19, Ka-Hing Cheung wrote: > This has been running in our test colo for the past week with no ill effects. > > On Wed, Jan 23, 2019 at 4:39 AM Maxim Konovalov wrote: >> >> Hi Ka-Hing, >> >> Roman told me that the delta is because of your changes. >> >> Thanks for your time on that. Waiting for your testing results. >> >> Maxim >> >> On 22/01/2019 22:34, Ka-Hing Cheung via nginx-devel wrote: >>> I spoke too soon, just realized our test colo is running the patches >>> without aio_open on. Flipping that switch now. >>> >>> Also, including the patch that we applied on top in addition to the >>> massaging we did to resolve conflicts. I haven't dug too deep to see >>> if stock nginx also requires similar changes or they are only >>> necessary because of our other nginx changes: >>> >> [...] >> >> -- >> Maxim Konovalov -- Maxim Konovalov From xeioex at nginx.com Thu Feb 7 17:40:41 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 07 Feb 2019 17:40:41 +0000 Subject: [njs] HTTP: skipping deleted elements while iterating over headers. Message-ID: details: https://hg.nginx.org/njs/rev/2feb1b5a210d branches: changeset: 768:2feb1b5a210d user: Dmitry Volyntsev date: Thu Feb 07 20:05:16 2019 +0300 description: HTTP: skipping deleted elements while iterating over headers. diffstat: nginx/ngx_http_js_module.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diffs (14 lines): diff -r 0913527ad077 -r 2feb1b5a210d nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Thu Feb 07 20:05:14 2019 +0300 +++ b/nginx/ngx_http_js_module.c Thu Feb 07 20:05:16 2019 +0300 @@ -860,6 +860,10 @@ ngx_http_js_ext_next_header(njs_vm_t *vm header = entry->part->elts; h = &header[entry->item++]; + if (h->hash == 0) { + continue; + } + return njs_string_create(vm, value, h->key.data, h->key.len, 0); } From xeioex at nginx.com Thu Feb 7 17:40:41 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 07 Feb 2019 17:40:41 +0000 Subject: [njs] HTTP: added support for delete operation in r.headersOut. Message-ID: details: https://hg.nginx.org/njs/rev/0913527ad077 branches: changeset: 767:0913527ad077 user: Dmitry Volyntsev date: Thu Feb 07 20:05:14 2019 +0300 description: HTTP: added support for delete operation in r.headersOut. This closes #64 issue on Github. diffstat: nginx/ngx_http_js_module.c | 16 +++++++++++++++- 1 files changed, 15 insertions(+), 1 deletions(-) diffs (40 lines): diff -r 016d5d9077ef -r 0913527ad077 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Wed Feb 06 19:52:54 2019 +0300 +++ b/nginx/ngx_http_js_module.c Thu Feb 07 20:05:14 2019 +0300 @@ -71,6 +71,8 @@ static njs_ret_t ngx_http_js_ext_get_hea njs_value_t *value, void *obj, uintptr_t data); static njs_ret_t ngx_http_js_ext_set_header_out(njs_vm_t *vm, void *obj, uintptr_t data, nxt_str_t *value); +static njs_ret_t ngx_http_js_ext_delete_header_out(njs_vm_t *vm, void *obj, + uintptr_t data, nxt_bool_t delete); static njs_ret_t ngx_http_js_ext_foreach_header_out(njs_vm_t *vm, void *obj, void *next); /*FIXME*/ static njs_ret_t ngx_http_js_ext_get_status(njs_vm_t *vm, njs_value_t *value, @@ -344,7 +346,7 @@ static njs_external_t ngx_http_js_ext_r 0, ngx_http_js_ext_get_header_out, ngx_http_js_ext_set_header_out, - NULL, + ngx_http_js_ext_delete_header_out, ngx_http_js_ext_foreach_header_out, ngx_http_js_ext_next_header, NULL, @@ -1016,6 +1018,18 @@ ngx_http_js_ext_set_header_out(njs_vm_t static njs_ret_t +ngx_http_js_ext_delete_header_out(njs_vm_t *vm, void *obj, uintptr_t data, + nxt_bool_t unused) +{ + nxt_str_t value; + + value = nxt_string_value(""); + + return ngx_http_js_ext_set_header_out(vm, obj, data, &value); +} + + +static njs_ret_t ngx_http_js_ext_foreach_header_out(njs_vm_t *vm, void *obj, void *next) { return ngx_http_js_ext_foreach_header(vm, obj, next, From pluknet at nginx.com Fri Feb 8 13:04:52 2019 From: pluknet at nginx.com (Sergey Kandaurov) Date: Fri, 08 Feb 2019 13:04:52 +0000 Subject: [nginx] SSL: fixed EVP_DigestFinal_ex() error message. Message-ID: details: https://hg.nginx.org/nginx/rev/992bf7540a98 branches: changeset: 7455:992bf7540a98 user: Sergey Kandaurov date: Thu Feb 07 19:39:35 2019 +0300 description: SSL: fixed EVP_DigestFinal_ex() error message. diffstat: src/event/ngx_event_openssl.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r e72c8a8a8b10 -r 992bf7540a98 src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Thu Jan 31 19:36:51 2019 +0300 +++ b/src/event/ngx_event_openssl.c Thu Feb 07 19:39:35 2019 +0300 @@ -2928,7 +2928,7 @@ ngx_ssl_session_id_context(ngx_ssl_t *ss if (EVP_DigestFinal_ex(md, buf, &len) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "EVP_DigestUpdate() failed"); + "EVP_DigestFinal_ex() failed"); goto failed; } From xeioex at nginx.com Fri Feb 8 17:20:22 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 08 Feb 2019 17:20:22 +0000 Subject: [njs] Shell: avoid reporting filenames in exception is quiet mode. Message-ID: details: https://hg.nginx.org/njs/rev/7978bb236657 branches: changeset: 770:7978bb236657 user: Dmitry Volyntsev date: Fri Feb 08 20:14:55 2019 +0300 description: Shell: avoid reporting filenames in exception is quiet mode. diffstat: njs/njs_shell.c | 10 ++++++---- 1 files changed, 6 insertions(+), 4 deletions(-) diffs (21 lines): diff -r cb7ccf9edc68 -r 7978bb236657 njs/njs_shell.c --- a/njs/njs_shell.c Fri Feb 08 20:06:05 2019 +0300 +++ b/njs/njs_shell.c Fri Feb 08 20:14:55 2019 +0300 @@ -214,11 +214,13 @@ main(int argc, char **argv) nxt_memzero(&vm_options, sizeof(njs_vm_opt_t)); - if (opts.file != NULL) { - nxt_file_name(&vm_options.file, opts.file); + if (!opts.quiet) { + if (opts.file != NULL) { + nxt_file_name(&vm_options.file, opts.file); - } else { - vm_options.file = nxt_string_value("shell"); + } else { + vm_options.file = nxt_string_value("shell"); + } } vm_options.init = !opts.interactive; From xeioex at nginx.com Fri Feb 8 17:20:22 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 08 Feb 2019 17:20:22 +0000 Subject: [njs] Updated list of reserved keywords. Message-ID: details: https://hg.nginx.org/njs/rev/cb7ccf9edc68 branches: changeset: 769:cb7ccf9edc68 user: Dmitry Volyntsev date: Fri Feb 08 20:06:05 2019 +0300 description: Updated list of reserved keywords. diffstat: njs/njs_lexer_keyword.c | 18 ++---------------- njs/test/njs_expect_test.exp | 4 ++-- 2 files changed, 4 insertions(+), 18 deletions(-) diffs (64 lines): diff -r 2feb1b5a210d -r cb7ccf9edc68 njs/njs_lexer_keyword.c --- a/njs/njs_lexer_keyword.c Thu Feb 07 20:05:16 2019 +0300 +++ b/njs/njs_lexer_keyword.c Fri Feb 08 20:06:05 2019 +0300 @@ -95,37 +95,23 @@ static const njs_keyword_t njs_keywords /* Reserved words. */ - { nxt_string("abstract"), NJS_TOKEN_RESERVED, 0 }, - { nxt_string("boolean"), NJS_TOKEN_RESERVED, 0 }, - { nxt_string("byte"), NJS_TOKEN_RESERVED, 0 }, - { nxt_string("char"), NJS_TOKEN_RESERVED, 0 }, + { nxt_string("await"), NJS_TOKEN_RESERVED, 0 }, { nxt_string("class"), NJS_TOKEN_RESERVED, 0 }, { nxt_string("const"), NJS_TOKEN_RESERVED, 0 }, { nxt_string("debugger"), NJS_TOKEN_RESERVED, 0 }, - { nxt_string("double"), NJS_TOKEN_RESERVED, 0 }, { nxt_string("enum"), NJS_TOKEN_RESERVED, 0 }, { nxt_string("export"), NJS_TOKEN_RESERVED, 0 }, { nxt_string("extends"), NJS_TOKEN_RESERVED, 0 }, - { nxt_string("final"), NJS_TOKEN_RESERVED, 0 }, - { nxt_string("float"), NJS_TOKEN_RESERVED, 0 }, - { nxt_string("goto"), NJS_TOKEN_RESERVED, 0 }, { nxt_string("implements"), NJS_TOKEN_RESERVED, 0 }, { nxt_string("import"), NJS_TOKEN_RESERVED, 0 }, - { nxt_string("int"), NJS_TOKEN_RESERVED, 0 }, { nxt_string("interface"), NJS_TOKEN_RESERVED, 0 }, - { nxt_string("long"), NJS_TOKEN_RESERVED, 0 }, - { nxt_string("native"), NJS_TOKEN_RESERVED, 0 }, + { nxt_string("let"), NJS_TOKEN_RESERVED, 0 }, { nxt_string("package"), NJS_TOKEN_RESERVED, 0 }, { nxt_string("private"), NJS_TOKEN_RESERVED, 0 }, { nxt_string("protected"), NJS_TOKEN_RESERVED, 0 }, { nxt_string("public"), NJS_TOKEN_RESERVED, 0 }, - { nxt_string("short"), NJS_TOKEN_RESERVED, 0 }, { nxt_string("static"), NJS_TOKEN_RESERVED, 0 }, { nxt_string("super"), NJS_TOKEN_RESERVED, 0 }, - { nxt_string("synchronized"), NJS_TOKEN_RESERVED, 0 }, - { nxt_string("throws"), NJS_TOKEN_RESERVED, 0 }, - { nxt_string("transient"), NJS_TOKEN_RESERVED, 0 }, - { nxt_string("volatile"), NJS_TOKEN_RESERVED, 0 }, }; diff -r 2feb1b5a210d -r cb7ccf9edc68 njs/test/njs_expect_test.exp --- a/njs/test/njs_expect_test.exp Thu Feb 07 20:05:16 2019 +0300 +++ b/njs/test/njs_expect_test.exp Fri Feb 08 20:06:05 2019 +0300 @@ -58,7 +58,7 @@ njs_test { # Global completions, yes njs_test { {"\t\ty" - "\a\r\nDisplay all*possibilities? (y or n)*abstract"} + "\a\r\nDisplay all*possibilities? (y or n)*await"} } # Global completions, single partial match @@ -130,7 +130,7 @@ njs_test { {"var a = 1; var aa = 2\r\n" "var a = 1; var aa = 2\r\nundefined\r\n>> "} {"a\t\t" - "a*aa*abstract"} + "a*aa*arguments*await"} } njs_test { From xeioex at nginx.com Fri Feb 8 17:22:46 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 08 Feb 2019 17:22:46 +0000 Subject: [njs] Removing unused argument of njs_parser_property_name(). Message-ID: details: https://hg.nginx.org/njs/rev/4e8940c1bef1 branches: changeset: 771:4e8940c1bef1 user: Dmitry Volyntsev date: Fri Feb 08 20:22:28 2019 +0300 description: Removing unused argument of njs_parser_property_name(). diffstat: njs/njs_parser.c | 2 +- njs/njs_parser.h | 3 +-- njs/njs_parser_expression.c | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diffs (46 lines): diff -r 7978bb236657 -r 4e8940c1bef1 njs/njs_parser.c --- a/njs/njs_parser.c Fri Feb 08 20:14:55 2019 +0300 +++ b/njs/njs_parser.c Fri Feb 08 20:22:28 2019 +0300 @@ -2191,7 +2191,7 @@ njs_parser_object(njs_vm_t *vm, njs_pars return njs_parser_token(parser); case NJS_TOKEN_NAME: - token = njs_parser_property_name(vm, parser, token); + token = njs_parser_property_name(vm, parser); break; case NJS_TOKEN_NUMBER: diff -r 7978bb236657 -r 4e8940c1bef1 njs/njs_parser.h --- a/njs/njs_parser.h Fri Feb 08 20:14:55 2019 +0300 +++ b/njs/njs_parser.h Fri Feb 08 20:22:28 2019 +0300 @@ -320,8 +320,7 @@ njs_token_t njs_parser_assignment_expres njs_parser_t *parser, njs_token_t token); njs_token_t njs_parser_terminal(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token); -njs_token_t njs_parser_property_name(njs_vm_t *vm, njs_parser_t *parser, - njs_token_t token); +njs_token_t njs_parser_property_name(njs_vm_t *vm, njs_parser_t *parser); njs_token_t njs_parser_property_token(njs_parser_t *parser); njs_token_t njs_parser_token(njs_parser_t *parser); nxt_int_t njs_parser_string_create(njs_vm_t *vm, njs_value_t *value); diff -r 7978bb236657 -r 4e8940c1bef1 njs/njs_parser_expression.c --- a/njs/njs_parser_expression.c Fri Feb 08 20:14:55 2019 +0300 +++ b/njs/njs_parser_expression.c Fri Feb 08 20:22:28 2019 +0300 @@ -993,7 +993,7 @@ njs_parser_property_expression(njs_vm_t return NJS_TOKEN_ILLEGAL; } - token = njs_parser_property_name(vm, parser, token); + token = njs_parser_property_name(vm, parser); } else { token = njs_parser_token(parser); @@ -1015,7 +1015,7 @@ njs_parser_property_expression(njs_vm_t njs_token_t -njs_parser_property_name(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) +njs_parser_property_name(njs_vm_t *vm, njs_parser_t *parser) { nxt_int_t ret; njs_parser_node_t *node; From kahing at cloudflare.com Fri Feb 8 22:40:37 2019 From: kahing at cloudflare.com (Ka-Hing Cheung) Date: Fri, 8 Feb 2019 14:40:37 -0800 Subject: cache: move open to thread pool In-Reply-To: References: <20180808181653.GX56558@mdounin.ru> <20180810113946.GG56558@mdounin.ru> <20180903160903.GI56558@mdounin.ru> <4ba7414a-0eba-6bd3-5a50-2eca591ac25e@nginx.com> <2a3577f6-4ad4-aa2d-80a2-7e9b715c070d@nginx.com> Message-ID: Unfortunately our test colo is not setup to do performance testing (the traffic it receives varies too much). We do intend to merge this to our production colos but there's no timeline yet. Yuchen (CC'ed) will be the main contact from now on as today is my last day at Cloudflare. - Ka-Hing On Thu, Feb 7, 2019 at 5:39 AM Maxim Konovalov wrote: > > Great. Thanks for the testing! > > Did you see any measurable perf. metrics changes comparing to your > aio open implementation or comparing to nginx without aio open support? > > We are still waiting for additional input from another tester, who > expressed interest before. > > Thanks, > > Maxim > > On 07/02/2019 00:19, Ka-Hing Cheung wrote: > > This has been running in our test colo for the past week with no ill effects. > > > > On Wed, Jan 23, 2019 at 4:39 AM Maxim Konovalov wrote: > >> > >> Hi Ka-Hing, > >> > >> Roman told me that the delta is because of your changes. > >> > >> Thanks for your time on that. Waiting for your testing results. > >> > >> Maxim > >> > >> On 22/01/2019 22:34, Ka-Hing Cheung via nginx-devel wrote: > >>> I spoke too soon, just realized our test colo is running the patches > >>> without aio_open on. Flipping that switch now. > >>> > >>> Also, including the patch that we applied on top in addition to the > >>> massaging we did to resolve conflicts. I haven't dug too deep to see > >>> if stock nginx also requires similar changes or they are only > >>> necessary because of our other nginx changes: > >>> > >> [...] > >> > >> -- > >> Maxim Konovalov > > > -- > Maxim Konovalov From xeioex at nginx.com Mon Feb 11 15:16:22 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 11 Feb 2019 15:16:22 +0000 Subject: [njs] Improved njs_parser_property_token(). Message-ID: details: https://hg.nginx.org/njs/rev/08285ce7dd7c branches: changeset: 772:08285ce7dd7c user: hongzhidao date: Sat Feb 09 16:26:08 2019 +0800 description: Improved njs_parser_property_token(). diffstat: njs/njs_parser.c | 27 ++++++++++++++++++++++----- njs/njs_parser.h | 4 +--- njs/njs_parser_expression.c | 26 ++------------------------ 3 files changed, 25 insertions(+), 32 deletions(-) diffs (138 lines): diff -r 4e8940c1bef1 -r 08285ce7dd7c njs/njs_parser.c --- a/njs/njs_parser.c Fri Feb 08 20:22:28 2019 +0300 +++ b/njs/njs_parser.c Sat Feb 09 16:26:08 2019 +0800 @@ -60,6 +60,7 @@ static njs_token_t njs_parser_object(njs njs_parser_node_t *obj); static njs_token_t njs_parser_array(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *obj); +static nxt_int_t njs_parser_string_create(njs_vm_t *vm, njs_value_t *value); static njs_token_t njs_parser_escape_string_create(njs_vm_t *vm, njs_parser_t *parser, njs_value_t *value); static njs_token_t njs_parser_unexpected_token(njs_vm_t *vm, @@ -1756,9 +1757,11 @@ njs_parser_grouping_expression(njs_vm_t njs_token_t -njs_parser_property_token(njs_parser_t *parser) +njs_parser_property_token(njs_vm_t *vm, njs_parser_t *parser) { - njs_token_t token; + nxt_int_t ret; + njs_token_t token; + njs_parser_node_t *node; parser->lexer->property = 1; @@ -1766,6 +1769,20 @@ njs_parser_property_token(njs_parser_t * parser->lexer->property = 0; + if (token == NJS_TOKEN_NAME) { + node = njs_parser_node_new(vm, parser, NJS_TOKEN_STRING); + if (nxt_slow_path(node == NULL)) { + return NJS_TOKEN_ERROR; + } + + ret = njs_parser_string_create(vm, &node->u.value); + if (nxt_slow_path(ret != NXT_OK)) { + return NJS_TOKEN_ERROR; + } + + parser->node = node; + } + return token; } @@ -2183,7 +2200,7 @@ njs_parser_object(njs_vm_t *vm, njs_pars object->u.object = obj; for ( ;; ) { - token = njs_parser_property_token(parser); + token = njs_parser_property_token(vm, parser); switch (token) { @@ -2191,7 +2208,7 @@ njs_parser_object(njs_vm_t *vm, njs_pars return njs_parser_token(parser); case NJS_TOKEN_NAME: - token = njs_parser_property_name(vm, parser); + token = njs_parser_token(parser); break; case NJS_TOKEN_NUMBER: @@ -2351,7 +2368,7 @@ njs_parser_array(njs_vm_t *vm, njs_parse } -nxt_int_t +static nxt_int_t njs_parser_string_create(njs_vm_t *vm, njs_value_t *value) { u_char *p; diff -r 4e8940c1bef1 -r 08285ce7dd7c njs/njs_parser.h --- a/njs/njs_parser.h Fri Feb 08 20:22:28 2019 +0300 +++ b/njs/njs_parser.h Sat Feb 09 16:26:08 2019 +0800 @@ -320,10 +320,8 @@ njs_token_t njs_parser_assignment_expres njs_parser_t *parser, njs_token_t token); njs_token_t njs_parser_terminal(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token); -njs_token_t njs_parser_property_name(njs_vm_t *vm, njs_parser_t *parser); -njs_token_t njs_parser_property_token(njs_parser_t *parser); +njs_token_t njs_parser_property_token(njs_vm_t *vm, njs_parser_t *parser); njs_token_t njs_parser_token(njs_parser_t *parser); -nxt_int_t njs_parser_string_create(njs_vm_t *vm, njs_value_t *value); njs_variable_t *njs_variable_resolve(njs_vm_t *vm, njs_parser_node_t *node); njs_index_t njs_variable_typeof(njs_vm_t *vm, njs_parser_node_t *node); njs_index_t njs_variable_index(njs_vm_t *vm, njs_parser_node_t *node); diff -r 4e8940c1bef1 -r 08285ce7dd7c njs/njs_parser_expression.c --- a/njs/njs_parser_expression.c Fri Feb 08 20:22:28 2019 +0300 +++ b/njs/njs_parser_expression.c Sat Feb 09 16:26:08 2019 +0800 @@ -984,7 +984,7 @@ njs_parser_property_expression(njs_vm_t if (token == NJS_TOKEN_DOT) { - token = njs_parser_property_token(parser); + token = njs_parser_property_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -993,7 +993,7 @@ njs_parser_property_expression(njs_vm_t return NJS_TOKEN_ILLEGAL; } - token = njs_parser_property_name(vm, parser); + token = njs_parser_token(parser); } else { token = njs_parser_token(parser); @@ -1014,28 +1014,6 @@ njs_parser_property_expression(njs_vm_t } -njs_token_t -njs_parser_property_name(njs_vm_t *vm, njs_parser_t *parser) -{ - nxt_int_t ret; - njs_parser_node_t *node; - - node = njs_parser_node_new(vm, parser, NJS_TOKEN_STRING); - if (nxt_slow_path(node == NULL)) { - return NJS_TOKEN_ERROR; - } - - ret = njs_parser_string_create(vm, &node->u.value); - if (nxt_slow_path(ret != NXT_OK)) { - return NJS_TOKEN_ERROR; - } - - parser->node = node; - - return njs_parser_token(parser); -} - - static njs_token_t njs_parser_property_brackets(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) From xeioex at nginx.com Mon Feb 11 15:16:23 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 11 Feb 2019 15:16:23 +0000 Subject: [njs] Added support for shorthand property names for Object literals. Message-ID: details: https://hg.nginx.org/njs/rev/eb099f4faf40 branches: changeset: 774:eb099f4faf40 user: Dmitry Volyntsev date: Mon Feb 11 18:15:43 2019 +0300 description: Added support for shorthand property names for Object literals. This closes #87 issue on Github. diffstat: njs/njs_lexer.c | 8 +++++- njs/njs_parser.c | 56 +++++++++++++++++++++++++++++++++++++++-------- njs/njs_parser.h | 3 ++ njs/test/njs_unit_test.c | 38 ++++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 12 deletions(-) diffs (190 lines): diff -r a091eaa9d8eb -r eb099f4faf40 njs/njs_lexer.c --- a/njs/njs_lexer.c Sat Feb 09 17:34:04 2019 +0800 +++ b/njs/njs_lexer.c Mon Feb 11 18:15:43 2019 +0300 @@ -459,7 +459,8 @@ njs_lexer_next_token(njs_lexer_t *lexer) static njs_token_t njs_lexer_word(njs_lexer_t *lexer, u_char c) { - u_char *p; + u_char *p; + njs_token_t token; /* TODO: UTF-8 */ @@ -498,11 +499,14 @@ njs_lexer_word(njs_lexer_t *lexer, u_cha lexer->start = p; lexer->text.length = p - lexer->text.start; + token = njs_lexer_keyword(lexer); + if (lexer->property) { + lexer->property_token = token; return NJS_TOKEN_NAME; } - return njs_lexer_keyword(lexer); + return token; } diff -r a091eaa9d8eb -r eb099f4faf40 njs/njs_parser.c --- a/njs/njs_parser.c Sat Feb 09 17:34:04 2019 +0800 +++ b/njs/njs_parser.c Mon Feb 11 18:15:43 2019 +0300 @@ -2215,13 +2215,29 @@ njs_parser_builtin(njs_vm_t *vm, njs_par } +/* + * ES6: 12.2.6 Object Initializer + * Supported syntax: + * PropertyDefinition: + * PropertyName : AssignmentExpression + * IdentifierReference + * PropertyName: + * IdentifierName, StringLiteral, NumericLiteral. + */ static njs_token_t njs_parser_object(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *obj) { + uint32_t hash; + nxt_str_t name; njs_token_t token; - njs_parser_node_t *stmt, *assign, *object, *propref, *left; + njs_lexer_t *lexer; + njs_parser_node_t *stmt, *assign, *object, *propref, *left, *expression; left = NULL; + lexer = parser->lexer; + + /* GCC and Clang complain about uninitialized hash. */ + hash = 0; object = njs_parser_node_new(vm, parser, NJS_TOKEN_OBJECT_VALUE); if (nxt_slow_path(object == NULL)) { @@ -2233,12 +2249,17 @@ njs_parser_object(njs_vm_t *vm, njs_pars for ( ;; ) { token = njs_parser_property_token(vm, parser); + name.start = NULL; + switch (token) { case NJS_TOKEN_CLOSE_BRACE: return njs_parser_token(parser); case NJS_TOKEN_NAME: + name = lexer->text; + hash = lexer->key_hash; + token = njs_parser_token(parser); break; @@ -2264,14 +2285,29 @@ njs_parser_object(njs_vm_t *vm, njs_pars propref->left = object; propref->right = parser->node; - token = njs_parser_match(vm, parser, token, NJS_TOKEN_COLON); - if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { - return token; - } - - token = njs_parser_assignment_expression(vm, parser, token); - if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { - return token; + if (name.start != NULL + && (token == NJS_TOKEN_COMMA || token == NJS_TOKEN_CLOSE_BRACE) + && lexer->property_token != NJS_TOKEN_THIS + && lexer->property_token != NJS_TOKEN_GLOBAL_THIS) + { + expression = njs_parser_reference(vm, parser, lexer->property_token, + &name, hash); + if (nxt_slow_path(expression == NULL)) { + return NJS_TOKEN_ERROR; + } + + } else { + token = njs_parser_match(vm, parser, token, NJS_TOKEN_COLON); + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return token; + } + + token = njs_parser_assignment_expression(vm, parser, token); + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return token; + } + + expression = parser->node; } assign = njs_parser_node_new(vm, parser, NJS_TOKEN_ASSIGNMENT); @@ -2281,7 +2317,7 @@ njs_parser_object(njs_vm_t *vm, njs_pars assign->u.operation = njs_vmcode_move; assign->left = propref; - assign->right = parser->node; + assign->right = expression; stmt = njs_parser_node_new(vm, parser, NJS_TOKEN_STATEMENT); if (nxt_slow_path(stmt == NULL)) { diff -r a091eaa9d8eb -r eb099f4faf40 njs/njs_parser.h --- a/njs/njs_parser.h Sat Feb 09 17:34:04 2019 +0800 +++ b/njs/njs_parser.h Mon Feb 11 18:15:43 2019 +0300 @@ -210,7 +210,10 @@ typedef enum { typedef struct { njs_token_t token:16; njs_token_t prev_token:16; + uint8_t property; /* 1 bit */ + njs_token_t property_token:16; + uint32_t key_hash; uint32_t token_line; diff -r a091eaa9d8eb -r eb099f4faf40 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Sat Feb 09 17:34:04 2019 +0800 +++ b/njs/test/njs_unit_test.c Mon Feb 11 18:15:43 2019 +0300 @@ -2761,6 +2761,44 @@ static njs_unit_test_t njs_test[] = { nxt_string("var x = { a: 1 }, b = delete x.a; x.a +' '+ b"), nxt_string("undefined true") }, + /* Shorthand Object literals. */ + + { nxt_string("var a = 1; njs.dump({a})"), + nxt_string("{a:1}") }, + + { nxt_string("var a = 1, b; njs.dump({a,b})"), + nxt_string("{a:1,b:undefined}") }, + + { nxt_string("var a = 1, b = 2; ({a,b,c})"), + nxt_string("ReferenceError: \"c\" is not defined in 1") }, + + { nxt_string("var a = 1, b = 2; njs.dump({a,b,c:3})"), + nxt_string("{a:1,b:2,c:3}") }, + + { nxt_string("var b = 2, c = 3; njs.dump({a:1,b,c})"), + nxt_string("{a:1,b:2,c:3}") }, + + { nxt_string("({1})"), + nxt_string("SyntaxError: Unexpected token \"}\" in 1") }, + + { nxt_string("({default})"), + nxt_string("SyntaxError: Unexpected token \"}\" in 1") }, + + { nxt_string("({var})"), + nxt_string("SyntaxError: Unexpected token \"}\" in 1") }, + + { nxt_string("({this})"), + nxt_string("SyntaxError: Unexpected token \"}\" in 1") }, + + { nxt_string("typeof ({Number}).Number"), + nxt_string("function") }, + + { nxt_string("typeof ({eval}).eval"), + nxt_string("function") }, + + { nxt_string("typeof ({Math}).Math.sin"), + nxt_string("function") }, + { nxt_string("delete null"), nxt_string("true") }, From xeioex at nginx.com Mon Feb 11 15:16:22 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 11 Feb 2019 15:16:22 +0000 Subject: [njs] Refactored njs_parser_terminal(). Message-ID: details: https://hg.nginx.org/njs/rev/a091eaa9d8eb branches: changeset: 773:a091eaa9d8eb user: hongzhidao date: Sat Feb 09 17:34:04 2019 +0800 description: Refactored njs_parser_terminal(). 1) Introduced njs_parser_reference(). 2) njs_parser_builtin_object() and njs_parser_builtin_function() are refactored into njs_parser_builtin(). 3) njs_parser_external() is simplified and renamed as njs_external_lookup(). diffstat: njs/njs_extern.c | 6 +- njs/njs_extern.h | 1 + njs/njs_parser.c | 267 ++++++++++++++++++++++++++++++------------------------ njs/njs_parser.h | 2 - 4 files changed, 153 insertions(+), 123 deletions(-) diffs (442 lines): diff -r 08285ce7dd7c -r a091eaa9d8eb njs/njs_extern.c --- a/njs/njs_extern.c Sat Feb 09 16:26:08 2019 +0800 +++ b/njs/njs_extern.c Sat Feb 09 17:34:04 2019 +0800 @@ -304,13 +304,13 @@ njs_extern_keys_array(njs_vm_t *vm, cons njs_value_t * -njs_parser_external(njs_vm_t *vm, njs_parser_t *parser) +njs_external_lookup(njs_vm_t *vm, nxt_str_t *name, uint32_t hash) { nxt_lvlhsh_query_t lhq; njs_extern_value_t *ev; - lhq.key_hash = parser->lexer->key_hash; - lhq.key = parser->lexer->text; + lhq.key_hash = hash; + lhq.key = *name; lhq.proto = &njs_extern_value_hash_proto; if (nxt_lvlhsh_find(&vm->externals_hash, &lhq) == NXT_OK) { diff -r 08285ce7dd7c -r a091eaa9d8eb njs/njs_extern.h --- a/njs/njs_extern.h Sat Feb 09 16:26:08 2019 +0800 +++ b/njs/njs_extern.h Sat Feb 09 17:34:04 2019 +0800 @@ -42,6 +42,7 @@ typedef struct { njs_array_t *njs_extern_keys_array(njs_vm_t *vm, const njs_extern_t *external); +njs_value_t *njs_external_lookup(njs_vm_t *vm, nxt_str_t *name, uint32_t hash); nxt_int_t njs_external_match_native_function(njs_vm_t *vm, njs_function_native_t func, nxt_str_t *name); diff -r 08285ce7dd7c -r a091eaa9d8eb njs/njs_parser.c --- a/njs/njs_parser.c Sat Feb 09 16:26:08 2019 +0800 +++ b/njs/njs_parser.c Sat Feb 09 17:34:04 2019 +0800 @@ -52,10 +52,11 @@ static njs_token_t njs_parser_throw_stat njs_parser_t *parser); static njs_token_t njs_parser_grouping_expression(njs_vm_t *vm, njs_parser_t *parser); -static njs_token_t njs_parser_builtin_object(njs_vm_t *vm, njs_parser_t *parser, - njs_parser_node_t *node); -static njs_token_t njs_parser_builtin_function(njs_vm_t *vm, - njs_parser_t *parser, njs_parser_node_t *node); +static njs_parser_node_t *njs_parser_reference(njs_vm_t *vm, + njs_parser_t *parser, njs_token_t token, nxt_str_t *name, uint32_t hash); +static nxt_int_t njs_parser_builtin(njs_vm_t *vm, njs_parser_t *parser, + njs_parser_node_t *node, njs_value_type_t type, nxt_str_t *name, + uint32_t hash); static njs_token_t njs_parser_object(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *obj); static njs_token_t njs_parser_array(njs_vm_t *vm, njs_parser_t *parser, @@ -1808,11 +1809,12 @@ njs_parser_token(njs_parser_t *parser) njs_token_t njs_parser_terminal(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) { - double num; - njs_ret_t ret; - njs_value_t *ext; - njs_parser_node_t *node; - njs_parser_scope_t *scope; + double num; + njs_ret_t ret; + njs_lexer_t *lexer; + njs_parser_node_t *node; + + lexer = parser->lexer; if (token == NJS_TOKEN_OPEN_PARENTHESIS) { @@ -1833,37 +1835,16 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa return njs_parser_function_expression(vm, parser); } - node = njs_parser_node_new(vm, parser, token); - if (nxt_slow_path(node == NULL)) { - return NJS_TOKEN_ERROR; - } - switch (token) { - case NJS_TOKEN_NAME: - nxt_thread_log_debug("JS: %V", &parser->lexer->text); - - ext = njs_parser_external(vm, parser); - - if (ext != NULL) { - node->token = NJS_TOKEN_EXTERNAL; - node->u.value = *ext; - node->index = (njs_index_t) ext; - break; - } - - ret = njs_parser_variable_reference(vm, parser, node, NJS_REFERENCE); - if (nxt_slow_path(ret != NXT_OK)) { + case NJS_TOKEN_OPEN_BRACE: + nxt_thread_log_debug("JS: OBJECT"); + + node = njs_parser_node_new(vm, parser, NJS_TOKEN_OBJECT); + if (nxt_slow_path(node == NULL)) { return NJS_TOKEN_ERROR; } - break; - - case NJS_TOKEN_OPEN_BRACE: - node->token = NJS_TOKEN_OBJECT; - - nxt_thread_log_debug("JS: OBJECT"); - parser->node = node; token = njs_parser_object(vm, parser, node); @@ -1877,10 +1858,13 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa return token; case NJS_TOKEN_OPEN_BRACKET: - node->token = NJS_TOKEN_ARRAY; - nxt_thread_log_debug("JS: ARRAY"); + node = njs_parser_node_new(vm, parser, NJS_TOKEN_ARRAY); + if (nxt_slow_path(node == NULL)) { + return NJS_TOKEN_ERROR; + } + parser->node = node; token = njs_parser_array(vm, parser, node); @@ -1894,19 +1878,27 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa return token; case NJS_TOKEN_DIVISION: + node = njs_parser_node_new(vm, parser, NJS_TOKEN_REGEXP); + if (nxt_slow_path(node == NULL)) { + return NJS_TOKEN_ERROR; + } + token = njs_regexp_literal(vm, parser, &node->u.value); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } - nxt_thread_log_debug("REGEX: '%V'", &parser->lexer->text); - - node->token = NJS_TOKEN_REGEXP; + nxt_thread_log_debug("REGEX: '%V'", &lexer->text); break; case NJS_TOKEN_STRING: - nxt_thread_log_debug("JS: '%V'", &parser->lexer->text); + nxt_thread_log_debug("JS: '%V'", &lexer->text); + + node = njs_parser_node_new(vm, parser, NJS_TOKEN_STRING); + if (nxt_slow_path(node == NULL)) { + return NJS_TOKEN_ERROR; + } ret = njs_parser_string_create(vm, &node->u.value); if (nxt_slow_path(ret != NXT_OK)) { @@ -1916,9 +1908,12 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa break; case NJS_TOKEN_ESCAPE_STRING: - node->token = NJS_TOKEN_STRING; - - nxt_thread_log_debug("JS: '%V'", &parser->lexer->text); + nxt_thread_log_debug("JS: '%V'", &lexer->text); + + node = njs_parser_node_new(vm, parser, NJS_TOKEN_STRING); + if (nxt_slow_path(node == NULL)) { + return NJS_TOKEN_ERROR; + } ret = njs_parser_escape_string_create(vm, parser, &node->u.value); if (nxt_slow_path(ret != NJS_TOKEN_STRING)) { @@ -1929,14 +1924,19 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa case NJS_TOKEN_UNTERMINATED_STRING: njs_parser_syntax_error(vm, parser, "Unterminated string \"%V\"", - &parser->lexer->text); + &lexer->text); return NJS_TOKEN_ILLEGAL; case NJS_TOKEN_NUMBER: - nxt_thread_log_debug("JS: %f", parser->lexer->number); - - num = parser->lexer->number; + num = lexer->number; + nxt_thread_log_debug("JS: %f", num); + + node = njs_parser_node_new(vm, parser, NJS_TOKEN_NUMBER); + if (nxt_slow_path(node == NULL)) { + return NJS_TOKEN_ERROR; + } + node->u.value.data.u.number = num; node->u.value.type = NJS_NUMBER; node->u.value.data.truth = njs_is_number_true(num); @@ -1944,9 +1944,14 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa break; case NJS_TOKEN_BOOLEAN: - nxt_thread_log_debug("JS: boolean: %V", &parser->lexer->text); - - if (parser->lexer->number == 0) { + nxt_thread_log_debug("JS: boolean: %V", &lexer->text); + + node = njs_parser_node_new(vm, parser, NJS_TOKEN_BOOLEAN); + if (nxt_slow_path(node == NULL)) { + return NJS_TOKEN_ERROR; + } + + if (lexer->number == 0) { node->u.value = njs_value_false; } else { @@ -1955,6 +1960,39 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa break; + default: + node = njs_parser_reference(vm, parser, token, &lexer->text, + lexer->key_hash); + + if (nxt_slow_path(node == NULL)) { + return NJS_TOKEN_ERROR; + } + + break; + } + + parser->node = node; + + return njs_parser_token(parser); +} + + +static njs_parser_node_t * +njs_parser_reference(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token, + nxt_str_t *name, uint32_t hash) +{ + njs_ret_t ret; + njs_value_t *ext; + njs_parser_node_t *node; + njs_parser_scope_t *scope; + + node = njs_parser_node_new(vm, parser, token); + if (nxt_slow_path(node == NULL)) { + return NULL; + } + + switch (token) { + case NJS_TOKEN_NULL: nxt_thread_log_debug("JS: null"); @@ -1992,16 +2030,21 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa case NJS_TOKEN_NJS: case NJS_TOKEN_MATH: case NJS_TOKEN_JSON: - return njs_parser_builtin_object(vm, parser, node); + ret = njs_parser_builtin(vm, parser, node, NJS_OBJECT, name, hash); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } + + break; case NJS_TOKEN_ARGUMENTS: nxt_thread_log_debug("JS: arguments"); if (parser->scope->type <= NJS_SCOPE_GLOBAL) { njs_parser_syntax_error(vm, parser, "\"%V\" object " - "in global scope", &parser->lexer->text); - - return NJS_TOKEN_ILLEGAL; + "in global scope", name); + + return NULL; } break; @@ -2088,24 +2131,46 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa case NJS_TOKEN_SET_TIMEOUT: case NJS_TOKEN_SET_IMMEDIATE: case NJS_TOKEN_CLEAR_TIMEOUT: - return njs_parser_builtin_function(vm, parser, node); + ret = njs_parser_builtin(vm, parser, node, NJS_FUNCTION, name, hash); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } + + break; + + case NJS_TOKEN_NAME: + nxt_thread_log_debug("JS: %V", name); + + ext = njs_external_lookup(vm, name, hash); + + if (ext != NULL) { + node->token = NJS_TOKEN_EXTERNAL; + node->u.value = *ext; + node->index = (njs_index_t) ext; + break; + } + + ret = njs_variable_reference(vm, parser->scope, node, name, hash, + NJS_REFERENCE); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } + + break; default: - return njs_parser_unexpected_token(vm, parser, token); + (void) njs_parser_unexpected_token(vm, parser, token); + return NULL; } - parser->node = node; - - return njs_parser_token(parser); + return node; } -static njs_token_t -njs_parser_builtin_object(njs_vm_t *vm, njs_parser_t *parser, - njs_parser_node_t *node) +static nxt_int_t +njs_parser_builtin(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *node, + njs_value_type_t type, nxt_str_t *name, uint32_t hash) { - uint32_t hash; - nxt_str_t *name; njs_ret_t ret; nxt_uint_t index; njs_variable_t *var; @@ -2117,70 +2182,36 @@ njs_parser_builtin_object(njs_vm_t *vm, scope = scope->parent; } - hash = parser->lexer->key_hash; - name = &parser->lexer->text; - var = njs_variable_add(vm, scope, name, hash, NJS_VARIABLE_VAR); if (nxt_slow_path(var == NULL)) { - return NJS_TOKEN_ERROR; + return NXT_ERROR; } /* TODO: once */ - index = node->token - NJS_TOKEN_FIRST_OBJECT; - var->value.data.u.object = &vm->shared->objects[index]; - var->value.type = NJS_OBJECT; + switch (type) { + case NJS_OBJECT: + index = node->token - NJS_TOKEN_FIRST_OBJECT; + var->value.data.u.object = &vm->shared->objects[index]; + break; + + case NJS_FUNCTION: + index = node->token - NJS_TOKEN_FIRST_FUNCTION; + var->value.data.u.function = &vm->shared->functions[index]; + break; + + default: + return NXT_ERROR; + } + + var->value.type = type; var->value.data.truth = 1; ret = njs_variable_reference(vm, scope, node, name, hash, NJS_REFERENCE); if (nxt_slow_path(ret != NXT_OK)) { - return NJS_TOKEN_ERROR; + return NXT_ERROR; } - parser->node = node; - - return njs_parser_token(parser); -} - - -static njs_token_t -njs_parser_builtin_function(njs_vm_t *vm, njs_parser_t *parser, - njs_parser_node_t *node) -{ - uint32_t hash; - nxt_str_t *name; - njs_ret_t ret; - nxt_uint_t index; - njs_variable_t *var; - njs_parser_scope_t *scope; - - scope = parser->scope; - - while (scope->type != NJS_SCOPE_GLOBAL) { - scope = scope->parent; - } - - hash = parser->lexer->key_hash; - name = &parser->lexer->text; - - var = njs_variable_add(vm, scope, name, hash, NJS_VARIABLE_VAR); - if (nxt_slow_path(var == NULL)) { - return NJS_TOKEN_ERROR; - } - - /* TODO: once */ - index = node->token - NJS_TOKEN_FIRST_FUNCTION; - var->value.data.u.function = &vm->shared->functions[index]; - var->value.type = NJS_FUNCTION; - var->value.data.truth = 1; - - ret = njs_variable_reference(vm, scope, node, name, hash, NJS_REFERENCE); - if (nxt_slow_path(ret != NXT_OK)) { - return NJS_TOKEN_ERROR; - } - - parser->node = node; - - return njs_parser_token(parser); + return NXT_OK; } diff -r 08285ce7dd7c -r a091eaa9d8eb njs/njs_parser.h --- a/njs/njs_parser.h Sat Feb 09 16:26:08 2019 +0800 +++ b/njs/njs_parser.h Sat Feb 09 17:34:04 2019 +0800 @@ -306,8 +306,6 @@ void njs_lexer_rollback(njs_lexer_t *lex nxt_int_t njs_lexer_keywords_init(nxt_mp_t *mcp, nxt_lvlhsh_t *hash); njs_token_t njs_lexer_keyword(njs_lexer_t *lexer); -njs_value_t *njs_parser_external(njs_vm_t *vm, njs_parser_t *parser); - nxt_int_t njs_parser(njs_vm_t *vm, njs_parser_t *parser, njs_parser_t *prev); njs_token_t njs_parser_arguments(njs_vm_t *vm, njs_parser_t *parser, From chanhun.jeong at navercorp.com Tue Feb 12 02:38:41 2019 From: chanhun.jeong at navercorp.com (=?utf-8?B?7KCV7LCs7ZuI?=) Date: Tue, 12 Feb 2019 11:38:41 +0900 Subject: Fix buffer size comparison for the case header_start + 256 has same value to buffer_size (ticket #17 Message-ID: <127871f3e28adcdc1ec9fab1a955a6@cweb03.nmdf.nhnsystem.com> # HG changeset patch # User Chanhun Jeong # Date 1549859813 -32400 # Mon Feb 11 13:36:53 2019 +0900 # Node ID f2648ca4ed03a907e6d3c22729be82b3bc4027a0 # Parent 992bf7540a980c48a37c305d2c511cf9a48fe701 Fix buffer size comparison for the case header_start + 256 has same value to buffer_size (ticket #1722). ? diff -r 992bf7540a98 -r f2648ca4ed03 src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c Thu Feb 07 19:39:35 2019 +0300 +++ b/src/http/ngx_http_upstream.c Mon Feb 11 13:36:53 2019 +0900 @@ -850,7 +850,7 @@ ? ngx_http_file_cache_create_key(r); ? - if (r->cache->header_start + 256 >= u->conf->buffer_size) { + if (r->cache->header_start + 256 > u->conf->buffer_size) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%V_buffer_size %uz is not enough for cache key, " "it should be increased to at least %uz", ? ? -------------- next part -------------- An HTML attachment was scrubbed... URL: From xeioex at nginx.com Tue Feb 12 15:56:16 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 12 Feb 2019 15:56:16 +0000 Subject: [njs] Replacing vsprintf with nxt_vsprintf in modules' exceptions API. Message-ID: details: https://hg.nginx.org/njs/rev/1ab2658c7a28 branches: changeset: 775:1ab2658c7a28 user: Dmitry Volyntsev date: Tue Feb 12 18:37:59 2019 +0300 description: Replacing vsprintf with nxt_vsprintf in modules' exceptions API. diffstat: nginx/ngx_http_js_module.c | 3 +-- nginx/ngx_stream_js_module.c | 6 ++---- njs/njs_error.c | 27 +++++++++++++++++---------- njs/njs_error.h | 30 ++++++++++++++++++------------ njs/njs_generator.c | 2 +- njs/njs_parser.c | 2 +- njs/njs_vm.c | 35 ++++++----------------------------- 7 files changed, 46 insertions(+), 59 deletions(-) diffs (239 lines): diff -r eb099f4faf40 -r 1ab2658c7a28 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Mon Feb 11 18:15:43 2019 +0300 +++ b/nginx/ngx_http_js_module.c Tue Feb 12 18:37:59 2019 +0300 @@ -1751,8 +1751,7 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, } if (method == n) { - njs_vm_error(vm, "unknown method \"%.*s\"", - (int) method_name.length, method_name.start); + njs_vm_error(vm, "unknown method \"%V\"", &method_name); return NJS_ERROR; } } diff -r eb099f4faf40 -r 1ab2658c7a28 nginx/ngx_stream_js_module.c --- a/nginx/ngx_stream_js_module.c Mon Feb 11 18:15:43 2019 +0300 +++ b/nginx/ngx_stream_js_module.c Tue Feb 12 18:37:59 2019 +0300 @@ -862,8 +862,7 @@ ngx_stream_js_event(ngx_stream_session_t } if (i == n) { - njs_vm_error(ctx->vm, "unknown event \"%.*s\"", (int) event->length, - event->start); + njs_vm_error(ctx->vm, "unknown event \"%V\"", event); return NULL; } @@ -1053,8 +1052,7 @@ ngx_stream_js_ext_on(njs_vm_t *vm, njs_v } if (*event != NULL) { - njs_vm_error(vm, "event handler \"%.*s\" is already set", - (int) name.length, name.start); + njs_vm_error(vm, "event handler \"%V\" is already set", &name); return NJS_ERROR; } diff -r eb099f4faf40 -r 1ab2658c7a28 njs/njs_error.c --- a/njs/njs_error.c Mon Feb 11 18:15:43 2019 +0300 +++ b/njs/njs_error.c Tue Feb 12 18:37:59 2019 +0300 @@ -15,7 +15,8 @@ static const njs_value_t njs_error_name void -njs_error_new(njs_vm_t *vm, njs_value_type_t type, u_char *start, size_t size) +njs_error_new(njs_vm_t *vm, njs_value_t *dst, njs_value_type_t type, + u_char *start, size_t size) { nxt_int_t ret; njs_value_t string; @@ -29,15 +30,16 @@ njs_error_new(njs_vm_t *vm, njs_value_ty error = njs_error_alloc(vm, type, NULL, &string); if (nxt_fast_path(error != NULL)) { - vm->retval.data.u.object = error; - vm->retval.type = type; - vm->retval.data.truth = 1; + dst->data.u.object = error; + dst->type = type; + dst->data.truth = 1; } } void -njs_error_fmt_new(njs_vm_t *vm, njs_value_type_t type, const char* fmt, ...) +njs_error_fmt_new(njs_vm_t *vm, njs_value_t *dst, njs_value_type_t type, + const char* fmt, ...) { va_list args; u_char buf[NXT_MAX_ERROR_STR], *p; @@ -50,7 +52,7 @@ njs_error_fmt_new(njs_vm_t *vm, njs_valu va_end(args); } - njs_error_new(vm, type, buf, p - buf); + njs_error_new(vm, dst, type, buf, p - buf); } @@ -65,8 +67,7 @@ njs_error_alloc(njs_vm_t *vm, njs_value_ error = nxt_mp_alloc(vm->mem_pool, sizeof(njs_object_t)); if (nxt_slow_path(error == NULL)) { - njs_memory_error(vm); - return NULL; + goto memory_error; } nxt_lvlhsh_init(&error->hash); @@ -86,7 +87,7 @@ njs_error_alloc(njs_vm_t *vm, njs_value_ prop = njs_object_prop_alloc(vm, &njs_error_name_string, name, 1); if (nxt_slow_path(prop == NULL)) { - return NULL; + goto memory_error; } lhq.value = prop; @@ -105,7 +106,7 @@ njs_error_alloc(njs_vm_t *vm, njs_value_ prop = njs_object_prop_alloc(vm, &njs_error_message_string, message, 1); if (nxt_slow_path(prop == NULL)) { - return NULL; + goto memory_error; } prop->enumerable = 0; @@ -120,6 +121,12 @@ njs_error_alloc(njs_vm_t *vm, njs_value_ } return error; + +memory_error: + + njs_memory_error(vm); + + return NULL; } diff -r eb099f4faf40 -r 1ab2658c7a28 njs/njs_error.h --- a/njs/njs_error.h Mon Feb 11 18:15:43 2019 +0300 +++ b/njs/njs_error.h Tue Feb 12 18:37:59 2019 +0300 @@ -9,26 +9,32 @@ #define njs_error(vm, fmt, ...) \ - njs_error_fmt_new(vm, NJS_OBJECT_ERROR, fmt, ##__VA_ARGS__) + njs_error_fmt_new(vm, &vm->retval, NJS_OBJECT_ERROR, fmt, ##__VA_ARGS__) #define njs_eval_error(vm, fmt, ...) \ - njs_error_fmt_new(vm, NJS_OBJECT_EVAL_ERROR, fmt, ##__VA_ARGS__) + njs_error_fmt_new(vm, &vm->retval, NJS_OBJECT_EVAL_ERROR, fmt, \ + ##__VA_ARGS__) #define njs_internal_error(vm, fmt, ...) \ - njs_error_fmt_new(vm, NJS_OBJECT_INTERNAL_ERROR, fmt, \ - ##__VA_ARGS__) + njs_error_fmt_new(vm, &vm->retval, NJS_OBJECT_INTERNAL_ERROR, fmt, \ + ##__VA_ARGS__) #define njs_range_error(vm, fmt, ...) \ - njs_error_fmt_new(vm, NJS_OBJECT_RANGE_ERROR, fmt, ##__VA_ARGS__) + njs_error_fmt_new(vm, &vm->retval, NJS_OBJECT_RANGE_ERROR, fmt, \ + ##__VA_ARGS__) #define njs_reference_error(vm, fmt, ...) \ - njs_error_fmt_new(vm, NJS_OBJECT_REF_ERROR, fmt, ##__VA_ARGS__) + njs_error_fmt_new(vm, &vm->retval, NJS_OBJECT_REF_ERROR, fmt, \ + ##__VA_ARGS__) #define njs_syntax_error(vm, fmt, ...) \ - njs_error_fmt_new(vm, NJS_OBJECT_SYNTAX_ERROR, fmt, ##__VA_ARGS__) + njs_error_fmt_new(vm, &vm->retval, NJS_OBJECT_SYNTAX_ERROR, fmt, \ + ##__VA_ARGS__) #define njs_type_error(vm, fmt, ...) \ - njs_error_fmt_new(vm, NJS_OBJECT_TYPE_ERROR, fmt, ##__VA_ARGS__) + njs_error_fmt_new(vm, &vm->retval, NJS_OBJECT_TYPE_ERROR, fmt, \ + ##__VA_ARGS__) #define njs_uri_error(vm, fmt, ...) \ - njs_error_fmt_new(vm, NJS_OBJECT_URI_ERROR, fmt, ##__VA_ARGS__) + njs_error_fmt_new(vm, &vm->retval, NJS_OBJECT_URI_ERROR, fmt, \ + ##__VA_ARGS__) -void njs_error_new(njs_vm_t *vm, njs_value_type_t type, u_char *start, - size_t size); -void njs_error_fmt_new(njs_vm_t *vm, njs_value_type_t type, +void njs_error_new(njs_vm_t *vm, njs_value_t *dst, njs_value_type_t type, + u_char *start, size_t size); +void njs_error_fmt_new(njs_vm_t *vm, njs_value_t *dst, njs_value_type_t type, const char* fmt, ...); void njs_memory_error(njs_vm_t *vm); diff -r eb099f4faf40 -r 1ab2658c7a28 njs/njs_generator.c --- a/njs/njs_generator.c Mon Feb 11 18:15:43 2019 +0300 +++ b/njs/njs_generator.c Tue Feb 12 18:37:59 2019 +0300 @@ -3191,5 +3191,5 @@ njs_generate_syntax_error(njs_vm_t *vm, p = nxt_sprintf(p, end, " in %uD", node->token_line); } - njs_error_new(vm, NJS_OBJECT_SYNTAX_ERROR, msg, p - msg); + njs_error_new(vm, &vm->retval, NJS_OBJECT_SYNTAX_ERROR, msg, p - msg); } diff -r eb099f4faf40 -r 1ab2658c7a28 njs/njs_parser.c --- a/njs/njs_parser.c Mon Feb 11 18:15:43 2019 +0300 +++ b/njs/njs_parser.c Tue Feb 12 18:37:59 2019 +0300 @@ -2759,5 +2759,5 @@ njs_parser_error(njs_vm_t *vm, njs_parse p = nxt_sprintf(p, end, " in %uD", lexer->line); } - njs_error_new(vm, type, msg, p - msg); + njs_error_new(vm, &vm->retval, type, msg, p - msg); } diff -r eb099f4faf40 -r 1ab2658c7a28 njs/njs_vm.c --- a/njs/njs_vm.c Mon Feb 11 18:15:43 2019 +0300 +++ b/njs/njs_vm.c Tue Feb 12 18:37:59 2019 +0300 @@ -3329,41 +3329,18 @@ njs_value_data_set(njs_value_t *value, v void njs_value_error_set(njs_vm_t *vm, njs_value_t *value, const char *fmt, ...) { - size_t size; - va_list args; - nxt_int_t ret; - njs_value_t string; - njs_object_t *error; - char buf[256]; + va_list args; + u_char buf[NXT_MAX_ERROR_STR], *p; + + p = buf; if (fmt != NULL) { va_start(args, fmt); - size = vsnprintf(buf, sizeof(buf), fmt, args); + p = nxt_vsprintf(buf, buf + sizeof(buf), fmt, args); va_end(args); - - } else { - size = 0; - } - - ret = njs_string_new(vm, &string, (u_char *) buf, size, size); - if (nxt_slow_path(ret != NXT_OK)) { - goto memory_error; } - error = njs_error_alloc(vm, NJS_OBJECT_ERROR, NULL, &string); - if (nxt_slow_path(error == NULL)) { - goto memory_error; - } - - value->data.u.object = error; - value->type = NJS_OBJECT_ERROR; - value->data.truth = 1; - - return; - -memory_error: - - njs_memory_error_set(vm, value); + njs_error_new(vm, value, NJS_OBJECT_ERROR, buf, p - buf); } From xeioex at nginx.com Tue Feb 12 15:56:16 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 12 Feb 2019 15:56:16 +0000 Subject: [njs] Eliminating sprintf() and vsnprintf() usage. Message-ID: details: https://hg.nginx.org/njs/rev/03be823cd95b branches: changeset: 776:03be823cd95b user: Dmitry Volyntsev date: Tue Feb 12 18:56:04 2019 +0300 description: Eliminating sprintf() and vsnprintf() usage. diffstat: njs/njs_builtin.c | 21 ++++++++++----------- njs/njs_date.c | 28 ++++++++++++---------------- njs/njs_json.c | 9 ++++----- njs/njs_number.h | 9 +++++---- njs/njs_regexp.c | 5 +++-- njs/njs_shell.c | 12 ++++++------ njs/njs_time.c | 8 +++++--- njs/test/njs_unit_test.c | 9 ++++----- nxt/nxt_string.h | 3 +++ nxt/nxt_trace.c | 9 +++++---- 10 files changed, 57 insertions(+), 56 deletions(-) diffs (335 lines): diff -r 1ab2658c7a28 -r 03be823cd95b njs/njs_builtin.c --- a/njs/njs_builtin.c Tue Feb 12 18:37:59 2019 +0300 +++ b/njs/njs_builtin.c Tue Feb 12 18:56:04 2019 +0300 @@ -595,7 +595,7 @@ njs_builtin_completions_size(njs_vm_t *v static nxt_array_t * njs_builtin_completions(njs_vm_t *vm, nxt_array_t *array) { - char *compl; + u_char *compl; size_t n, len; nxt_str_t string, *completions; nxt_uint_t i, k; @@ -634,7 +634,8 @@ njs_builtin_completions(njs_vm_t *vm, nx return NULL; } - snprintf(compl, len, "%s.%s", obj->name.start, string.start); + nxt_sprintf(compl, compl + len, "%s.%s%Z", obj->name.start, + string.start); completions[n].length = len; completions[n++].start = (u_char *) compl; @@ -654,12 +655,10 @@ njs_builtin_completions(njs_vm_t *vm, nx return NULL; } - snprintf(compl, len, ".%s", string.start); + nxt_sprintf(compl, compl + len, ".%s%Z", string.start); for (k = 0; k < n; k++) { - if (strncmp((char *) completions[k].start, compl, len) - == 0) - { + if (nxt_strncmp(completions[k].start, compl, len) == 0) { break; } } @@ -684,7 +683,8 @@ njs_builtin_completions(njs_vm_t *vm, nx return NULL; } - snprintf(compl, len, "%s.%s", obj->name.start, string.start); + nxt_sprintf(compl, compl + len, "%s.%s%Z", obj->name.start, + string.start); completions[n].length = len; completions[n++].start = (u_char *) compl; @@ -710,7 +710,7 @@ njs_builtin_completions(njs_vm_t *vm, nx return NULL; } - snprintf(compl, len, "%.*s", (int) ev->name.length, ev->name.start); + nxt_sprintf(compl, compl + len, "%V%Z", &ev->name); completions[n].length = len; completions[n++].start = (u_char *) compl; @@ -728,9 +728,8 @@ njs_builtin_completions(njs_vm_t *vm, nx return NULL; } - snprintf(compl, len, "%.*s.%.*s", (int) ev->name.length, - ev->name.start, (int) ext_prop->name.length, - ext_prop->name.start); + nxt_sprintf(compl, compl + len, "%V.%V%Z", &ev->name, + &ext_prop->name); completions[n].length = len; completions[n++].start = (u_char *) compl; diff -r 1ab2658c7a28 -r 03be823cd95b njs/njs_date.c --- a/njs/njs_date.c Tue Feb 12 18:37:59 2019 +0300 +++ b/njs/njs_date.c Tue Feb 12 18:56:04 2019 +0300 @@ -984,9 +984,8 @@ njs_date_prototype_to_utc_string(njs_vm_ nxt_uint_t nargs, njs_index_t unused) { double time; - size_t size; time_t clock; - u_char buf[NJS_DATE_TIME_LEN]; + u_char buf[NJS_DATE_TIME_LEN], *p; struct tm tm; static const char *week[] = { "Sun", "Mon", "Tue", "Wed", @@ -1001,13 +1000,12 @@ njs_date_prototype_to_utc_string(njs_vm_ clock = time / 1000; gmtime_r(&clock, &tm); - size = snprintf((char *) buf, NJS_DATE_TIME_LEN, + p = nxt_sprintf(buf, buf + NJS_DATE_TIME_LEN, "%s %s %02d %4d %02d:%02d:%02d GMT", - week[tm.tm_wday], month[tm.tm_mon], - tm.tm_mday, tm.tm_year + 1900, - tm.tm_hour, tm.tm_min, tm.tm_sec); - - return njs_string_new(vm, &vm->retval, buf, size, size); + week[tm.tm_wday], month[tm.tm_mon], tm.tm_mday, + tm.tm_year + 1900, tm.tm_hour, tm.tm_min, tm.tm_sec); + + return njs_string_new(vm, &vm->retval, buf, p - buf, p - buf); } vm->retval = njs_string_invalid_date; @@ -1029,9 +1027,8 @@ njs_date_to_string(njs_vm_t *vm, njs_val { int32_t year; double time; - size_t size; time_t clock; - u_char buf[NJS_ISO_DATE_TIME_LEN]; + u_char buf[NJS_ISO_DATE_TIME_LEN], *p; struct tm tm; time = date->data.u.date->time; @@ -1043,14 +1040,13 @@ njs_date_to_string(njs_vm_t *vm, njs_val year = tm.tm_year + 1900; - size = snprintf((char *) buf, NJS_ISO_DATE_TIME_LEN, + p = nxt_sprintf(buf, buf + NJS_ISO_DATE_TIME_LEN, (year < 0) ? "%07d-%02d-%02dT%02d:%02d:%02d.%03dZ" : "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", - year, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec, - (int) ((int64_t) time % 1000)); - - return njs_string_new(vm, retval, buf, size, size); + year, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, + tm.tm_sec, (int) ((int64_t) time % 1000)); + + return njs_string_new(vm, retval, buf, p - buf, p - buf); } vm->retval = njs_string_invalid_date; diff -r 1ab2658c7a28 -r 03be823cd95b njs/njs_json.c --- a/njs/njs_json.c Tue Feb 12 18:37:59 2019 +0300 +++ b/njs/njs_json.c Tue Feb 12 18:56:04 2019 +0300 @@ -2069,13 +2069,12 @@ const njs_object_init_t njs_json_object static nxt_int_t njs_dump_value(njs_json_stringify_t *stringify, const njs_value_t *value) { - size_t len; njs_ret_t ret; nxt_str_t str; nxt_uint_t written; njs_value_t str_val; const njs_extern_t *ext_proto; - char buf[32]; + u_char buf[32], *p; njs_ret_t (*to_string)(njs_vm_t *, njs_value_t *, const njs_value_t *); @@ -2243,9 +2242,9 @@ njs_dump_value(njs_json_stringify_t *str return njs_json_buf_append(stringify, (char *) str.start, str.length); default: - len = snprintf(buf, sizeof(buf), "[Unknown value type:%d]", - value->type); - return njs_json_buf_append(stringify, buf, len); + p = nxt_sprintf(buf, buf + nxt_length(buf), "[Unknown value type:%uD]", + value->type); + return njs_json_buf_append(stringify, (char *) buf, p - buf); } return ret; diff -r 1ab2658c7a28 -r 03be823cd95b njs/njs_number.h --- a/njs/njs_number.h Tue Feb 12 18:37:59 2019 +0300 +++ b/njs/njs_number.h Tue Feb 12 18:56:04 2019 +0300 @@ -62,11 +62,12 @@ njs_char_to_hex(u_char c) nxt_inline void njs_uint32_to_string(njs_value_t *value, uint32_t u32) { - size_t size; + u_char *dst, *p; - size = snprintf((char *) njs_string_short_start(value), - NJS_STRING_SHORT, "%u", u32); - njs_string_short_set(value, size, size); + dst = njs_string_short_start(value); + p = nxt_sprintf(dst, dst + NJS_STRING_SHORT, "%uD", u32); + + njs_string_short_set(value, p - dst, p - dst); } diff -r 1ab2658c7a28 -r 03be823cd95b njs/njs_regexp.c --- a/njs/njs_regexp.c Tue Feb 12 18:37:59 2019 +0300 +++ b/njs/njs_regexp.c Tue Feb 12 18:56:04 2019 +0300 @@ -378,10 +378,11 @@ njs_regexp_compile_trace_handler(nxt_tra p = trace->handler(trace, td, start); if (vm->parser != NULL) { - njs_syntax_error(vm, "%s in %uD", start, vm->parser->lexer->line); + njs_syntax_error(vm, "%*s in %uD", (int) (p - start), start, + vm->parser->lexer->line); } else { - njs_syntax_error(vm, "%s", start); + njs_syntax_error(vm, "%*s", (int) (p - start), start); } return p; diff -r 1ab2658c7a28 -r 03be823cd95b njs/njs_shell.c --- a/njs/njs_shell.c Tue Feb 12 18:37:59 2019 +0300 +++ b/njs/njs_shell.c Tue Feb 12 18:56:04 2019 +0300 @@ -719,7 +719,7 @@ next: continue; } - if (strncmp(text, (char *) var->name.start, cmpl->length) == 0) { + if (nxt_strncmp(text, var->name.start, cmpl->length) == 0) { return njs_editline(&var->name); } } @@ -769,8 +769,8 @@ next: suffix = njs_completion(cmpl->suffix_completions, cmpl->index++); - if (len != 0 && strncmp((char *) suffix->start, p, - nxt_min(len, suffix->length)) != 0) + if (len != 0 && nxt_strncmp(suffix->start, p, + nxt_min(len, suffix->length)) != 0) { continue; } @@ -781,8 +781,8 @@ next: return NULL; } - snprintf(completion, len, "%.*s%.*s", (int) (p - text), text, - (int) suffix->length, suffix->start); + nxt_sprintf((u_char *) completion, (u_char *) completion + len, + "%*s%V%Z", (int) (p - text), text, suffix); return completion; } @@ -803,7 +803,7 @@ next: continue; } - if (strncmp(text, (char *) suffix->start, cmpl->length) == 0) { + if (nxt_strncmp(text, suffix->start, cmpl->length) == 0) { return njs_editline(suffix); } } diff -r 1ab2658c7a28 -r 03be823cd95b njs/njs_time.c --- a/njs/njs_time.c Tue Feb 12 18:37:59 2019 +0300 +++ b/njs/njs_time.c Tue Feb 12 18:56:04 2019 +0300 @@ -100,7 +100,7 @@ njs_ret_t njs_clear_timeout(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) { - u_char buf[16]; + u_char buf[16], *p; njs_ret_t ret; njs_event_t *event; nxt_lvlhsh_query_t lhq; @@ -110,9 +110,11 @@ njs_clear_timeout(njs_vm_t *vm, njs_valu return NJS_OK; } + p = nxt_sprintf(buf, buf + nxt_length(buf), "%uD", + (unsigned) args[1].data.u.number); + lhq.key.start = buf; - lhq.key.length = snprintf((char *) buf, sizeof(buf) - 1, "%u", - (unsigned) args[1].data.u.number); + lhq.key.length = p - buf; lhq.key_hash = nxt_djb_hash(lhq.key.start, lhq.key.length); lhq.proto = &njs_event_hash_proto; lhq.pool = vm->mem_pool; diff -r 1ab2658c7a28 -r 03be823cd95b njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Tue Feb 12 18:37:59 2019 +0300 +++ b/njs/test/njs_unit_test.c Tue Feb 12 18:56:04 2019 +0300 @@ -11288,15 +11288,14 @@ static njs_ret_t njs_unit_test_r_get_a_external(njs_vm_t *vm, njs_value_t *value, void *obj, uintptr_t data) { - char buf[16]; - size_t len; + u_char buf[16], *p; njs_unit_test_req_t *r; r = (njs_unit_test_req_t *) obj; - len = sprintf(buf, "%u", r->a); - - return njs_string_create(vm, value, (u_char *) buf, len, 0); + p = nxt_sprintf(buf, buf + nxt_length(buf), "%uD", r->a); + + return njs_string_create(vm, value, buf, p - buf, 0); } diff -r 1ab2658c7a28 -r 03be823cd95b nxt/nxt_string.h --- a/nxt/nxt_string.h Tue Feb 12 18:37:59 2019 +0300 +++ b/nxt/nxt_string.h Tue Feb 12 18:56:04 2019 +0300 @@ -44,6 +44,9 @@ nxt_upper_case(u_char c) #define nxt_cpymem(dst, src, n) (((u_char *) memcpy(dst, src, n)) + (n)) +#define nxt_strncmp(s1, s2, n) strncmp((char *) s1, (char *) s2, n) + + #define nxt_memset(buf, c, length) (void) (memset(buf, c, length)) diff -r 1ab2658c7a28 -r 03be823cd95b nxt/nxt_trace.c --- a/nxt/nxt_trace.c Tue Feb 12 18:37:59 2019 +0300 +++ b/nxt/nxt_trace.c Tue Feb 12 18:56:04 2019 +0300 @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -15,14 +16,14 @@ static u_char * nxt_last_handler(nxt_trace_t *trace, nxt_trace_data_t *td, u_char *start) { - int n; + u_char *p; ssize_t size; size = td->end - start; - n = vsnprintf((char *) start, size, td->fmt, td->args); + p = nxt_vsprintf(start, start + size, td->fmt, td->args); - if (n < size) { - start += n; + if (p - start < size) { + start = p; } return start; From mdounin at mdounin.ru Tue Feb 12 19:41:38 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 12 Feb 2019 19:41:38 +0000 Subject: [nginx] Upstream: fixed logging of required buffer size (ticket #1722). Message-ID: details: https://hg.nginx.org/nginx/rev/608810849b6d branches: changeset: 7456:608810849b6d user: Chanhun Jeong date: Mon Feb 11 13:36:53 2019 +0900 description: Upstream: fixed logging of required buffer size (ticket #1722). diffstat: src/http/ngx_http_upstream.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -850,7 +850,7 @@ ngx_http_upstream_cache(ngx_http_request ngx_http_file_cache_create_key(r); - if (r->cache->header_start + 256 >= u->conf->buffer_size) { + if (r->cache->header_start + 256 > u->conf->buffer_size) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%V_buffer_size %uz is not enough for cache key, " "it should be increased to at least %uz", From mdounin at mdounin.ru Tue Feb 12 19:41:40 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 12 Feb 2019 19:41:40 +0000 Subject: [nginx] Slab: removed redundant page calculation (ticket #1721). Message-ID: details: https://hg.nginx.org/nginx/rev/d97d09ef3afe branches: changeset: 7457:d97d09ef3afe user: Maxim Dounin date: Tue Feb 12 21:51:15 2019 +0300 description: Slab: removed redundant page calculation (ticket #1721). diffstat: src/core/ngx_slab.c | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diffs (15 lines): diff --git a/src/core/ngx_slab.c b/src/core/ngx_slab.c --- a/src/core/ngx_slab.c +++ b/src/core/ngx_slab.c @@ -635,10 +635,9 @@ ngx_slab_free_locked(ngx_slab_pool_t *po goto fail; } - n = ((u_char *) p - pool->start) >> ngx_pagesize_shift; size = slab & ~NGX_SLAB_PAGE_START; - ngx_slab_free_pages(pool, &pool->pages[n], size); + ngx_slab_free_pages(pool, page, size); ngx_slab_junk(p, size << ngx_pagesize_shift); From mdounin at mdounin.ru Tue Feb 12 19:42:24 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 12 Feb 2019 22:42:24 +0300 Subject: Fix buffer size comparison for the case header_start + 256 has same value to buffer_size (ticket #17 In-Reply-To: <127871f3e28adcdc1ec9fab1a955a6@cweb03.nmdf.nhnsystem.com> References: <127871f3e28adcdc1ec9fab1a955a6@cweb03.nmdf.nhnsystem.com> Message-ID: <20190212194223.GI1877@mdounin.ru> Hello! On Tue, Feb 12, 2019 at 11:38:41AM +0900, ??? wrote: > # HG changeset patch > # User Chanhun Jeong > # Date 1549859813 -32400 > # Mon Feb 11 13:36:53 2019 +0900 > # Node ID f2648ca4ed03a907e6d3c22729be82b3bc4027a0 > # Parent 992bf7540a980c48a37c305d2c511cf9a48fe701 > Fix buffer size comparison for the case header_start + 256 has same value to buffer_size (ticket #1722). > ? > diff -r 992bf7540a98 -r f2648ca4ed03 src/http/ngx_http_upstream.c > --- a/src/http/ngx_http_upstream.c Thu Feb 07 19:39:35 2019 +0300 > +++ b/src/http/ngx_http_upstream.c Mon Feb 11 13:36:53 2019 +0900 > @@ -850,7 +850,7 @@ > ? > ngx_http_file_cache_create_key(r); > ? > - if (r->cache->header_start + 256 >= u->conf->buffer_size) { > + if (r->cache->header_start + 256 > u->conf->buffer_size) { > ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, > "%V_buffer_size %uz is not enough for cache key, " > "it should be increased to at least %uz", > ? > ? Committed (with a fixed commit message), thanks. -- Maxim Dounin http://mdounin.ru/ From xeioex at nginx.com Thu Feb 14 11:41:43 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 14 Feb 2019 11:41:43 +0000 Subject: [njs] Fixed parsing of string literals. Message-ID: details: https://hg.nginx.org/njs/rev/2a425a8ea90f branches: changeset: 777:2a425a8ea90f user: Dmitry Volyntsev date: Thu Feb 14 14:40:50 2019 +0300 description: Fixed parsing of string literals. This closes #93 issue on Github. diffstat: njs/njs_lexer.c | 11 +++++++++++ njs/test/njs_unit_test.c | 35 +++++++++++++++++++++++++++++++---- 2 files changed, 42 insertions(+), 4 deletions(-) diffs (106 lines): diff -r 03be823cd95b -r 2a425a8ea90f njs/njs_lexer.c --- a/njs/njs_lexer.c Tue Feb 12 18:56:04 2019 +0300 +++ b/njs/njs_lexer.c Thu Feb 14 14:40:50 2019 +0300 @@ -530,11 +530,22 @@ njs_lexer_string(njs_lexer_t *lexer, u_c } p++; + + /* Line continuation. */ + if (p < lexer->end && p[-1] == '\r' && p[0] == '\n') { + p++; + } + escape = 1; continue; } + /* Line terminator. */ + if (c == '\r' || c == '\n') { + break; + } + if (c == quote) { lexer->start = p; lexer->text.length = (p - 1) - lexer->text.start; diff -r 03be823cd95b -r 2a425a8ea90f njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Tue Feb 12 18:56:04 2019 +0300 +++ b/njs/test/njs_unit_test.c Thu Feb 14 14:40:50 2019 +0300 @@ -2863,7 +2863,7 @@ static njs_unit_test_t njs_test[] = { nxt_string("({[]:1})"), nxt_string("SyntaxError: Unexpected token \"[\" in 1") }, - { nxt_string("({'AB\n\\cd':1})['AB\n\\cd']"), + { nxt_string("({'AB\\ncd':1})['AB\\ncd']"), nxt_string("1") }, /* Inheritance. */ @@ -3935,6 +3935,15 @@ static njs_unit_test_t njs_test[] = { nxt_string("'\\a \\' \\\" \\\\ \\0 \\b \\f \\n \\r \\t \\v'"), nxt_string("a ' \" \\ \0 \b \f \n \r \t \v") }, + { nxt_string("'\\\n'"), + nxt_string("") }, + + { nxt_string("'\\\r'"), + nxt_string("") }, + + { nxt_string("'\\\r\n'"), + nxt_string("") }, + { nxt_string("'a\\\nb'"), nxt_string("ab") }, @@ -3944,15 +3953,33 @@ static njs_unit_test_t njs_test[] = { nxt_string("'a\\\r\nb'"), nxt_string("ab") }, + { nxt_string("'a\\\n\rb'"), + nxt_string("SyntaxError: Unterminated string \"'a\\\n\r\" in 1") }, + + { nxt_string("'a\\\nb\nc'"), + nxt_string("SyntaxError: Unterminated string \"'a\\\nb\n\" in 1") }, + { nxt_string("'abcde"), nxt_string("SyntaxError: Unterminated string \"'abcde\" in 1") }, { nxt_string("'\\"), nxt_string("SyntaxError: Unterminated string \"'\\\" in 1") }, + { nxt_string("'\\\r\n"), + nxt_string("SyntaxError: Unterminated string \"'\\\r\n\" in 1") }, + { nxt_string("'\\'"), nxt_string("SyntaxError: Unterminated string \"'\\'\" in 1") }, + { nxt_string("'a\n"), + nxt_string("SyntaxError: Unterminated string \"'a\n\" in 1") }, + + { nxt_string("'a\r"), + nxt_string("SyntaxError: Unterminated string \"'a\r\" in 1") }, + + { nxt_string("\"a\n"), + nxt_string("SyntaxError: Unterminated string \"\"a\n\" in 1") }, + { nxt_string("'\\u03B1'"), nxt_string("?") }, @@ -10464,14 +10491,14 @@ static njs_unit_test_t njs_test[] = { nxt_string("JSON.stringify('??z'.repeat(10)).length"), nxt_string("32") }, - { nxt_string("JSON.stringify('a\nbc')"), + { nxt_string("JSON.stringify('a\\nbc')"), nxt_string("\"a\\nbc\"") }, { nxt_string("JSON.stringify('?\t??')"), nxt_string("\"?\\t??\"") }, - { nxt_string("JSON.stringify('\n\t\r\"\f\b ')"), - nxt_string("\"\\n\\t\\r\\\"\\f\\b \"") }, + { nxt_string("JSON.stringify('\\n\\t\\r\\\"\\f\\b')"), + nxt_string("\"\\n\\t\\r\\\"\\f\\b\"") }, { nxt_string("JSON.stringify('\x00\x01\x02\x1f')"), nxt_string("\"\\u0000\\u0001\\u0002\\u001F\"") }, From xeioex at nginx.com Thu Feb 14 13:34:32 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 14 Feb 2019 13:34:32 +0000 Subject: [njs] Fixed line number in reporting variable reference errors. Message-ID: details: https://hg.nginx.org/njs/rev/3852b2044dfd branches: changeset: 778:3852b2044dfd user: Dmitry Volyntsev date: Thu Feb 14 15:21:02 2019 +0300 description: Fixed line number in reporting variable reference errors. This closes #94 issue on Github. diffstat: njs/njs_generator.c | 42 ++------------------------------- njs/njs_parser.c | 60 +++++++++++++++++++++++++++++++++-------------- njs/njs_parser.h | 15 ++++++++---- njs/njs_variable.c | 3 +- njs/test/njs_unit_test.c | 6 ++++ 5 files changed, 63 insertions(+), 63 deletions(-) diffs (210 lines): diff -r 2a425a8ea90f -r 3852b2044dfd njs/njs_generator.c --- a/njs/njs_generator.c Thu Feb 14 14:40:50 2019 +0300 +++ b/njs/njs_generator.c Thu Feb 14 15:21:02 2019 +0300 @@ -162,9 +162,6 @@ static nxt_noinline nxt_int_t njs_genera static nxt_int_t njs_generate_function_debug(njs_vm_t *vm, nxt_str_t *name, njs_function_lambda_t *lambda, njs_parser_node_t *node); -static void njs_generate_syntax_error(njs_vm_t *vm, njs_parser_node_t *node, - const char *fmt, ...); - #define njs_generate_code(generator, type, code) \ do { \ @@ -207,6 +204,9 @@ static void njs_generate_syntax_error(nj njs_code_offset_diff(generator, patch->jump_offset) +#define njs_generate_syntax_error(vm, node, fmt, ...) \ + njs_parser_node_error(vm, node, NJS_OBJECT_SYNTAX_ERROR, fmt, ##__VA_ARGS__) + static const nxt_str_t no_label = { 0, NULL }; @@ -3157,39 +3157,3 @@ njs_generate_function_debug(njs_vm_t *vm return NXT_OK; } - - -static void -njs_generate_syntax_error(njs_vm_t *vm, njs_parser_node_t *node, - const char *fmt, ...) -{ - size_t width; - u_char msg[NXT_MAX_ERROR_STR]; - u_char *p, *end; - va_list args; - njs_parser_scope_t *scope; - - p = msg; - end = msg + NXT_MAX_ERROR_STR; - - va_start(args, fmt); - p = nxt_vsprintf(p, end, fmt, args); - va_end(args); - - scope = node->scope; - - width = nxt_length(" in ") + scope->file.length + NXT_INT_T_LEN; - - if (p > end - width) { - p = end - width; - } - - if (scope->file.start != NULL) { - p = nxt_sprintf(p, end, " in %V:%uD", &scope->file, node->token_line); - - } else { - p = nxt_sprintf(p, end, " in %uD", node->token_line); - } - - njs_error_new(vm, &vm->retval, NJS_OBJECT_SYNTAX_ERROR, msg, p - msg); -} diff -r 2a425a8ea90f -r 3852b2044dfd njs/njs_parser.c --- a/njs/njs_parser.c Thu Feb 14 14:40:50 2019 +0300 +++ b/njs/njs_parser.c Thu Feb 14 15:21:02 2019 +0300 @@ -2141,6 +2141,8 @@ njs_parser_reference(njs_vm_t *vm, njs_p case NJS_TOKEN_NAME: nxt_thread_log_debug("JS: %V", name); + node->token_line = parser->lexer->token_line; + ext = njs_external_lookup(vm, name, hash); if (ext != NULL) { @@ -2727,37 +2729,59 @@ njs_parser_trace_handler(nxt_trace_t *tr } -void -njs_parser_error(njs_vm_t *vm, njs_parser_t *parser, njs_value_type_t type, - const char *fmt, ...) +static void +njs_parser_scope_error(njs_vm_t *vm, njs_parser_scope_t *scope, + njs_value_type_t type, uint32_t line, const char *fmt, va_list args) { - size_t width; - u_char *p, *end; - u_char msg[NXT_MAX_ERROR_STR]; - va_list args; - njs_lexer_t *lexer; + size_t width; + u_char msg[NXT_MAX_ERROR_STR]; + u_char *p, *end; + nxt_str_t *file; + + file = &scope->file; p = msg; end = msg + NXT_MAX_ERROR_STR; - va_start(args, fmt); p = nxt_vsprintf(p, end, fmt, args); - va_end(args); - - lexer = parser->lexer; - - width = nxt_length(" in ") + lexer->file.length + NXT_INT_T_LEN; + + width = nxt_length(" in ") + file->length + NXT_INT_T_LEN; if (p > end - width) { p = end - width; } - if (lexer->file.start != NULL) { - p = nxt_sprintf(p, end, " in %V:%uD", &lexer->file, lexer->line); + if (file->start != NULL) { + p = nxt_sprintf(p, end, " in %V:%uD", file, line); } else { - p = nxt_sprintf(p, end, " in %uD", lexer->line); + p = nxt_sprintf(p, end, " in %uD", line); } njs_error_new(vm, &vm->retval, type, msg, p - msg); - } +} + + +void +njs_parser_lexer_error(njs_vm_t *vm, njs_parser_t *parser, + njs_value_type_t type, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + njs_parser_scope_error(vm, parser->scope, type, parser->lexer->line, fmt, + args); + va_end(args); +} + + +void +njs_parser_node_error(njs_vm_t *vm, njs_parser_node_t *node, + njs_value_type_t type, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + njs_parser_scope_error(vm, node->scope, type, node->token_line, fmt, args); + va_end(args); +} diff -r 2a425a8ea90f -r 3852b2044dfd njs/njs_parser.h --- a/njs/njs_parser.h Thu Feb 14 14:40:50 2019 +0300 +++ b/njs/njs_parser.h Thu Feb 14 15:21:02 2019 +0300 @@ -329,14 +329,19 @@ njs_index_t njs_variable_index(njs_vm_t nxt_bool_t njs_parser_has_side_effect(njs_parser_node_t *node); u_char *njs_parser_trace_handler(nxt_trace_t *trace, nxt_trace_data_t *td, u_char *start); -void njs_parser_error(njs_vm_t *vm, njs_parser_t *parser, +void njs_parser_lexer_error(njs_vm_t *vm, njs_parser_t *parser, + njs_value_type_t type, const char *fmt, ...); +void njs_parser_node_error(njs_vm_t *vm, njs_parser_node_t *node, njs_value_type_t type, const char *fmt, ...); -#define njs_parser_syntax_error(vm, parser, fmt, ...) \ - njs_parser_error(vm, parser, NJS_OBJECT_SYNTAX_ERROR, fmt, ##__VA_ARGS__) -#define njs_parser_ref_error(vm, parser, fmt, ...) \ - njs_parser_error(vm, parser, NJS_OBJECT_REF_ERROR, fmt, ##__VA_ARGS__) +#define njs_parser_syntax_error(vm, parser, fmt, ...) \ + njs_parser_lexer_error(vm, parser, NJS_OBJECT_SYNTAX_ERROR, fmt, \ + ##__VA_ARGS__) + + +#define njs_parser_ref_error(vm, parser, fmt, ...) \ + njs_parser_lexer_error(vm, parser, NJS_OBJECT_REF_ERROR, fmt, ##__VA_ARGS__) nxt_inline njs_parser_node_t * diff -r 2a425a8ea90f -r 3852b2044dfd njs/njs_variable.c --- a/njs/njs_variable.c Thu Feb 14 14:40:50 2019 +0300 +++ b/njs/njs_variable.c Thu Feb 14 15:21:02 2019 +0300 @@ -344,7 +344,8 @@ njs_variable_resolve(njs_vm_t *vm, njs_p not_found: - njs_parser_ref_error(vm, vm->parser, "\"%V\" is not defined", &vr->name); + njs_parser_node_error(vm, node, NJS_OBJECT_REF_ERROR, + "\"%V\" is not defined", &vr->name); return NULL; } diff -r 2a425a8ea90f -r 3852b2044dfd njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Thu Feb 14 14:40:50 2019 +0300 +++ b/njs/test/njs_unit_test.c Thu Feb 14 15:21:02 2019 +0300 @@ -2107,6 +2107,12 @@ static njs_unit_test_t njs_test[] = { nxt_string("a"), nxt_string("ReferenceError: \"a\" is not defined in 1") }, + { nxt_string("\na"), + nxt_string("ReferenceError: \"a\" is not defined in 2") }, + + { nxt_string("\n\na"), + nxt_string("ReferenceError: \"a\" is not defined in 3") }, + { nxt_string("a + a"), nxt_string("ReferenceError: \"a\" is not defined in 1") }, From xeioex at nginx.com Thu Feb 14 14:25:11 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 14 Feb 2019 14:25:11 +0000 Subject: [njs] Style. Message-ID: details: https://hg.nginx.org/njs/rev/dde9a253361e branches: changeset: 779:dde9a253361e user: Dmitry Volyntsev date: Thu Feb 14 17:01:26 2019 +0300 description: Style. diffstat: nginx/ngx_http_js_module.c | 2 +- njs/njs_regexp.c | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diffs (27 lines): diff -r 3852b2044dfd -r dde9a253361e nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Thu Feb 14 15:21:02 2019 +0300 +++ b/nginx/ngx_http_js_module.c Thu Feb 14 17:01:26 2019 +0300 @@ -1967,7 +1967,7 @@ ngx_http_js_ext_get_parent(njs_vm_t *vm, static njs_ret_t ngx_http_js_ext_get_reply_body(njs_vm_t *vm, njs_value_t *value, void *obj, - uintptr_t data) + uintptr_t data) { size_t len; u_char *p; diff -r 3852b2044dfd -r dde9a253361e njs/njs_regexp.c --- a/njs/njs_regexp.c Thu Feb 14 15:21:02 2019 +0300 +++ b/njs/njs_regexp.c Thu Feb 14 17:01:26 2019 +0300 @@ -268,9 +268,8 @@ njs_regexp_pattern_create(njs_vm_t *vm, size += ((flags & NJS_REGEXP_IGNORE_CASE) != 0); size += ((flags & NJS_REGEXP_MULTILINE) != 0); - pattern = nxt_mp_zalloc(vm->mem_pool, - sizeof(njs_regexp_pattern_t) - + 1 + length + size + 1); + pattern = nxt_mp_zalloc(vm->mem_pool, sizeof(njs_regexp_pattern_t) + 1 + + length + size + 1); if (nxt_slow_path(pattern == NULL)) { njs_memory_error(vm); return NULL; From xeioex at nginx.com Fri Feb 15 15:51:43 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 15 Feb 2019 15:51:43 +0000 Subject: [njs] Fixed String.prototype.split() for unicode strings. Message-ID: details: https://hg.nginx.org/njs/rev/8c422e42448e branches: changeset: 781:8c422e42448e user: Dmitry Volyntsev date: Thu Feb 14 21:19:51 2019 +0300 description: Fixed String.prototype.split() for unicode strings. This closes #95 issue on Github. diffstat: njs/njs_string.c | 8 ++++---- njs/test/njs_unit_test.c | 12 ++++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diffs (47 lines): diff -r e1bfc7be7c55 -r 8c422e42448e njs/njs_string.c --- a/njs/njs_string.c Thu Feb 14 21:19:51 2019 +0300 +++ b/njs/njs_string.c Thu Feb 14 21:19:51 2019 +0300 @@ -2798,8 +2798,8 @@ njs_string_prototype_split(njs_vm_t *vm, /* Empty split string. */ if (p == next) { - p++; - next++; + p = nxt_utf8_next(p, end); + next = p; } size = p - start; @@ -2845,8 +2845,8 @@ njs_string_prototype_split(njs_vm_t *vm, /* Empty split regexp. */ if (p == next) { - p++; - next++; + p = nxt_utf8_next(p, end); + next = p; } size = p - start; diff -r e1bfc7be7c55 -r 8c422e42448e njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Thu Feb 14 21:19:51 2019 +0300 +++ b/njs/test/njs_unit_test.c Thu Feb 14 21:19:51 2019 +0300 @@ -5078,6 +5078,18 @@ static njs_unit_test_t njs_test[] = { nxt_string("'abc'.split('')"), nxt_string("a,b,c") }, + { nxt_string("'???'.split('')"), + nxt_string("?,?,?") }, + + { nxt_string("'???'.split('')"), + nxt_string("?,?,?") }, + + { nxt_string("'????'.split('')"), + nxt_string("?,?,?,?") }, + + { nxt_string("'?????'.split('?')"), + nxt_string("?,?,?") }, + { nxt_string("'abc'.split('abc')"), nxt_string(",") }, From xeioex at nginx.com Fri Feb 15 15:51:42 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 15 Feb 2019 15:51:42 +0000 Subject: [njs] Adding const qualifiers to njs_string_prototype_split() and friends. Message-ID: details: https://hg.nginx.org/njs/rev/e1bfc7be7c55 branches: changeset: 780:e1bfc7be7c55 user: Dmitry Volyntsev date: Thu Feb 14 21:19:51 2019 +0300 description: Adding const qualifiers to njs_string_prototype_split() and friends. diffstat: njs/njs.h | 2 +- njs/njs_array.c | 2 +- njs/njs_array.h | 4 ++-- njs/njs_regexp.c | 4 ++-- njs/njs_regexp.h | 4 ++-- njs/njs_string.c | 14 +++++++------- njs/njs_string.h | 2 +- nxt/nxt_pcre.c | 6 +++--- nxt/nxt_regex.h | 2 +- 9 files changed, 20 insertions(+), 20 deletions(-) diffs (168 lines): diff -r dde9a253361e -r e1bfc7be7c55 njs/njs.h --- a/njs/njs.h Thu Feb 14 17:01:26 2019 +0300 +++ b/njs/njs.h Thu Feb 14 21:19:51 2019 +0300 @@ -232,7 +232,7 @@ NXT_EXPORT void njs_vm_retval_set(njs_vm NXT_EXPORT u_char * njs_string_alloc(njs_vm_t *vm, njs_value_t *value, uint32_t size, uint32_t length); NXT_EXPORT njs_ret_t njs_string_create(njs_vm_t *vm, njs_value_t *value, - u_char *start, uint32_t size, uint32_t length); + const u_char *start, uint32_t size, uint32_t length); NXT_EXPORT nxt_int_t njs_value_string_copy(njs_vm_t *vm, nxt_str_t *retval, const njs_value_t *value, uintptr_t *next); diff -r dde9a253361e -r e1bfc7be7c55 njs/njs_array.c --- a/njs/njs_array.c Thu Feb 14 17:01:26 2019 +0300 +++ b/njs/njs_array.c Thu Feb 14 21:19:51 2019 +0300 @@ -184,7 +184,7 @@ njs_array_add(njs_vm_t *vm, njs_array_t njs_ret_t -njs_array_string_add(njs_vm_t *vm, njs_array_t *array, u_char *start, +njs_array_string_add(njs_vm_t *vm, njs_array_t *array, const u_char *start, size_t size, size_t length) { njs_ret_t ret; diff -r dde9a253361e -r e1bfc7be7c55 njs/njs_array.h --- a/njs/njs_array.h Thu Feb 14 17:01:26 2019 +0300 +++ b/njs/njs_array.h Thu Feb 14 21:19:51 2019 +0300 @@ -17,8 +17,8 @@ njs_array_t *njs_array_alloc(njs_vm_t *vm, uint32_t length, uint32_t spare); njs_ret_t njs_array_add(njs_vm_t *vm, njs_array_t *array, njs_value_t *value); -njs_ret_t njs_array_string_add(njs_vm_t *vm, njs_array_t *array, u_char *start, - size_t size, size_t length); +njs_ret_t njs_array_string_add(njs_vm_t *vm, njs_array_t *array, + const u_char *start, size_t size, size_t length); njs_ret_t njs_array_expand(njs_vm_t *vm, njs_array_t *array, uint32_t prepend, uint32_t size); njs_ret_t njs_array_constructor(njs_vm_t *vm, njs_value_t *args, diff -r dde9a253361e -r e1bfc7be7c55 njs/njs_regexp.c --- a/njs/njs_regexp.c Thu Feb 14 17:01:26 2019 +0300 +++ b/njs/njs_regexp.c Thu Feb 14 21:19:51 2019 +0300 @@ -389,8 +389,8 @@ njs_regexp_compile_trace_handler(nxt_tra nxt_int_t -njs_regexp_match(njs_vm_t *vm, nxt_regex_t *regex, u_char *subject, size_t len, - nxt_regex_match_data_t *match_data) +njs_regexp_match(njs_vm_t *vm, nxt_regex_t *regex, const u_char *subject, + size_t len, nxt_regex_match_data_t *match_data) { nxt_int_t ret; nxt_trace_handler_t handler; diff -r dde9a253361e -r e1bfc7be7c55 njs/njs_regexp.h --- a/njs/njs_regexp.h Thu Feb 14 17:01:26 2019 +0300 +++ b/njs/njs_regexp.h Thu Feb 14 21:19:51 2019 +0300 @@ -25,8 +25,8 @@ njs_token_t njs_regexp_literal(njs_vm_t njs_value_t *value); njs_regexp_pattern_t *njs_regexp_pattern_create(njs_vm_t *vm, u_char *string, size_t length, njs_regexp_flags_t flags); -nxt_int_t njs_regexp_match(njs_vm_t *vm, nxt_regex_t *regex, u_char *subject, - size_t len, nxt_regex_match_data_t *match_data); +nxt_int_t njs_regexp_match(njs_vm_t *vm, nxt_regex_t *regex, + const u_char *subject, size_t len, nxt_regex_match_data_t *match_data); njs_regexp_t *njs_regexp_alloc(njs_vm_t *vm, njs_regexp_pattern_t *pattern); njs_ret_t njs_regexp_prototype_exec(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); diff -r dde9a253361e -r e1bfc7be7c55 njs/njs_string.c --- a/njs/njs_string.c Thu Feb 14 17:01:26 2019 +0300 +++ b/njs/njs_string.c Thu Feb 14 21:19:51 2019 +0300 @@ -77,7 +77,7 @@ static njs_ret_t njs_string_prototype_pa static njs_ret_t njs_string_match_multiple(njs_vm_t *vm, njs_value_t *args, njs_regexp_pattern_t *pattern); static njs_ret_t njs_string_split_part_add(njs_vm_t *vm, njs_array_t *array, - njs_utf8_t utf8, u_char *start, size_t size); + njs_utf8_t utf8, const u_char *start, size_t size); static njs_ret_t njs_string_replace_regexp(njs_vm_t *vm, njs_value_t *args, njs_string_replace_t *r); static njs_ret_t njs_string_replace_regexp_function(njs_vm_t *vm, @@ -111,10 +111,11 @@ static njs_ret_t njs_string_decode(njs_v njs_ret_t -njs_string_create(njs_vm_t *vm, njs_value_t *value, u_char *start, +njs_string_create(njs_vm_t *vm, njs_value_t *value, const u_char *start, uint32_t size, uint32_t length) { - u_char *dst, *src; + u_char *dst; + const u_char *src; njs_string_t *string; value->type = NJS_STRING; @@ -153,7 +154,7 @@ njs_string_create(njs_vm_t *vm, njs_valu value->long_string.data = string; - string->start = start; + string->start = (u_char *) start; string->length = length; string->retain = 1; } @@ -2729,12 +2730,11 @@ njs_string_prototype_split(njs_vm_t *vm, njs_index_t unused) { int ret, *captures; - u_char *p, *start, *next; size_t size; uint32_t limit; njs_utf8_t utf8; njs_array_t *array; - const u_char *end; + const u_char *p, *start, *next, *end; njs_regexp_utf8_t type; njs_string_prop_t string, split; njs_regexp_pattern_t *pattern; @@ -2887,7 +2887,7 @@ done: static njs_ret_t njs_string_split_part_add(njs_vm_t *vm, njs_array_t *array, njs_utf8_t utf8, - u_char *start, size_t size) + const u_char *start, size_t size) { ssize_t length; diff -r dde9a253361e -r e1bfc7be7c55 njs/njs_string.h --- a/njs/njs_string.h Thu Feb 14 17:01:26 2019 +0300 +++ b/njs/njs_string.h Thu Feb 14 21:19:51 2019 +0300 @@ -100,7 +100,7 @@ typedef enum { nxt_inline uint32_t -njs_string_length(njs_utf8_t utf8, u_char *start, size_t size) +njs_string_length(njs_utf8_t utf8, const u_char *start, size_t size) { ssize_t length; diff -r dde9a253361e -r e1bfc7be7c55 nxt/nxt_pcre.c --- a/nxt/nxt_pcre.c Thu Feb 14 17:01:26 2019 +0300 +++ b/nxt/nxt_pcre.c Thu Feb 14 21:19:51 2019 +0300 @@ -209,13 +209,13 @@ nxt_pcre_default_free(void *p, void *mem nxt_int_t -nxt_regex_match(nxt_regex_t *regex, u_char *subject, size_t len, +nxt_regex_match(nxt_regex_t *regex, const u_char *subject, size_t len, nxt_regex_match_data_t *match_data, nxt_regex_context_t *ctx) { int ret; - ret = pcre_exec(regex->code, regex->extra, (char *) subject, len, 0, 0, - match_data->captures, match_data->ncaptures); + ret = pcre_exec(regex->code, regex->extra, (const char *) subject, len, + 0, 0, match_data->captures, match_data->ncaptures); /* PCRE_ERROR_NOMATCH is -1. */ diff -r dde9a253361e -r e1bfc7be7c55 nxt/nxt_regex.h --- a/nxt/nxt_regex.h Thu Feb 14 17:01:26 2019 +0300 +++ b/nxt/nxt_regex.h Thu Feb 14 21:19:51 2019 +0300 @@ -35,7 +35,7 @@ NXT_EXPORT nxt_regex_match_data_t *nxt_r nxt_regex_context_t *ctx); NXT_EXPORT void nxt_regex_match_data_free(nxt_regex_match_data_t *match_data, nxt_regex_context_t *ctx); -NXT_EXPORT nxt_int_t nxt_regex_match(nxt_regex_t *regex, u_char *subject, +NXT_EXPORT nxt_int_t nxt_regex_match(nxt_regex_t *regex, const u_char *subject, size_t len, nxt_regex_match_data_t *match_data, nxt_regex_context_t *ctx); NXT_EXPORT int *nxt_regex_captures(nxt_regex_match_data_t *match_data); From Maciej.Grochowski at sony.com Mon Feb 18 14:21:25 2019 From: Maciej.Grochowski at sony.com (Maciej.Grochowski at sony.com) Date: Mon, 18 Feb 2019 14:21:25 +0000 Subject: [Module development] Any good idea to hook response from proxy Message-ID: <0B243603C69C594B878E7AED7774F37605659E27@USCULXMSG15.am.sony.com> At very beginning apologizes for the newbie question, but I am very new in Nginx but would like to extend some functionality in the existing module. I am currently using ngx_http_enhanced_memcached_module, and it meets most of my needs. However, currently, I need to manually populate cache, via PUT requests. My nginx configuration looks as follow: ``` upstream memcached_upstream { server 127.0.0.1:11211; keepalive 20; } upstream backendstorage_upstream { server 10.0.0.10:9000 } server { location / { error_page 404 502 504 = @fallback; error_page 405 = 200 $uri; set $enhanced_memcached_key "$request_uri"; ... enhanced_memcached_pass memcached_upstream; } location @fallback { proxy_pass http://backendstorage_upstream; } } ``` I started thinking of embedding STORE functionality inside the module itself. A high-level idea would be: whenever we got cache miss to fetch the response from backend_upstream via `proxy_pass` and then get response and sent it back to the `memcached_upstream` via PUT method. This sounds really simple, however, I have 2 questions based on my understanding of Nginx internals: 1. `proxy_pass` is a method which runs inside NGX_HTTP_CONTENT_PHASE, so based on documentation only one method in that type can be inside the location. In order to hijack response from `proxy_pass`, the only way that I can see is to wrap `proxy_pass` via i.e. `enhanced_memcached_proxy_pass`. In that custom method: first of all original code from proxy module would be run and then as one of the end stages, a custom method like (i.e. input_filter) would be able to access response from the backend and send content to Memcached. Given the size of the proxy module and its implementation based on callbacks, first thoughts that I have is that I can end up easily via merging these modules. Is there any other easier way to access the response from location? 2. If I will need to implement such a method like `enhanced_memcached_proxy_pass`, is there any recommended (asynchronous) way to send PUT to external service. My understanding is that as long as we spent time doing operations inside pipeline we block particular event which can cause delay to the client (of course here I would like to send response first to the client and then store it). Thank you for any help! Maciej -------------- next part -------------- An HTML attachment was scrubbed... URL: From hungnv at opensource.com.vn Mon Feb 18 15:52:11 2019 From: hungnv at opensource.com.vn (Hung Nguyen) Date: Mon, 18 Feb 2019 22:52:11 +0700 Subject: [Module development] Any good idea to hook response from proxy In-Reply-To: <0B243603C69C594B878E7AED7774F37605659E27@USCULXMSG15.am.sony.com> References: <0B243603C69C594B878E7AED7774F37605659E27@USCULXMSG15.am.sony.com> Message-ID: <18AC8FAD-3E1C-45F1-9E86-C3A472051688@opensource.com.vn> As my understanding all you need is doing a body filter on backend_upstream response and send a set request to memcache with value is response itself. To determine whether response is from memcache or from backend, before proxy pass request to backend you can set some customize header like x-update-cache: true, inside the filter you check that header and perform set operation. -- H?ng > On Feb 18, 2019, at 21:21, wrote: > > At very beginning apologizes for the newbie question, but I am very new in Nginx but would like to extend some functionality in the existing module. > > I am currently using ngx_http_enhanced_memcached_module, and it meets most of my needs. > However, currently, I need to manually populate cache, via PUT requests. > > My nginx configuration looks as follow: > > ``` > upstream memcached_upstream { > server 127.0.0.1:11211; > keepalive 20; > } > upstream backendstorage_upstream { > server 10.0.0.10:9000 > } > > server { > location / { > error_page 404 502 504 = @fallback; > error_page 405 = 200 $uri; > > set $enhanced_memcached_key "$request_uri"; > ... > enhanced_memcached_pass memcached_upstream; > } > > location @fallback { > proxy_pass http://backendstorage_upstream; > } > } > ``` > > I started thinking of embedding STORE functionality inside the module itself. A high-level idea would be: > whenever we got cache miss to fetch the response from backend_upstream via `proxy_pass` and then get response and > sent it back to the `memcached_upstream` via PUT method. > > This sounds really simple, however, I have 2 questions based on my understanding of Nginx internals: > > 1. `proxy_pass` is a method which runs inside NGX_HTTP_CONTENT_PHASE, so based on documentation only one method in that type can be inside the location. > In order to hijack response from `proxy_pass`, the only way that I can see is to wrap `proxy_pass` via i.e. `enhanced_memcached_proxy_pass`. > In that custom method: first of all original code from proxy module would be run and then as one of the end stages, a custom method like (i.e. input_filter) would be able to access response from the backend and send content to Memcached. > Given the size of the proxy module and its implementation based on callbacks, first thoughts that I have is that I can end up easily via merging these modules. > Is there any other easier way to access the response from location? > > 2. If I will need to implement such a method like `enhanced_memcached_proxy_pass`, is there any recommended (asynchronous) way to send PUT to external service. > My understanding is that as long as we spent time doing operations inside pipeline we block particular event which can cause delay to the client (of course here I would like to send response first to the client and then store it). > > Thank you for any help! > Maciej > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: From Maciej.Grochowski at sony.com Mon Feb 18 17:01:50 2019 From: Maciej.Grochowski at sony.com (Maciej.Grochowski at sony.com) Date: Mon, 18 Feb 2019 17:01:50 +0000 Subject: [Module development] Any good idea to hook response from proxy In-Reply-To: <18AC8FAD-3E1C-45F1-9E86-C3A472051688@opensource.com.vn> References: <0B243603C69C594B878E7AED7774F37605659E27@USCULXMSG15.am.sony.com> <18AC8FAD-3E1C-45F1-9E86-C3A472051688@opensource.com.vn> Message-ID: <0B243603C69C594B878E7AED7774F3760565A067@USCULXMSG15.am.sony.com> Hi Hung, Thank you for your advice that really sound like much simpler and better solution! From: nginx-devel On Behalf Of Hung Nguyen Sent: Monday, February 18, 2019 3:52 PM To: nginx-devel at nginx.org Subject: Re: [Module development] Any good idea to hook response from proxy As my understanding all you need is doing a body filter on backend_upstream response and send a set request to memcache with value is response itself. To determine whether response is from memcache or from backend, before proxy pass request to backend you can set some customize header like x-update-cache: true, inside the filter you check that header and perform set operation. -- H?ng On Feb 18, 2019, at 21:21, > > wrote: At very beginning apologizes for the newbie question, but I am very new in Nginx but would like to extend some functionality in the existing module. I am currently using ngx_http_enhanced_memcached_module, and it meets most of my needs. However, currently, I need to manually populate cache, via PUT requests. My nginx configuration looks as follow: ``` upstream memcached_upstream { server 127.0.0.1:11211; keepalive 20; } upstream backendstorage_upstream { server 10.0.0.10:9000 } server { location / { error_page 404 502 504 = @fallback; error_page 405 = 200 $uri; set $enhanced_memcached_key "$request_uri"; ... enhanced_memcached_pass memcached_upstream; } location @fallback { proxy_pass http://backendstorage_upstream; } } ``` I started thinking of embedding STORE functionality inside the module itself. A high-level idea would be: whenever we got cache miss to fetch the response from backend_upstream via `proxy_pass` and then get response and sent it back to the `memcached_upstream` via PUT method. This sounds really simple, however, I have 2 questions based on my understanding of Nginx internals: 1. `proxy_pass` is a method which runs inside NGX_HTTP_CONTENT_PHASE, so based on documentation only one method in that type can be inside the location. In order to hijack response from `proxy_pass`, the only way that I can see is to wrap `proxy_pass` via i.e. `enhanced_memcached_proxy_pass`. In that custom method: first of all original code from proxy module would be run and then as one of the end stages, a custom method like (i.e. input_filter) would be able to access response from the backend and send content to Memcached. Given the size of the proxy module and its implementation based on callbacks, first thoughts that I have is that I can end up easily via merging these modules. Is there any other easier way to access the response from location? 2. If I will need to implement such a method like `enhanced_memcached_proxy_pass`, is there any recommended (asynchronous) way to send PUT to external service. My understanding is that as long as we spent time doing operations inside pipeline we block particular event which can cause delay to the client (of course here I would like to send response first to the client and then store it). Thank you for any help! Maciej _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: From xeioex at nginx.com Wed Feb 20 14:26:00 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 20 Feb 2019 14:26:00 +0000 Subject: [njs] Introduced njs_parser_global_scope(). Message-ID: details: https://hg.nginx.org/njs/rev/64278ad1e14c branches: changeset: 783:64278ad1e14c user: hongzhidao date: Sat Feb 16 23:18:43 2019 +0800 description: Introduced njs_parser_global_scope(). diffstat: njs/njs_parser.c | 6 +----- njs/njs_parser.h | 15 +++++++++++++++ njs/njs_variable.c | 8 +++----- 3 files changed, 19 insertions(+), 10 deletions(-) diffs (73 lines): diff -r 8250061df72a -r 64278ad1e14c njs/njs_parser.c --- a/njs/njs_parser.c Wed Feb 20 16:16:30 2019 +0300 +++ b/njs/njs_parser.c Sat Feb 16 23:18:43 2019 +0800 @@ -2178,11 +2178,7 @@ njs_parser_builtin(njs_vm_t *vm, njs_par njs_variable_t *var; njs_parser_scope_t *scope; - scope = parser->scope; - - while (scope->type != NJS_SCOPE_GLOBAL) { - scope = scope->parent; - } + scope = njs_parser_global_scope(vm); var = njs_variable_add(vm, scope, name, hash, NJS_VARIABLE_VAR); if (nxt_slow_path(var == NULL)) { diff -r 8250061df72a -r 64278ad1e14c njs/njs_parser.h --- a/njs/njs_parser.h Wed Feb 20 16:16:30 2019 +0300 +++ b/njs/njs_parser.h Sat Feb 16 23:18:43 2019 +0800 @@ -360,6 +360,21 @@ njs_parser_node_new(njs_vm_t *vm, njs_pa } +nxt_inline njs_parser_scope_t * +njs_parser_global_scope(njs_vm_t *vm) +{ + njs_parser_scope_t *scope; + + scope = vm->parser->scope; + + while (scope->type != NJS_SCOPE_GLOBAL) { + scope = scope->parent; + } + + return scope; +} + + extern const nxt_lvlhsh_proto_t njs_keyword_hash_proto; diff -r 8250061df72a -r 64278ad1e14c njs/njs_variable.c --- a/njs/njs_variable.c Wed Feb 20 16:16:30 2019 +0300 +++ b/njs/njs_variable.c Sat Feb 16 23:18:43 2019 +0800 @@ -356,7 +356,7 @@ njs_variable_reference_resolve(njs_vm_t njs_parser_scope_t *node_scope) { nxt_lvlhsh_query_t lhq; - njs_parser_scope_t *scope, *parent, *previous; + njs_parser_scope_t *scope, *previous; lhq.key_hash = vr->hash; lhq.key = vr->name; @@ -395,9 +395,7 @@ njs_variable_reference_resolve(njs_vm_t return NXT_OK; } - parent = scope->parent; - - if (parent == NULL) { + if (scope->parent == NULL) { /* A global scope. */ vr->scope = scope; @@ -405,7 +403,7 @@ njs_variable_reference_resolve(njs_vm_t } previous = scope; - scope = parent; + scope = scope->parent; } } From xeioex at nginx.com Wed Feb 20 14:26:00 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 20 Feb 2019 14:26:00 +0000 Subject: [njs] Introduced nxt_file_basename() and nxt_file_dirname(). Message-ID: details: https://hg.nginx.org/njs/rev/8250061df72a branches: changeset: 782:8250061df72a user: Dmitry Volyntsev date: Wed Feb 20 16:16:30 2019 +0300 description: Introduced nxt_file_basename() and nxt_file_dirname(). diffstat: njs/njs_shell.c | 4 +- njs/test/njs_unit_test.c | 100 +++++++++++++++++++++++++++++++++++++++++++++- nxt/nxt_file.c | 59 ++++++++++++++++++++++----- nxt/nxt_file.h | 3 +- 4 files changed, 150 insertions(+), 16 deletions(-) diffs (217 lines): diff -r 8c422e42448e -r 8250061df72a njs/njs_shell.c --- a/njs/njs_shell.c Thu Feb 14 21:19:51 2019 +0300 +++ b/njs/njs_shell.c Wed Feb 20 16:16:30 2019 +0300 @@ -216,7 +216,9 @@ main(int argc, char **argv) if (!opts.quiet) { if (opts.file != NULL) { - nxt_file_name(&vm_options.file, opts.file); + vm_options.file.start = (u_char *) opts.file; + vm_options.file.length = strlen(opts.file); + nxt_file_basename(&vm_options.file, &vm_options.file); } else { vm_options.file = nxt_string_value("shell"); diff -r 8c422e42448e -r 8250061df72a njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Thu Feb 14 21:19:51 2019 +0300 +++ b/njs/test/njs_unit_test.c Wed Feb 20 16:16:30 2019 +0300 @@ -11994,6 +11994,97 @@ njs_vm_object_alloc_test(njs_vm_t * vm, } +static nxt_int_t +nxt_file_basename_test(njs_vm_t * vm, nxt_bool_t disassemble, + nxt_bool_t verbose) +{ + nxt_str_t name; + nxt_bool_t success; + nxt_uint_t i; + + static const struct { + nxt_str_t path; + nxt_str_t expected; + } tests[] = { + { nxt_string(""), nxt_string("") }, + { nxt_string("/"), nxt_string("") }, + { nxt_string("/a"), nxt_string("a") }, + { nxt_string("///"), nxt_string("") }, + { nxt_string("///a"), nxt_string("a") }, + { nxt_string("///a/"), nxt_string("") }, + { nxt_string("a"), nxt_string("a") }, + { nxt_string("a/"), nxt_string("") }, + { nxt_string("a//"), nxt_string("") }, + { nxt_string("path/name"), nxt_string("name") }, + { nxt_string("/path/name"), nxt_string("name") }, + { nxt_string("/path/name/"), nxt_string("") }, + }; + + for (i = 0; i < nxt_nitems(tests); i++) { + nxt_file_basename(&tests[i].path, &name); + + success = nxt_strstr_eq(&tests[i].expected, &name); + + if (!success) { + printf("nxt_file_basename_test(\"%.*s\"):\n" + "expected: \"%.*s\"\n got: \"%.*s\"\n", + (int) tests[i].path.length, tests[i].path.start, + (int) tests[i].expected.length, tests[i].expected.start, + (int) name.length, name.start); + return NXT_ERROR; + } + } + + return NXT_OK; +} + + +static nxt_int_t +nxt_file_dirname_test(njs_vm_t * vm, nxt_bool_t disassemble, + nxt_bool_t verbose) +{ + nxt_str_t name; + nxt_bool_t success; + nxt_uint_t i; + + static const struct { + nxt_str_t path; + nxt_str_t expected; + } tests[] = { + { nxt_string(""), nxt_string("") }, + { nxt_string("/"), nxt_string("/") }, + { nxt_string("/a"), nxt_string("/") }, + { nxt_string("///"), nxt_string("///") }, + { nxt_string("///a"), nxt_string("///") }, + { nxt_string("///a/"), nxt_string("///a") }, + { nxt_string("a"), nxt_string("") }, + { nxt_string("a/"), nxt_string("a") }, + { nxt_string("a//"), nxt_string("a") }, + { nxt_string("p1/p2/name"), nxt_string("p1/p2") }, + { nxt_string("/p1/p2/name"), nxt_string("/p1/p2") }, + { nxt_string("/p1/p2///name"), nxt_string("/p1/p2") }, + { nxt_string("/p1/p2/name/"), nxt_string("/p1/p2/name") }, + }; + + for (i = 0; i < nxt_nitems(tests); i++) { + nxt_file_dirname(&tests[i].path, &name); + + success = nxt_strstr_eq(&tests[i].expected, &name); + + if (!success) { + printf("nxt_file_dirname_test(\"%.*s\"):\n" + "expected: \"%.*s\"\n got: \"%.*s\"\n", + (int) tests[i].path.length, tests[i].path.start, + (int) tests[i].expected.length, tests[i].expected.start, + (int) name.length, name.start); + return NXT_ERROR; + } + } + + return NXT_OK; +} + + typedef struct { nxt_int_t (*test)(njs_vm_t *, nxt_bool_t, nxt_bool_t); nxt_str_t name; @@ -12009,10 +12100,13 @@ njs_api_test(nxt_bool_t disassemble, nxt njs_vm_opt_t options; njs_api_test_t *test; - static njs_api_test_t njs_api_test[] = - { + static njs_api_test_t njs_api_test[] = { { njs_vm_object_alloc_test, - nxt_string("njs_vm_object_alloc_test") } + nxt_string("njs_vm_object_alloc_test") }, + { nxt_file_basename_test, + nxt_string("nxt_file_basename_test") }, + { nxt_file_dirname_test, + nxt_string("nxt_file_dirname_test") }, }; rc = NXT_ERROR; diff -r 8c422e42448e -r 8250061df72a nxt/nxt_file.c --- a/nxt/nxt_file.c Thu Feb 14 21:19:51 2019 +0300 +++ b/nxt/nxt_file.c Wed Feb 20 16:16:30 2019 +0300 @@ -14,20 +14,57 @@ void -nxt_file_name(nxt_str_t *name, char *path) +nxt_file_basename(const nxt_str_t *path, nxt_str_t *name) { - char *p; - size_t length; + const u_char *p, *end; + + end = path->start + path->length; + p = end - 1; + + /* Stripping dir prefix. */ + + while (p >= path->start && *p != '/') { p--; } + + p++; - length = strlen(path); + name->start = (u_char *) p; + name->length = end - p; +} + - for (p = path + length; p >= path; p--) { - if (*p == '/') { - p++; - break; - } +void +nxt_file_dirname(const nxt_str_t *path, nxt_str_t *name) +{ + const u_char *p, *end; + + if (path->length == 0) { + *name = nxt_string_value(""); + return; } - name->start = (u_char *) p; - name->length = length - (p - path); + p = path->start + path->length - 1; + + /* Stripping basename. */ + + while (p >= path->start && *p != '/') { p--; } + + end = p + 1; + + if (end == path->start) { + *name = nxt_string_value(""); + return; + } + + /* Stripping trailing slashes. */ + + while (p >= path->start && *p == '/') { p--; } + + p++; + + if (p == path->start) { + p = end; + } + + name->start = path->start; + name->length = p - path->start; } diff -r 8c422e42448e -r 8250061df72a nxt/nxt_file.h --- a/nxt/nxt_file.h Thu Feb 14 21:19:51 2019 +0300 +++ b/nxt/nxt_file.h Wed Feb 20 16:16:30 2019 +0300 @@ -8,7 +8,8 @@ #define _NXT_FILE_H_INCLUDED_ -void nxt_file_name(nxt_str_t *name, char *path); +void nxt_file_basename(const nxt_str_t *path, nxt_str_t *name); +void nxt_file_dirname(const nxt_str_t *path, nxt_str_t *name); #endif /* _NXT_FILE_H_INCLUDED_ */ From xeioex at nginx.com Wed Feb 20 14:26:01 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 20 Feb 2019 14:26:01 +0000 Subject: [njs] Making njs_vm_invoke() public. Message-ID: details: https://hg.nginx.org/njs/rev/b23c0a90e37f branches: changeset: 784:b23c0a90e37f user: hongzhidao date: Sat Feb 16 23:18:43 2019 +0800 description: Making njs_vm_invoke() public. diffstat: njs/njs.c | 6 ++---- njs/njs.h | 2 ++ 2 files changed, 4 insertions(+), 4 deletions(-) diffs (38 lines): diff -r 64278ad1e14c -r b23c0a90e37f njs/njs.c --- a/njs/njs.c Sat Feb 16 23:18:43 2019 +0800 +++ b/njs/njs.c Sat Feb 16 23:18:43 2019 +0800 @@ -10,8 +10,6 @@ static nxt_int_t njs_vm_init(njs_vm_t *vm); -static nxt_int_t njs_vm_invoke(njs_vm_t *vm, njs_function_t *function, - const njs_value_t *args, nxt_uint_t nargs, njs_index_t retval); static nxt_int_t njs_vm_handle_events(njs_vm_t *vm); @@ -458,11 +456,11 @@ nxt_int_t njs_vm_call(njs_vm_t *vm, njs_function_t *function, const njs_value_t *args, nxt_uint_t nargs) { - return njs_vm_invoke(vm, function, args, nargs, NJS_INDEX_GLOBAL_RETVAL); + return njs_vm_invoke(vm, function, args, nargs, NJS_INDEX_GLOBAL_RETVAL); } -static nxt_int_t +nxt_int_t njs_vm_invoke(njs_vm_t *vm, njs_function_t *function, const njs_value_t *args, nxt_uint_t nargs, njs_index_t retval) { diff -r 64278ad1e14c -r b23c0a90e37f njs/njs.h --- a/njs/njs.h Sat Feb 16 23:18:43 2019 +0800 +++ b/njs/njs.h Sat Feb 16 23:18:43 2019 +0800 @@ -193,6 +193,8 @@ NXT_EXPORT nxt_int_t njs_vm_posted(njs_v */ NXT_EXPORT nxt_int_t njs_vm_call(njs_vm_t *vm, njs_function_t *function, const njs_value_t *args, nxt_uint_t nargs); +NXT_EXPORT nxt_int_t njs_vm_invoke(njs_vm_t *vm, njs_function_t *function, + const njs_value_t *args, nxt_uint_t nargs, njs_index_t retval); /* * Runs posted events. From xeioex at nginx.com Wed Feb 20 14:26:01 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 20 Feb 2019 14:26:01 +0000 Subject: [njs] Allocating njs_generator_t on stack. Message-ID: details: https://hg.nginx.org/njs/rev/68e7119e97fe branches: changeset: 785:68e7119e97fe user: hongzhidao date: Sat Feb 16 23:18:43 2019 +0800 description: Allocating njs_generator_t on stack. diffstat: njs/njs.c | 30 +++++++++++------------------- njs/njs_generator.c | 27 +++++++++------------------ 2 files changed, 20 insertions(+), 37 deletions(-) diffs (109 lines): diff -r b23c0a90e37f -r 68e7119e97fe njs/njs.c --- a/njs/njs.c Sat Feb 16 23:18:43 2019 +0800 +++ b/njs/njs.c Sat Feb 16 23:18:43 2019 +0800 @@ -216,20 +216,20 @@ njs_vm_destroy(njs_vm_t *vm) nxt_int_t njs_vm_compile(njs_vm_t *vm, u_char **start, u_char *end) { - nxt_int_t ret; + nxt_int_t ret; njs_lexer_t *lexer; njs_parser_t *parser, *prev; - njs_generator_t *generator; + njs_generator_t generator; + + if (vm->parser != NULL && !vm->options.accumulative) { + return NJS_ERROR; + } parser = nxt_mp_zalloc(vm->mem_pool, sizeof(njs_parser_t)); if (nxt_slow_path(parser == NULL)) { return NJS_ERROR; } - if (vm->parser != NULL && !vm->options.accumulative) { - return NJS_ERROR; - } - prev = vm->parser; vm->parser = parser; @@ -269,24 +269,16 @@ njs_vm_compile(njs_vm_t *vm, u_char **st */ vm->code = NULL; - generator = nxt_mp_align(vm->mem_pool, sizeof(njs_value_t), - sizeof(njs_generator_t)); + nxt_memzero(&generator, sizeof(njs_generator_t)); - if (nxt_slow_path(generator == NULL)) { - goto fail; - } - - nxt_memzero(generator, sizeof(njs_generator_t)); - - ret = njs_generate_scope(vm, generator, parser->scope); + ret = njs_generate_scope(vm, &generator, parser->scope); if (nxt_slow_path(ret != NXT_OK)) { goto fail; } - vm->current = generator->code_start; - - vm->global_scope = generator->local_scope; - vm->scope_size = generator->scope_size; + vm->current = generator.code_start; + vm->global_scope = generator.local_scope; + vm->scope_size = generator.scope_size; vm->variables_hash = parser->scope->variables; diff -r b23c0a90e37f -r 68e7119e97fe njs/njs_generator.c --- a/njs/njs_generator.c Sat Feb 16 23:18:43 2019 +0800 +++ b/njs/njs_generator.c Sat Feb 16 23:18:43 2019 +0800 @@ -2282,19 +2282,13 @@ njs_generate_function_scope(njs_vm_t *vm size_t size; nxt_int_t ret; nxt_array_t *closure; - njs_generator_t *generator; - - generator = nxt_mp_align(vm->mem_pool, sizeof(njs_value_t), - sizeof(njs_generator_t)); - if (nxt_slow_path(generator == NULL)) { - return NXT_ERROR; - } - - nxt_memzero(generator, sizeof(njs_generator_t)); + njs_generator_t generator; node = node->right; - ret = njs_generate_scope(vm, generator, node->scope); + nxt_memzero(&generator, sizeof(njs_generator_t)); + + ret = njs_generate_scope(vm, &generator, node->scope); if (nxt_fast_path(ret == NXT_OK)) { size = 0; @@ -2309,16 +2303,13 @@ njs_generate_function_scope(njs_vm_t *vm lambda->closure_size = size; lambda->nesting = node->scope->nesting; - lambda->arguments_object = generator->arguments_object; - - lambda->local_size = generator->scope_size; - lambda->local_scope = generator->local_scope; - - lambda->start = generator->code_start; + lambda->arguments_object = generator.arguments_object; + + lambda->start = generator.code_start; + lambda->local_size = generator.scope_size; + lambda->local_scope = generator.local_scope; } - nxt_mp_free(vm->mem_pool, generator); - return ret; } From xeioex at nginx.com Wed Feb 20 14:26:01 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 20 Feb 2019 14:26:01 +0000 Subject: [njs] Allocating njs_lexer_t on stack. Message-ID: details: https://hg.nginx.org/njs/rev/2101597aa18d branches: changeset: 786:2101597aa18d user: hongzhidao date: Sat Feb 16 23:18:43 2019 +0800 description: Allocating njs_lexer_t on stack. diffstat: njs/njs.c | 22 ++++++++++------------ 1 files changed, 10 insertions(+), 12 deletions(-) diffs (47 lines): diff -r 68e7119e97fe -r 2101597aa18d njs/njs.c --- a/njs/njs.c Sat Feb 16 23:18:43 2019 +0800 +++ b/njs/njs.c Sat Feb 16 23:18:43 2019 +0800 @@ -217,7 +217,7 @@ nxt_int_t njs_vm_compile(njs_vm_t *vm, u_char **start, u_char *end) { nxt_int_t ret; - njs_lexer_t *lexer; + njs_lexer_t lexer; njs_parser_t *parser, *prev; njs_generator_t generator; @@ -233,17 +233,15 @@ njs_vm_compile(njs_vm_t *vm, u_char **st prev = vm->parser; vm->parser = parser; - lexer = nxt_mp_zalloc(vm->mem_pool, sizeof(njs_lexer_t)); - if (nxt_slow_path(lexer == NULL)) { - return NJS_ERROR; - } + nxt_memzero(&lexer, sizeof(njs_lexer_t)); - parser->lexer = lexer; - lexer->start = *start; - lexer->end = end; - lexer->line = 1; - lexer->file = vm->options.file; - lexer->keywords_hash = vm->shared->keywords_hash; + lexer.start = *start; + lexer.end = end; + lexer.line = 1; + lexer.file = vm->options.file; + lexer.keywords_hash = vm->shared->keywords_hash; + + parser->lexer = &lexer; if (vm->backtrace != NULL) { nxt_array_reset(vm->backtrace); @@ -261,7 +259,7 @@ njs_vm_compile(njs_vm_t *vm, u_char **st goto fail; } - *start = parser->lexer->start; + *start = lexer.start; /* * Reset the code array to prevent it from being disassembled From xeioex at nginx.com Wed Feb 20 14:26:02 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 20 Feb 2019 14:26:02 +0000 Subject: [njs] Improved njs_vm_compile(). Message-ID: details: https://hg.nginx.org/njs/rev/5db48d70db65 branches: changeset: 787:5db48d70db65 user: hongzhidao date: Sat Feb 16 23:18:43 2019 +0800 description: Improved njs_vm_compile(). diffstat: njs/njs.c | 17 ++++++++++------- 1 files changed, 10 insertions(+), 7 deletions(-) diffs (48 lines): diff -r 2101597aa18d -r 5db48d70db65 njs/njs.c --- a/njs/njs.c Sat Feb 16 23:18:43 2019 +0800 +++ b/njs/njs.c Sat Feb 16 23:18:43 2019 +0800 @@ -216,10 +216,11 @@ njs_vm_destroy(njs_vm_t *vm) nxt_int_t njs_vm_compile(njs_vm_t *vm, u_char **start, u_char *end) { - nxt_int_t ret; - njs_lexer_t lexer; - njs_parser_t *parser, *prev; - njs_generator_t generator; + nxt_int_t ret; + njs_lexer_t lexer; + njs_parser_t *parser, *prev; + njs_generator_t generator; + njs_parser_scope_t *scope; if (vm->parser != NULL && !vm->options.accumulative) { return NJS_ERROR; @@ -254,7 +255,9 @@ njs_vm_compile(njs_vm_t *vm, u_char **st goto fail; } - ret = njs_variables_scope_reference(vm, parser->scope); + scope = parser->scope; + + ret = njs_variables_scope_reference(vm, scope); if (nxt_slow_path(ret != NXT_OK)) { goto fail; } @@ -269,7 +272,7 @@ njs_vm_compile(njs_vm_t *vm, u_char **st nxt_memzero(&generator, sizeof(njs_generator_t)); - ret = njs_generate_scope(vm, &generator, parser->scope); + ret = njs_generate_scope(vm, &generator, scope); if (nxt_slow_path(ret != NXT_OK)) { goto fail; } @@ -278,7 +281,7 @@ njs_vm_compile(njs_vm_t *vm, u_char **st vm->global_scope = generator.local_scope; vm->scope_size = generator.scope_size; - vm->variables_hash = parser->scope->variables; + vm->variables_hash = scope->variables; if (vm->options.init) { ret = njs_vm_init(vm); From xeioex at nginx.com Wed Feb 20 14:26:02 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 20 Feb 2019 14:26:02 +0000 Subject: [njs] Fixed fast paths. Message-ID: details: https://hg.nginx.org/njs/rev/82794813ce4c branches: changeset: 788:82794813ce4c user: hongzhidao date: Sat Feb 16 23:18:43 2019 +0800 description: Fixed fast paths. diffstat: njs/njs_variable.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (21 lines): diff -r 5db48d70db65 -r 82794813ce4c njs/njs_variable.c --- a/njs/njs_variable.c Sat Feb 16 23:18:43 2019 +0800 +++ b/njs/njs_variable.c Sat Feb 16 23:18:43 2019 +0800 @@ -144,7 +144,7 @@ njs_variable_reference(njs_vm_t *vm, njs ret = nxt_lvlhsh_insert(&scope->references, &lhq); - if (nxt_slow_path(ret != NXT_ERROR)) { + if (nxt_fast_path(ret != NXT_ERROR)) { ret = NXT_OK; } } @@ -493,7 +493,7 @@ njs_name_copy(njs_vm_t *vm, nxt_str_t *d dst->start = nxt_mp_alloc(vm->mem_pool, src->length); - if (nxt_slow_path(dst->start != NULL)) { + if (nxt_fast_path(dst->start != NULL)) { (void) memcpy(dst->start, src->start, src->length); return NXT_OK; From xeioex at nginx.com Wed Feb 20 18:05:16 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 20 Feb 2019 18:05:16 +0000 Subject: [njs] Fixed %*s length argument type in nxt_sprintf() fmt string. Message-ID: details: https://hg.nginx.org/njs/rev/5764fb29b4c0 branches: changeset: 790:5764fb29b4c0 user: Dmitry Volyntsev date: Wed Feb 20 21:04:19 2019 +0300 description: Fixed %*s length argument type in nxt_sprintf() fmt string. diffstat: njs/njs_regexp.c | 4 ++-- njs/njs_shell.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diffs (29 lines): diff -r 46144bf0a378 -r 5764fb29b4c0 njs/njs_regexp.c --- a/njs/njs_regexp.c Wed Feb 20 18:25:01 2019 +0300 +++ b/njs/njs_regexp.c Wed Feb 20 21:04:19 2019 +0300 @@ -377,11 +377,11 @@ njs_regexp_compile_trace_handler(nxt_tra p = trace->handler(trace, td, start); if (vm->parser != NULL) { - njs_syntax_error(vm, "%*s in %uD", (int) (p - start), start, + njs_syntax_error(vm, "%*s in %uD", p - start, start, vm->parser->lexer->line); } else { - njs_syntax_error(vm, "%*s", (int) (p - start), start); + njs_syntax_error(vm, "%*s", p - start, start); } return p; diff -r 46144bf0a378 -r 5764fb29b4c0 njs/njs_shell.c --- a/njs/njs_shell.c Wed Feb 20 18:25:01 2019 +0300 +++ b/njs/njs_shell.c Wed Feb 20 21:04:19 2019 +0300 @@ -784,7 +784,7 @@ next: } nxt_sprintf((u_char *) completion, (u_char *) completion + len, - "%*s%V%Z", (int) (p - text), text, suffix); + "%*s%V%Z", p - text, text, suffix); return completion; } From xeioex at nginx.com Wed Feb 20 18:05:16 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 20 Feb 2019 18:05:16 +0000 Subject: [njs] Fixed creation of long UTF8 strings. Message-ID: details: https://hg.nginx.org/njs/rev/46144bf0a378 branches: changeset: 789:46144bf0a378 user: Dmitry Volyntsev date: Wed Feb 20 18:25:01 2019 +0300 description: Fixed creation of long UTF8 strings. This closes #98 issue on Github. diffstat: njs/njs_array.c | 4 ++-- njs/njs_extern.c | 4 ++-- njs/njs_json.c | 35 +++++++++++++++++++++++++++-------- njs/njs_regexp.c | 2 +- njs/njs_string.c | 18 +++++------------- njs/test/njs_unit_test.c | 19 +++++++++++++++++-- 6 files changed, 54 insertions(+), 28 deletions(-) diffs (235 lines): diff -r 82794813ce4c -r 46144bf0a378 njs/njs_array.c --- a/njs/njs_array.c Sat Feb 16 23:18:43 2019 +0800 +++ b/njs/njs_array.c Wed Feb 20 18:25:01 2019 +0300 @@ -192,8 +192,8 @@ njs_array_string_add(njs_vm_t *vm, njs_a ret = njs_array_expand(vm, array, 0, 1); if (nxt_fast_path(ret == NXT_OK)) { - return njs_string_create(vm, &array->start[array->length++], - start, size, length); + return njs_string_new(vm, &array->start[array->length++], start, size, + length); } return ret; diff -r 82794813ce4c -r 46144bf0a378 njs/njs_extern.c --- a/njs/njs_extern.c Sat Feb 16 23:18:43 2019 +0800 +++ b/njs/njs_extern.c Wed Feb 20 18:25:01 2019 +0300 @@ -291,8 +291,8 @@ njs_extern_keys_array(njs_vm_t *vm, cons break; } - ret = njs_string_create(vm, &keys->start[n++], ext->name.start, - ext->name.length, 0); + ret = njs_string_new(vm, &keys->start[n++], ext->name.start, + ext->name.length, 0); if (ret != NXT_OK) { return NULL; diff -r 82794813ce4c -r 46144bf0a378 njs/njs_json.c --- a/njs/njs_json.c Sat Feb 16 23:18:43 2019 +0800 +++ b/njs/njs_json.c Wed Feb 20 18:25:01 2019 +0300 @@ -628,6 +628,7 @@ njs_json_parse_string(njs_json_parse_ctx start = p + 1; + dst = NULL; state = 0; surplus = 0; @@ -807,11 +808,15 @@ njs_json_parse_string(njs_json_parse_ctx length = 0; } - ret = njs_string_create(ctx->vm, value, (u_char *) start, size, length); + ret = njs_string_new(ctx->vm, value, (u_char *) start, size, length); if (nxt_slow_path(ret != NXT_OK)) { return NULL; } + if (dst != NULL) { + nxt_mp_free(ctx->pool, dst); + } + return last + 1; } @@ -1188,6 +1193,8 @@ static njs_ret_t njs_json_stringify_continuation(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) { + u_char *start; + size_t size; ssize_t length; nxt_int_t i; njs_ret_t ret; @@ -1406,25 +1413,37 @@ done: */ if (str.length <= nxt_length("{\n\n}")) { vm->retval = njs_value_void; - return NXT_OK; + goto release; } /* Stripping the wrapper's data. */ - str.start += nxt_length("{\"\":"); - str.length -= nxt_length("{\"\":}"); + start = str.start; + size = str.length; + + start += nxt_length("{\"\":"); + size -= nxt_length("{\"\":}"); if (stringify->space.length != 0) { - str.start += nxt_length("\n "); - str.length -= nxt_length("\n \n"); + start += nxt_length("\n "); + size -= nxt_length("\n \n"); } - length = nxt_utf8_length(str.start, str.length); + length = nxt_utf8_length(start, size); if (nxt_slow_path(length < 0)) { length = 0; } - return njs_string_create(vm, &vm->retval, str.start, str.length, length); + ret = njs_string_new(vm, &vm->retval, start, size, length); + if (nxt_slow_path(ret != NXT_OK)) { + goto memory_error; + } + +release: + + nxt_mp_free(vm->mem_pool, str.start); + + return NXT_OK; memory_error: diff -r 82794813ce4c -r 46144bf0a378 njs/njs_regexp.c --- a/njs/njs_regexp.c Sat Feb 16 23:18:43 2019 +0800 +++ b/njs/njs_regexp.c Wed Feb 20 18:25:01 2019 +0300 @@ -798,7 +798,7 @@ njs_regexp_string_create(njs_vm_t *vm, n { length = (length >= 0) ? length : 0; - return njs_string_create(vm, value, start, size, length); + return njs_string_new(vm, value, start, size, length); } diff -r 82794813ce4c -r 46144bf0a378 njs/njs_string.c --- a/njs/njs_string.c Sat Feb 16 23:18:43 2019 +0800 +++ b/njs/njs_string.c Wed Feb 20 18:25:01 2019 +0300 @@ -907,14 +907,6 @@ njs_string_prototype_from_utf8(njs_vm_t length = nxt_utf8_length(string.start, slice.length); if (length >= 0) { - - if (length < NJS_STRING_MAP_STRIDE || (size_t) length == slice.length) { - /* ASCII or short UTF-8 string. */ - return njs_string_create(vm, &vm->retval, string.start, - slice.length, length); - } - - /* Long UTF-8 string. */ return njs_string_new(vm, &vm->retval, string.start, slice.length, length); } @@ -2699,8 +2691,8 @@ njs_string_match_multiple(njs_vm_t *vm, length = njs_string_length(utf8, start, size); - ret = njs_string_create(vm, &array->start[array->length], - start, size, length); + ret = njs_string_new(vm, &array->start[array->length], + start, size, length); if (nxt_slow_path(ret != NXT_OK)) { return ret; } @@ -3136,7 +3128,7 @@ njs_string_replace_regexp_function(njs_v length = njs_string_length(r->utf8, start, size); - ret = njs_string_create(vm, &arguments[i], start, size, length); + ret = njs_string_new(vm, &arguments[i], start, size, length); if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; } @@ -3148,8 +3140,8 @@ njs_string_replace_regexp_function(njs_v /* The whole string being examined. */ length = njs_string_length(r->utf8, r->part[0].start, r->part[0].size); - ret = njs_string_create(vm, &arguments[n + 2], r->part[0].start, - r->part[0].size, length); + ret = njs_string_new(vm, &arguments[n + 2], r->part[0].start, + r->part[0].size, length); if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; diff -r 82794813ce4c -r 46144bf0a378 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Sat Feb 16 23:18:43 2019 +0800 +++ b/njs/test/njs_unit_test.c Wed Feb 20 18:25:01 2019 +0300 @@ -4993,6 +4993,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("'$1,$2'.replace(/(\\$(\\d))/g, '$$1-$1$2')"), nxt_string("$1-$11,$1-$22") }, + { nxt_string("('?' + '?'.repeat(33)+'?').replace(/(?+)(?+)/, function(m, p1) { return p1[32]; })"), + nxt_string("??") }, + { nxt_string("'abcdefgh'.match()"), nxt_string("") }, @@ -5062,6 +5065,9 @@ static njs_unit_test_t njs_test[] = "a +' '+ a.length"), nxt_string("?? 2") }, + { nxt_string("('?' + '?'.repeat(33) +'?').match(/?+/g)[0][32]"), + nxt_string("?") }, + { nxt_string("var a = '\\u00CE\\u00B1'.toBytes().match(/?/g)[0] + '?';" "a +' '+ a.length"), nxt_string("?? 4") }, @@ -5090,6 +5096,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("'?????'.split('?')"), nxt_string("?,?,?") }, + { nxt_string("('?'+'?'.repeat(33)).repeat(2).split('?')[1][32]"), + nxt_string("?") }, + { nxt_string("'abc'.split('abc')"), nxt_string(",") }, @@ -6364,6 +6373,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("var r = new RegExp('abc', 'i'); r.test('00ABC11')"), nxt_string("true") }, + { nxt_string("RegExp('?'.repeat(33)).toString()[32]"), + nxt_string("?") }, + { nxt_string("new RegExp('', 'x')"), nxt_string("SyntaxError: Invalid RegExp flags \"x\"") }, @@ -10154,8 +10166,8 @@ static njs_unit_test_t njs_test[] = { nxt_string("JSON.parse('\"?????????????\"').length"), nxt_string("13") }, - { nxt_string("JSON.parse('\"?????????????\"').length"), - nxt_string("13") }, + { nxt_string("JSON.parse('[\"' + '?'.repeat(33) + '\"]')[0][32]"), + nxt_string("?") }, { nxt_string("JSON.parse('\"\\\\u03B1\"')"), nxt_string("?") }, @@ -10509,6 +10521,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("JSON.stringify('??z'.repeat(10)).length"), nxt_string("32") }, + { nxt_string("JSON.stringify('?'.repeat(33))[32]"), + nxt_string("?") }, + { nxt_string("JSON.stringify('a\\nbc')"), nxt_string("\"a\\nbc\"") }, From xeioex at nginx.com Wed Feb 20 18:05:17 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 20 Feb 2019 18:05:17 +0000 Subject: [njs] Style. Message-ID: details: https://hg.nginx.org/njs/rev/7bb252625b94 branches: changeset: 791:7bb252625b94 user: Dmitry Volyntsev date: Wed Feb 20 21:04:22 2019 +0300 description: Style. diffstat: njs/njs_error.c | 2 +- njs/njs_error.h | 2 +- njs/njs_json.c | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diffs (63 lines): diff -r 5764fb29b4c0 -r 7bb252625b94 njs/njs_error.c --- a/njs/njs_error.c Wed Feb 20 21:04:19 2019 +0300 +++ b/njs/njs_error.c Wed Feb 20 21:04:22 2019 +0300 @@ -39,7 +39,7 @@ njs_error_new(njs_vm_t *vm, njs_value_t void njs_error_fmt_new(njs_vm_t *vm, njs_value_t *dst, njs_value_type_t type, - const char* fmt, ...) + const char *fmt, ...) { va_list args; u_char buf[NXT_MAX_ERROR_STR], *p; diff -r 5764fb29b4c0 -r 7bb252625b94 njs/njs_error.h --- a/njs/njs_error.h Wed Feb 20 21:04:19 2019 +0300 +++ b/njs/njs_error.h Wed Feb 20 21:04:22 2019 +0300 @@ -35,7 +35,7 @@ void njs_error_new(njs_vm_t *vm, njs_value_t *dst, njs_value_type_t type, u_char *start, size_t size); void njs_error_fmt_new(njs_vm_t *vm, njs_value_t *dst, njs_value_type_t type, - const char* fmt, ...); + const char *fmt, ...); void njs_memory_error(njs_vm_t *vm); void njs_memory_error_set(njs_vm_t *vm, njs_value_t *value); diff -r 5764fb29b4c0 -r 7bb252625b94 njs/njs_json.c --- a/njs/njs_json.c Wed Feb 20 21:04:19 2019 +0300 +++ b/njs/njs_json.c Wed Feb 20 21:04:22 2019 +0300 @@ -115,7 +115,7 @@ static njs_json_state_t *njs_json_push_p njs_json_parse_t *parse, njs_value_t *value); static njs_json_state_t *njs_json_pop_parse_state(njs_json_parse_t *parse); static void njs_json_parse_exception(njs_json_parse_ctx_t *ctx, - const char* msg, const u_char *pos); + const char *msg, const u_char *pos); static njs_ret_t njs_json_stringify_continuation(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); @@ -152,7 +152,7 @@ static njs_value_t *njs_json_wrap_value( #define njs_json_buf_node_room(n) (size_t) ((n)->end - (n)->pos) static nxt_int_t njs_json_buf_append(njs_json_stringify_t *stringify, - const char* msg, size_t len); + const char *msg, size_t len); static u_char *njs_json_buf_reserve(njs_json_stringify_t *stringify, size_t size); static nxt_int_t njs_json_buf_pullup(njs_json_stringify_t *stringify, @@ -1126,7 +1126,7 @@ njs_json_pop_parse_state(njs_json_parse_ static void -njs_json_parse_exception(njs_json_parse_ctx_t *ctx, const char* msg, +njs_json_parse_exception(njs_json_parse_ctx_t *ctx, const char *msg, const u_char *pos) { ssize_t length; @@ -1927,7 +1927,7 @@ njs_json_wrap_value(njs_vm_t *vm, njs_va static nxt_int_t -njs_json_buf_append(njs_json_stringify_t *stringify, const char* msg, +njs_json_buf_append(njs_json_stringify_t *stringify, const char *msg, size_t len) { u_char *p; From xeioex at nginx.com Wed Feb 20 18:18:36 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 20 Feb 2019 18:18:36 +0000 Subject: [njs] Fixed njs_benchmark. Message-ID: details: https://hg.nginx.org/njs/rev/736cfe916b2b branches: changeset: 792:736cfe916b2b user: hongzhidao date: Thu Feb 21 00:30:40 2019 +0800 description: Fixed njs_benchmark. diffstat: njs/test/njs_benchmark.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diffs (48 lines): diff -r 7bb252625b94 -r 736cfe916b2b njs/test/njs_benchmark.c --- a/njs/test/njs_benchmark.c Wed Feb 20 21:04:22 2019 +0300 +++ b/njs/test/njs_benchmark.c Thu Feb 21 00:30:40 2019 +0800 @@ -54,7 +54,7 @@ njs_unit_test_benchmark(nxt_str_t *scrip goto done; } - (void) njs_vm_run(nvm); + (void) njs_vm_start(nvm); if (njs_vm_retval_to_ext_string(nvm, &s) != NXT_OK) { printf("njs_vm_retval_to_ext_string() failed\n"); @@ -112,7 +112,7 @@ main(int argc, char **argv) static nxt_str_t fibo_number = nxt_string( "function fibo(n) {" " if (n > 1)" - " return fibo(n - 1) + fibo(n - 2)" + " return fibo(n - 1) + fibo(n - 2);" " return 1" "}" "fibo(32)"); @@ -120,7 +120,7 @@ main(int argc, char **argv) static nxt_str_t fibo_ascii = nxt_string( "function fibo(n) {" " if (n > 1)" - " return fibo(n - 1) + fibo(n - 2)" + " return fibo(n - 1) + fibo(n - 2);" " return '.'" "}" "fibo(32).length"); @@ -129,7 +129,7 @@ main(int argc, char **argv) "var a = '\\x80'.toBytes();" "function fibo(n) {" " if (n > 1)" - " return fibo(n - 1) + fibo(n - 2)" + " return fibo(n - 1) + fibo(n - 2);" " return a" "}" "fibo(32).length"); @@ -137,7 +137,7 @@ main(int argc, char **argv) static nxt_str_t fibo_utf8 = nxt_string( "function fibo(n) {" " if (n > 1)" - " return fibo(n - 1) + fibo(n - 2)" + " return fibo(n - 1) + fibo(n - 2);" " return '?'" "}" "fibo(32).length"); From xeioex at nginx.com Thu Feb 21 13:49:17 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 21 Feb 2019 13:49:17 +0000 Subject: [njs] Improved API for value creation from the outside of VM. Message-ID: details: https://hg.nginx.org/njs/rev/2a6f5ffd5e96 branches: changeset: 793:2a6f5ffd5e96 user: Dmitry Volyntsev date: Thu Feb 21 16:35:52 2019 +0300 description: Improved API for value creation from the outside of VM. diffstat: nginx/ngx_http_js_module.c | 34 ++++++++++++++++++---------------- nginx/ngx_stream_js_module.c | 13 +++++++------ njs/njs.h | 22 ++++++++++++---------- njs/njs_string.c | 8 ++++---- njs/njs_string.h | 4 ++++ njs/njs_vm.c | 21 ++++++++++++++++++--- njs/test/njs_unit_test.c | 18 +++++++++--------- 7 files changed, 72 insertions(+), 48 deletions(-) diffs (383 lines): diff -r 736cfe916b2b -r 2a6f5ffd5e96 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Thu Feb 21 00:30:40 2019 +0800 +++ b/nginx/ngx_http_js_module.c Thu Feb 21 16:35:52 2019 +0300 @@ -805,7 +805,7 @@ ngx_http_js_ext_get_string(njs_vm_t *vm, field = (ngx_str_t *) (p + data); - return njs_string_create(vm, value, field->data, field->len, 0); + return njs_vm_value_string_set(vm, value, field->data, field->len); } @@ -864,7 +864,7 @@ ngx_http_js_ext_next_header(njs_vm_t *vm continue; } - return njs_string_create(vm, value, h->key.data, h->key.len, 0); + return njs_vm_value_string_set(vm, value, h->key.data, h->key.len); } return NJS_DONE; @@ -920,10 +920,10 @@ ngx_http_js_ext_get_header_out(njs_vm_t h = ngx_http_js_get_header(&r->headers_out.headers.part, v->start, v->length); if (h == NULL) { - return njs_string_create(vm, value, NULL, 0, 0); + return njs_vm_value_string_set(vm, value, NULL, 0); } - return njs_string_create(vm, value, h->value.data, h->value.len, 0); + return njs_vm_value_string_set(vm, value, h->value.data, h->value.len); } @@ -1122,7 +1122,8 @@ ngx_http_js_ext_send(njs_vm_t *vm, njs_v next = 0; for ( ;; ) { - ret = njs_value_string_copy(vm, &s, njs_argument(args, n), &next); + ret = njs_vm_value_string_copy(vm, &s, njs_argument(args, n), + &next); if (ret == NJS_DECLINED) { break; @@ -1387,7 +1388,7 @@ ngx_http_js_ext_get_http_version(njs_vm_ break; } - return njs_string_create(vm, value, v.data, v.len, 0); + return njs_vm_value_string_set(vm, value, v.data, v.len); } @@ -1401,7 +1402,8 @@ ngx_http_js_ext_get_remote_address(njs_v r = (ngx_http_request_t *) obj; c = r->connection; - return njs_string_create(vm, value, c->addr_text.data, c->addr_text.len, 0); + return njs_vm_value_string_set(vm, value, c->addr_text.data, + c->addr_text.len); } @@ -1472,7 +1474,7 @@ ngx_http_js_ext_get_request_body(njs_vm_ done: - ret = njs_string_create(vm, request_body, body, len, 0); + ret = njs_vm_value_string_set(vm, request_body, body, len); if (ret != NXT_OK) { return NJS_ERROR; @@ -1498,10 +1500,10 @@ ngx_http_js_ext_get_header_in(njs_vm_t * h = ngx_http_js_get_header(&r->headers_in.headers.part, v->start, v->length); if (h == NULL) { - return njs_string_create(vm, value, NULL, 0, 0); + return njs_vm_value_string_set(vm, value, NULL, 0); } - return njs_string_create(vm, value, h->value.data, h->value.len, 0); + return njs_vm_value_string_set(vm, value, h->value.data, h->value.len); } @@ -1524,10 +1526,10 @@ ngx_http_js_ext_get_arg(njs_vm_t *vm, nj v = (nxt_str_t *) data; if (ngx_http_arg(r, v->start, v->length, &arg) == NGX_OK) { - return njs_string_create(vm, value, arg.data, arg.len, 0); + return njs_vm_value_string_set(vm, value, arg.data, arg.len); } - return njs_string_create(vm, value, NULL, 0, 0); + return njs_vm_value_string_set(vm, value, NULL, 0); } @@ -1590,7 +1592,7 @@ ngx_http_js_ext_next_arg(njs_vm_t *vm, n entry->len = 0; } - return njs_string_create(vm, value, start, len, 0); + return njs_vm_value_string_set(vm, value, start, len); } @@ -1614,10 +1616,10 @@ ngx_http_js_ext_get_variable(njs_vm_t *v vv = ngx_http_get_variable(r, &name, key); if (vv == NULL || vv->not_found) { - return njs_string_create(vm, value, NULL, 0, 0); + return njs_vm_value_string_set(vm, value, NULL, 0); } - return njs_string_create(vm, value, vv->data, vv->len, 0); + return njs_vm_value_string_set(vm, value, vv->data, vv->len); } @@ -1980,7 +1982,7 @@ ngx_http_js_ext_get_reply_body(njs_vm_t len = b ? b->last - b->pos : 0; - p = njs_string_alloc(vm, value, len, 0); + p = njs_vm_value_string_alloc(vm, value, len); if (p == NULL) { return NJS_ERROR; } diff -r 736cfe916b2b -r 2a6f5ffd5e96 nginx/ngx_stream_js_module.c --- a/nginx/ngx_stream_js_module.c Thu Feb 21 00:30:40 2019 +0800 +++ b/nginx/ngx_stream_js_module.c Thu Feb 21 16:35:52 2019 +0300 @@ -794,7 +794,7 @@ ngx_stream_js_buffer_arg(ngx_stream_sess len = b ? b->last - b->pos : 0; - p = njs_string_alloc(ctx->vm, buffer, len, 0); + p = njs_vm_value_string_alloc(ctx->vm, buffer, len); if (p == NULL) { return NJS_ERROR; } @@ -821,8 +821,8 @@ ngx_stream_js_flags_arg(ngx_stream_sessi ctx = ngx_stream_get_module_ctx(s, ngx_stream_js_module); - njs_string_create(ctx->vm, njs_value_arg(&last_key), last_str.start, - last_str.length, 0); + njs_vm_value_string_set(ctx->vm, njs_value_arg(&last_key), last_str.start, + last_str.length); c = s->connection; @@ -884,7 +884,8 @@ ngx_stream_js_ext_get_remote_address(njs s = (ngx_stream_session_t *) obj; c = s->connection; - return njs_string_create(vm, value, c->addr_text.data, c->addr_text.len, 0); + return njs_vm_value_string_set(vm, value, c->addr_text.data, + c->addr_text.len); } @@ -1200,10 +1201,10 @@ ngx_stream_js_ext_get_variable(njs_vm_t vv = ngx_stream_get_variable(s, &name, key); if (vv == NULL || vv->not_found) { - return njs_string_create(vm, value, NULL, 0, 0); + return njs_vm_value_string_set(vm, value, NULL, 0); } - return njs_string_create(vm, value, vv->data, vv->len, 0); + return njs_vm_value_string_set(vm, value, vv->data, vv->len); } diff -r 736cfe916b2b -r 2a6f5ffd5e96 njs/njs.h --- a/njs/njs.h Thu Feb 21 00:30:40 2019 +0800 +++ b/njs/njs.h Thu Feb 21 16:35:52 2019 +0300 @@ -57,7 +57,7 @@ extern const njs_value_t njs_ #define njs_vm_error(vm, fmt, ...) \ - njs_value_error_set(vm, njs_vm_retval(vm), fmt, ##__VA_ARGS__) + njs_vm_value_error_set(vm, njs_vm_retval(vm), fmt, ##__VA_ARGS__) typedef njs_ret_t (*njs_extern_get_t)(njs_vm_t *vm, njs_value_t *value, @@ -231,14 +231,16 @@ NXT_EXPORT njs_function_t *njs_vm_functi NXT_EXPORT njs_value_t *njs_vm_retval(njs_vm_t *vm); NXT_EXPORT void njs_vm_retval_set(njs_vm_t *vm, const njs_value_t *value); -NXT_EXPORT u_char * njs_string_alloc(njs_vm_t *vm, njs_value_t *value, - uint32_t size, uint32_t length); -NXT_EXPORT njs_ret_t njs_string_create(njs_vm_t *vm, njs_value_t *value, - const u_char *start, uint32_t size, uint32_t length); - -NXT_EXPORT nxt_int_t njs_value_string_copy(njs_vm_t *vm, nxt_str_t *retval, +/* + * Sets a byte string value. + * start data is not copied and should not be freed. + */ +NXT_EXPORT njs_ret_t njs_vm_value_string_set(njs_vm_t *vm, njs_value_t *value, + const u_char *start, uint32_t size); +NXT_EXPORT u_char *njs_vm_value_string_alloc(njs_vm_t *vm, njs_value_t *value, + uint32_t size); +NXT_EXPORT nxt_int_t njs_vm_value_string_copy(njs_vm_t *vm, nxt_str_t *retval, const njs_value_t *value, uintptr_t *next); - NXT_EXPORT njs_ret_t njs_vm_value_to_ext_string(njs_vm_t *vm, nxt_str_t *dst, const njs_value_t *src, nxt_uint_t handle_exception); NXT_EXPORT njs_ret_t njs_vm_retval_to_ext_string(njs_vm_t *vm, nxt_str_t *dst); @@ -248,14 +250,14 @@ NXT_EXPORT njs_ret_t njs_vm_value_dump(n NXT_EXPORT njs_ret_t njs_vm_retval_dump(njs_vm_t *vm, nxt_str_t *dst, nxt_uint_t indent); +NXT_EXPORT void njs_vm_value_error_set(njs_vm_t *vm, njs_value_t *value, + const char *fmt, ...); NXT_EXPORT void njs_vm_memory_error(njs_vm_t *vm); NXT_EXPORT void njs_value_void_set(njs_value_t *value); NXT_EXPORT void njs_value_boolean_set(njs_value_t *value, int yn); NXT_EXPORT void njs_value_number_set(njs_value_t *value, double num); NXT_EXPORT void njs_value_data_set(njs_value_t *value, void *data); -NXT_EXPORT void njs_value_error_set(njs_vm_t *vm, njs_value_t *value, - const char *fmt, ...); NXT_EXPORT uint8_t njs_value_bool(const njs_value_t *value); NXT_EXPORT double njs_value_number(const njs_value_t *value); diff -r 736cfe916b2b -r 2a6f5ffd5e96 njs/njs_string.c --- a/njs/njs_string.c Thu Feb 21 00:30:40 2019 +0800 +++ b/njs/njs_string.c Thu Feb 21 16:35:52 2019 +0300 @@ -111,8 +111,8 @@ static njs_ret_t njs_string_decode(njs_v njs_ret_t -njs_string_create(njs_vm_t *vm, njs_value_t *value, const u_char *start, - uint32_t size, uint32_t length) +njs_string_set(njs_vm_t *vm, njs_value_t *value, const u_char *start, + uint32_t size) { u_char *dst; const u_char *src; @@ -123,7 +123,7 @@ njs_string_create(njs_vm_t *vm, njs_valu if (size <= NJS_STRING_SHORT) { value->short_string.size = size; - value->short_string.length = length; + value->short_string.length = 0; dst = value->short_string.start; src = start; @@ -155,7 +155,7 @@ njs_string_create(njs_vm_t *vm, njs_valu value->long_string.data = string; string->start = (u_char *) start; - string->length = length; + string->length = 0; string->retain = 1; } diff -r 736cfe916b2b -r 2a6f5ffd5e96 njs/njs_string.h --- a/njs/njs_string.h Thu Feb 21 00:30:40 2019 +0800 +++ b/njs/njs_string.h Thu Feb 21 16:35:52 2019 +0300 @@ -121,6 +121,10 @@ njs_string_length(njs_utf8_t utf8, const } +njs_ret_t njs_string_set(njs_vm_t *vm, njs_value_t *value, const u_char *start, + uint32_t size); +u_char *njs_string_alloc(njs_vm_t *vm, njs_value_t *value, uint32_t size, + uint32_t length); njs_ret_t njs_string_new(njs_vm_t *vm, njs_value_t *value, const u_char *start, uint32_t size, uint32_t length); njs_ret_t njs_string_hex(njs_vm_t *vm, njs_value_t *value, diff -r 736cfe916b2b -r 2a6f5ffd5e96 njs/njs_vm.c --- a/njs/njs_vm.c Thu Feb 21 00:30:40 2019 +0800 +++ b/njs/njs_vm.c Thu Feb 21 16:35:52 2019 +0300 @@ -3326,8 +3326,23 @@ njs_value_data_set(njs_value_t *value, v } +nxt_noinline njs_ret_t +njs_vm_value_string_set(njs_vm_t *vm, njs_value_t *value, const u_char *start, + uint32_t size) +{ + return njs_string_set(vm, value, start, size); +} + + +nxt_noinline u_char * +njs_vm_value_string_alloc(njs_vm_t *vm, njs_value_t *value, uint32_t size) +{ + return njs_string_alloc(vm, value, size, 0); +} + + void -njs_value_error_set(njs_vm_t *vm, njs_value_t *value, const char *fmt, ...) +njs_vm_value_error_set(njs_vm_t *vm, njs_value_t *value, const char *fmt, ...) { va_list args; u_char buf[NXT_MAX_ERROR_STR], *p; @@ -3431,8 +3446,8 @@ njs_value_is_function(const njs_value_t nxt_int_t -njs_value_string_copy(njs_vm_t *vm, nxt_str_t *retval, const njs_value_t *value, - uintptr_t *next) +njs_vm_value_string_copy(njs_vm_t *vm, nxt_str_t *retval, + const njs_value_t *value, uintptr_t *next) { uintptr_t n; njs_array_t *array; diff -r 736cfe916b2b -r 2a6f5ffd5e96 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Thu Feb 21 00:30:40 2019 +0800 +++ b/njs/test/njs_unit_test.c Thu Feb 21 16:35:52 2019 +0300 @@ -11324,7 +11324,7 @@ njs_unit_test_r_get_uri_external(njs_vm_ field = (nxt_str_t *) (p + data); - return njs_string_create(vm, value, field->start, field->length, 0); + return njs_vm_value_string_set(vm, value, field->start, field->length); } @@ -11355,7 +11355,7 @@ njs_unit_test_r_get_a_external(njs_vm_t p = nxt_sprintf(buf, buf + nxt_length(buf), "%uD", r->a); - return njs_string_create(vm, value, buf, p - buf, 0); + return njs_vm_value_string_set(vm, value, buf, p - buf); } @@ -11373,7 +11373,7 @@ static njs_ret_t njs_unit_test_host_external(njs_vm_t *vm, njs_value_t *value, void *obj, uintptr_t data) { - return njs_string_create(vm, value, (u_char *) "???????????", 22, 0); + return njs_vm_value_string_set(vm, value, (u_char *) "???????????", 22); } @@ -11427,8 +11427,8 @@ njs_unit_test_r_set_vars(njs_vm_t *vm, v return NXT_ERROR; } - njs_string_create(vm, &name, key->start, key->length, 0); - njs_string_create(vm, &val, value->start, value->length, 0); + 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) { @@ -11492,7 +11492,7 @@ njs_unit_test_header_external(njs_vm_t * size = 7 + h->length; - p = njs_string_alloc(vm, value, size, 0); + p = njs_vm_value_string_alloc(vm, value, size); if (p == NULL) { return NJS_ERROR; } @@ -11531,7 +11531,7 @@ njs_unit_test_header_next_external(njs_v return NXT_DONE; } - return njs_string_create(vm, value, s, 2, 0); + return njs_vm_value_string_set(vm, value, s, 2); } @@ -11550,8 +11550,8 @@ njs_unit_test_method_external(njs_vm_t * ret = njs_vm_value_to_ext_string(vm, &s, njs_arg(args, nargs, 1), 0); if (ret == NXT_OK && s.length == 3 && memcmp(s.start, "YES", 3) == 0) { - return njs_string_create(vm, njs_vm_retval(vm), r->uri.start, - r->uri.length, 0); + return njs_vm_value_string_set(vm, njs_vm_retval(vm), r->uri.start, + r->uri.length); } vm->retval = njs_value_void; From xeioex at nginx.com Thu Feb 21 18:06:26 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 21 Feb 2019 18:06:26 +0000 Subject: [njs] Added support for setting nginx variables. Message-ID: details: https://hg.nginx.org/njs/rev/c0e7041165c0 branches: changeset: 794:c0e7041165c0 user: Dmitry Volyntsev date: Thu Feb 21 20:47:52 2019 +0300 description: Added support for setting nginx variables. This closes #37 issue on Github. diffstat: nginx/ngx_http_js_module.c | 71 ++++++++++++++++++++++++++++++++++++++++++- nginx/ngx_stream_js_module.c | 72 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 141 insertions(+), 2 deletions(-) diffs (191 lines): diff -r 2a6f5ffd5e96 -r c0e7041165c0 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Thu Feb 21 16:35:52 2019 +0300 +++ b/nginx/ngx_http_js_module.c Thu Feb 21 20:47:52 2019 +0300 @@ -117,6 +117,8 @@ static njs_ret_t ngx_http_js_ext_next_ar void *obj, void *next); static njs_ret_t ngx_http_js_ext_get_variable(njs_vm_t *vm, njs_value_t *value, void *obj, uintptr_t data); +static njs_ret_t ngx_http_js_ext_set_variable(njs_vm_t *vm, void *obj, + uintptr_t data, nxt_str_t *value); static njs_ret_t ngx_http_js_ext_subrequest(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); static ngx_int_t ngx_http_js_subrequest(ngx_http_request_t *r, @@ -321,7 +323,7 @@ static njs_external_t ngx_http_js_ext_r NULL, 0, ngx_http_js_ext_get_variable, - NULL, + ngx_http_js_ext_set_variable, NULL, NULL, NULL, @@ -1624,6 +1626,73 @@ ngx_http_js_ext_get_variable(njs_vm_t *v static njs_ret_t +ngx_http_js_ext_set_variable(njs_vm_t *vm, void *obj, uintptr_t data, + nxt_str_t *value) +{ + nxt_str_t *val; + ngx_str_t name; + ngx_uint_t key; + ngx_http_request_t *r; + ngx_http_variable_t *v; + ngx_http_variable_value_t *vv; + ngx_http_core_main_conf_t *cmcf; + + r = (ngx_http_request_t *) obj; + val = (nxt_str_t *) data; + + name.data = val->start; + name.len = val->length; + + cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); + + key = ngx_hash_strlow(name.data, name.data, name.len); + + v = ngx_hash_find(&cmcf->variables_hash, key, name.data, name.len); + + if (v == NULL) { + njs_vm_error(vm, "variable not found"); + return NJS_ERROR; + } + + if (v->set_handler != NULL) { + vv = ngx_pcalloc(r->pool, sizeof(ngx_http_variable_value_t)); + if (vv == NULL) { + return NJS_ERROR; + } + + vv->valid = 1; + vv->not_found = 0; + vv->data = value->start; + vv->len = value->length; + + v->set_handler(r, vv, v->data); + + return NJS_OK; + } + + if (!(v->flags & NGX_HTTP_VAR_INDEXED)) { + njs_vm_error(vm, "variable is not writable"); + return NJS_ERROR; + } + + vv = &r->variables[v->index]; + + vv->valid = 1; + vv->not_found = 0; + + vv->data = ngx_pnalloc(r->pool, value->length); + if (vv->data == NULL) { + return NJS_ERROR; + } + + vv->len = value->length; + ngx_memcpy(vv->data, value->start, vv->len); + + return NJS_OK; +} + + +static njs_ret_t ngx_http_js_ext_subrequest(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) { diff -r 2a6f5ffd5e96 -r c0e7041165c0 nginx/ngx_stream_js_module.c --- a/nginx/ngx_stream_js_module.c Thu Feb 21 16:35:52 2019 +0300 +++ b/nginx/ngx_stream_js_module.c Thu Feb 21 20:47:52 2019 +0300 @@ -99,6 +99,8 @@ static njs_ret_t ngx_stream_js_ext_send( static njs_ret_t ngx_stream_js_ext_get_variable(njs_vm_t *vm, njs_value_t *value, void *obj, uintptr_t data); +static njs_ret_t ngx_stream_js_ext_set_variable(njs_vm_t *vm, void *obj, + uintptr_t data, nxt_str_t *value); static njs_host_event_t ngx_stream_js_set_timer(njs_external_ptr_t external, uint64_t delay, njs_vm_event_t vm_event); @@ -207,7 +209,7 @@ static njs_external_t ngx_stream_js_ext NULL, 0, ngx_stream_js_ext_get_variable, - NULL, + ngx_stream_js_ext_set_variable, NULL, NULL, NULL, @@ -1208,6 +1210,74 @@ ngx_stream_js_ext_get_variable(njs_vm_t } +static njs_ret_t +ngx_stream_js_ext_set_variable(njs_vm_t *vm, void *obj, uintptr_t data, + nxt_str_t *value) +{ + nxt_str_t *val; + ngx_str_t name; + ngx_uint_t key; + ngx_stream_variable_t *v; + ngx_stream_session_t *s; + ngx_stream_core_main_conf_t *cmcf; + ngx_stream_variable_value_t *vv; + + s = (ngx_stream_session_t *) obj; + val = (nxt_str_t *) data; + + name.data = val->start; + name.len = val->length; + + cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module); + + key = ngx_hash_strlow(name.data, name.data, name.len); + + v = ngx_hash_find(&cmcf->variables_hash, key, name.data, name.len); + + if (v == NULL) { + njs_vm_error(vm, "variable not found"); + return NJS_ERROR; + } + + if (v->set_handler != NULL) { + vv = ngx_pcalloc(s->connection->pool, + sizeof(ngx_stream_variable_value_t)); + if (vv == NULL) { + return NJS_ERROR; + } + + vv->valid = 1; + vv->not_found = 0; + vv->data = value->start; + vv->len = value->length; + + v->set_handler(s, vv, v->data); + + return NJS_OK; + } + + if (!(v->flags & NGX_STREAM_VAR_INDEXED)) { + njs_vm_error(vm, "variable is not writable"); + return NJS_ERROR; + } + + vv = &s->variables[v->index]; + + vv->valid = 1; + vv->not_found = 0; + + vv->data = ngx_pnalloc(s->connection->pool, value->length); + if (vv->data == NULL) { + return NJS_ERROR; + } + + vv->len = value->length; + ngx_memcpy(vv->data, value->start, vv->len); + + return NJS_OK; +} + + static njs_host_event_t ngx_stream_js_set_timer(njs_external_ptr_t external, uint64_t delay, njs_vm_event_t vm_event) From fabio.ancona at gmail.com Fri Feb 22 14:31:05 2019 From: fabio.ancona at gmail.com (Fabio Ancona) Date: Fri, 22 Feb 2019 15:31:05 +0100 Subject: Add ".apk" file extension in "mime.types" file In-Reply-To: <16e4044b-d0a0-b6d0-f1d1-60260bd226d0@nginx.com> References: <16e4044b-d0a0-b6d0-f1d1-60260bd226d0@nginx.com> Message-ID: Hi Konstantin. About "client software" I'm referring to browser, Chrome and Internet Explorer in this case. I suggested to add "apk" to the nginx's mime type file only because, without any customization / specification in nginx, the apk file are shown as "text/plain" (like a webpage) in the browser (both Chrome and Internet Explorer). Yes, if I add "default_type application/octet-stream" for apk of course I'm able to downlaod it as file. "application/vnd.android.package-archive" seems to be the "most appropriate and the official one" mime type for .apk files and if I add "application/vnd.android.package-archive" to nginx's mime type file both Chrome and Internet Explorer are able to "recognize" it as file to download and not to show like a HTML page in the browser. Anyway you are free to choose what to do. Thank you. Fabio Ancona Il giorno mar 5 feb 2019 alle ore 16:52 Konstantin Pavlov ha scritto: > Hi Fabio, > > 05.02.2019 16:02, Fabio Ancona wrote: > > Hi all. > > As reported here "https://github.com/nginx/nginx/pull/39" the ".apk" > > file extension is not managed by nginx. > > Please add "application/vnd.android.package-archive apk;" to > > the "mime.types" file. > > > > I have tested it on my nginx/1.15.8 and .apk files are correctly > > downloaded. Before, without "apk" in mime.types, nginx sent .apk as > "text". > > Thank you. > > Best Regards. > Wouldnt a simple "default_type application/octet-stream" be enough, > which is a default for most nginx packages ? I've been personally > running it for years on https://nightlies.videolan.org/ and never > received a single complaint from the testers. > > Overall the consensus seems to be that the content type must be widely > used on the internet to justify its addition. It's hard to judge the > popularity for a delivery method predominatly used for closed-garden > software shops, but what is the software of question that expects such a > mime type? > > Thank you, > > -- > Konstantin Pavlov > https://www.nginx.com/ > -------------- next part -------------- An HTML attachment was scrubbed... URL: From xeioex at nginx.com Fri Feb 22 17:37:39 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 22 Feb 2019 17:37:39 +0000 Subject: [njs] Fixed heap-buffer-overflow in String.prototype.split(). Message-ID: details: https://hg.nginx.org/njs/rev/c4522b3d3ff0 branches: changeset: 795:c4522b3d3ff0 user: Dmitry Volyntsev date: Fri Feb 22 20:33:31 2019 +0300 description: Fixed heap-buffer-overflow in String.prototype.split(). diffstat: njs/njs_string.c | 11 ++++++++--- njs/test/njs_unit_test.c | 3 +++ 2 files changed, 11 insertions(+), 3 deletions(-) diffs (47 lines): diff -r c0e7041165c0 -r c4522b3d3ff0 njs/njs_string.c --- a/njs/njs_string.c Thu Feb 21 20:47:52 2019 +0300 +++ b/njs/njs_string.c Fri Feb 22 20:33:31 2019 +0300 @@ -2726,7 +2726,7 @@ njs_string_prototype_split(njs_vm_t *vm, uint32_t limit; njs_utf8_t utf8; njs_array_t *array; - const u_char *p, *start, *next, *end; + const u_char *p, *start, *next, *last, *end; njs_regexp_utf8_t type; njs_string_prop_t string, split; njs_regexp_pattern_t *pattern; @@ -2778,14 +2778,19 @@ njs_string_prototype_split(njs_vm_t *vm, start = string.start; end = string.start + string.size; + last = end - split.size; do { - for (p = start; p < end; p++) { + for (p = start; p <= last; p++) { if (memcmp(p, split.start, split.size) == 0) { - break; + goto found; } } + p = end; + +found: + next = p + split.size; /* Empty split string. */ diff -r c0e7041165c0 -r c4522b3d3ff0 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Thu Feb 21 20:47:52 2019 +0300 +++ b/njs/test/njs_unit_test.c Fri Feb 22 20:33:31 2019 +0300 @@ -5096,6 +5096,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("'?????'.split('?')"), nxt_string("?,?,?") }, + { nxt_string("'a'.repeat(16).split('a'.repeat(15))"), + nxt_string(",a") }, + { nxt_string("('?'+'?'.repeat(33)).repeat(2).split('?')[1][32]"), nxt_string("?") }, From miranovy at gmail.com Mon Feb 25 11:06:07 2019 From: miranovy at gmail.com (=?UTF-8?Q?Miroslav_Nov=C3=BD?=) Date: Mon, 25 Feb 2019 12:06:07 +0100 Subject: limit_rate_after support variables In-Reply-To: References: <20180827112847.GE71000@lo0.su> <20180827160021.GG71000@lo0.su> <20180829114230.GC43480@lo0.su> <20181120141005.GA72348@lo0.su> <20181206144522.GF50234@lo0.su> Message-ID: Hello, how does it look with merge into the main branch? Thank you for answer Mira Novy po 10. 12. 2018 v 14:30 odes?latel Miroslav Novy napsal: > Hello, > your path is very good. I tested it and works fine for as. > > Reading complex value to the same local variable limit_rate was conflusing > for me at first time. But it is correct :) > > if (r->limit_rate_after == 0 > + && clcf->limit_rate_after > + && ngx_http_complex_value_size(r, clcf->limit_rate_after, > &val, > + &limit_rate) > <----------------------- > + == NGX_OK) > + { > + if (limit_rate != (size_t) NGX_ERROR) { > + r->limit_rate_after = limit_rate; > + > + } else if (val.len) { > > Please, merge your path to master branch. > > Best regards > M. Nov? > -------------- next part -------------- An HTML attachment was scrubbed... URL: From xeioex at nginx.com Mon Feb 25 12:38:48 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 25 Feb 2019 12:38:48 +0000 Subject: [njs] Fixed Array.prototype.fill(). Message-ID: details: https://hg.nginx.org/njs/rev/1718603aae6a branches: changeset: 797:1718603aae6a user: Artem S. Povalyukhin date: Sat Feb 23 04:21:44 2019 +0300 description: Fixed Array.prototype.fill(). This closes #71 issue on Github. diffstat: njs/njs_array.c | 11 +++++++---- njs/test/njs_unit_test.c | 4 ++++ 2 files changed, 11 insertions(+), 4 deletions(-) diffs (46 lines): diff -r 25b394b0e953 -r 1718603aae6a njs/njs_array.c --- a/njs/njs_array.c Sat Feb 23 04:20:23 2019 +0300 +++ b/njs/njs_array.c Sat Feb 23 04:21:44 2019 +0300 @@ -1372,12 +1372,13 @@ static njs_ret_t njs_array_prototype_fill(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) { - nxt_int_t i, start, end, length; - njs_array_t *array; + nxt_int_t i, start, end, length; + njs_array_t *array; + const njs_value_t *value; vm->retval = args[0]; - if (nargs < 2 || !njs_is_array(&args[0])) { + if (!njs_is_array(&args[0])) { return NXT_OK; } @@ -1423,8 +1424,10 @@ njs_array_prototype_fill(njs_vm_t *vm, n } } + value = njs_arg(args, nargs, 1); + for (i = start; i < end; i++) { - array->start[i] = args[1]; + array->start[i] = *value; } return NXT_OK; diff -r 25b394b0e953 -r 1718603aae6a njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Sat Feb 23 04:20:23 2019 +0300 +++ b/njs/test/njs_unit_test.c Sat Feb 23 04:21:44 2019 +0300 @@ -3668,6 +3668,10 @@ static njs_unit_test_t njs_test[] = { nxt_string("[1,2,3].fill({a:\"b\"}, 1, 2);"), nxt_string("1,[object Object],3") }, + { nxt_string("Array(3).fill().reduce(function(a, x)" + "{ return a + (x === undefined); }, 0)"), + nxt_string("3") }, + { nxt_string("var a = [];" "a.filter(function(v, i, a) { return v > 1 })"), nxt_string("") }, From xeioex at nginx.com Mon Feb 25 12:38:48 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 25 Feb 2019 12:38:48 +0000 Subject: [njs] Style. Message-ID: details: https://hg.nginx.org/njs/rev/25b394b0e953 branches: changeset: 796:25b394b0e953 user: Artem S. Povalyukhin date: Sat Feb 23 04:20:23 2019 +0300 description: Style. diffstat: njs/njs_array.c | 30 +++++++++++++++--------------- 1 files changed, 15 insertions(+), 15 deletions(-) diffs (40 lines): diff -r c4522b3d3ff0 -r 25b394b0e953 njs/njs_array.c --- a/njs/njs_array.c Fri Feb 22 20:33:31 2019 +0300 +++ b/njs/njs_array.c Sat Feb 23 04:20:23 2019 +0300 @@ -1406,21 +1406,21 @@ njs_array_prototype_fill(njs_vm_t *vm, n } } - if (nargs > 3) { - end = args[3].data.u.number; - - if (end > length) { - end = length; - } - - if (end < 0) { - end += length; - - if (end < 0) { - end = 0; - } - } - } + if (nargs > 3) { + end = args[3].data.u.number; + + if (end > length) { + end = length; + } + + if (end < 0) { + end += length; + + if (end < 0) { + end = 0; + } + } + } } for (i = start; i < end; i++) { From mdounin at mdounin.ru Mon Feb 25 13:49:36 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 25 Feb 2019 13:49:36 +0000 Subject: [nginx] Style. Message-ID: details: https://hg.nginx.org/nginx/rev/0f0c75caa038 branches: changeset: 7458:0f0c75caa038 user: Maxim Dounin date: Mon Feb 25 16:41:08 2019 +0300 description: Style. diffstat: src/http/ngx_http_request.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (11 lines): diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -833,6 +833,7 @@ ngx_http_ssl_handshake_handler(ngx_conne ngx_http_close_connection(c); } + #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME int From mdounin at mdounin.ru Mon Feb 25 13:49:37 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 25 Feb 2019 13:49:37 +0000 Subject: [nginx] SSL: removed logging of empty "(SSL:)" in ngx_ssl_error(). Message-ID: details: https://hg.nginx.org/nginx/rev/982008fbc4ba branches: changeset: 7459:982008fbc4ba user: Maxim Dounin date: Mon Feb 25 16:41:15 2019 +0300 description: SSL: removed logging of empty "(SSL:)" in ngx_ssl_error(). The "(SSL:)" snippet currently appears in logs when nginx code uses ngx_ssl_error() to log an error, but OpenSSL's error queue is empty. This can happen either because the error wasn't in fact from OpenSSL, or because OpenSSL did not indicate the error in the error queue for some reason. In particular, currently "(SSL:)" can be seen in errors at least in the following cases: - When SSL_write() fails due to a syscall error, "[info] ... SSL_write() failed (SSL:) (32: Broken pipe)...". - When loading a certificate with no data in it, "[emerg] PEM_read_bio_X509_AUX(...) failed (SSL:)". This can easily happen due to an additional empty line before the end line, so all lines of the certificate are interpreted as header lines. - When trying to configure an unknown curve, "[emerg] SSL_CTX_set1_curves_list("foo") failed (SSL:)". Likely there are other cases as well. With this change, "(SSL:...)" will be only added to the error message if there is something in the error queue. This is expected to make logs more readable in the above cases. Additionally, with this change it is now possible to use ngx_ssl_error() to log errors when some of the possible errors are not from OpenSSL and not expected to have anything in the error queue. diffstat: src/event/ngx_event_openssl.c | 70 +++++++++++++++++++++++------------------- 1 files changed, 38 insertions(+), 32 deletions(-) diffs (83 lines): diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -2743,41 +2743,47 @@ ngx_ssl_error(ngx_uint_t level, ngx_log_ p = ngx_vslprintf(errstr, last - 1, fmt, args); va_end(args); - p = ngx_cpystrn(p, (u_char *) " (SSL:", last - p); - - for ( ;; ) { - - n = ERR_peek_error_line_data(NULL, NULL, &data, &flags); - - if (n == 0) { - break; - } - - /* ERR_error_string_n() requires at least one byte */ - - if (p >= last - 1) { - goto next; + if (ERR_peek_error()) { + p = ngx_cpystrn(p, (u_char *) " (SSL:", last - p); + + for ( ;; ) { + + n = ERR_peek_error_line_data(NULL, NULL, &data, &flags); + + if (n == 0) { + break; + } + + /* ERR_error_string_n() requires at least one byte */ + + if (p >= last - 1) { + goto next; + } + + *p++ = ' '; + + ERR_error_string_n(n, (char *) p, last - p); + + while (p < last && *p) { + p++; + } + + if (p < last && *data && (flags & ERR_TXT_STRING)) { + *p++ = ':'; + p = ngx_cpystrn(p, (u_char *) data, last - p); + } + + next: + + (void) ERR_get_error(); } - *p++ = ' '; - - ERR_error_string_n(n, (char *) p, last - p); - - while (p < last && *p) { - p++; + if (p < last) { + *p++ = ')'; } - - if (p < last && *data && (flags & ERR_TXT_STRING)) { - *p++ = ':'; - p = ngx_cpystrn(p, (u_char *) data, last - p); - } - - next: - - (void) ERR_get_error(); - } - - ngx_log_error(level, log, err, "%*s)", p - errstr, errstr); + } + + ngx_log_error(level, log, err, "%*s", p - errstr, errstr); } From mdounin at mdounin.ru Mon Feb 25 13:49:39 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 25 Feb 2019 13:49:39 +0000 Subject: [nginx] SSL: reworked ngx_ssl_certificate(). Message-ID: details: https://hg.nginx.org/nginx/rev/77436d9951a1 branches: changeset: 7460:77436d9951a1 user: Maxim Dounin date: Mon Feb 25 16:41:28 2019 +0300 description: SSL: reworked ngx_ssl_certificate(). This makes it possible to reuse certificate loading at runtime, as introduced in the following patches. Additionally, this improves error logging, so nginx will now log human-friendly messages "cannot load certificate" instead of only referring to sometimes cryptic names of OpenSSL functions. diffstat: src/event/ngx_event_openssl.c | 333 ++++++++++++++++++++++++++--------------- 1 files changed, 208 insertions(+), 125 deletions(-) diffs (440 lines): diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -18,6 +18,10 @@ typedef struct { } ngx_openssl_conf_t; +static X509 *ngx_ssl_load_certificate(ngx_pool_t *pool, char **err, + ngx_str_t *cert, STACK_OF(X509) **chain); +static EVP_PKEY *ngx_ssl_load_certificate_key(ngx_pool_t *pool, char **err, + ngx_str_t *key, ngx_array_t *passwords); static int ngx_ssl_password_callback(char *buf, int size, int rwflag, void *userdata); static int ngx_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store); @@ -407,17 +411,139 @@ ngx_int_t ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, ngx_str_t *key, ngx_array_t *passwords) { - BIO *bio; - X509 *x509; - u_long n; - ngx_str_t *pwd; - ngx_uint_t tries; - - if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) { + char *err; + X509 *x509; + EVP_PKEY *pkey; + STACK_OF(X509) *chain; + + x509 = ngx_ssl_load_certificate(cf->pool, &err, cert, &chain); + if (x509 == NULL) { + if (err != NULL) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "cannot load certificate \"%s\": %s", + cert->data, err); + } + + return NGX_ERROR; + } + + if (SSL_CTX_use_certificate(ssl->ctx, x509) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_use_certificate(\"%s\") failed", cert->data); + X509_free(x509); + sk_X509_pop_free(chain, X509_free); + return NGX_ERROR; + } + + if (X509_set_ex_data(x509, ngx_ssl_certificate_name_index, cert->data) + == 0) + { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed"); + X509_free(x509); + sk_X509_pop_free(chain, X509_free); + return NGX_ERROR; + } + + if (X509_set_ex_data(x509, ngx_ssl_next_certificate_index, + SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index)) + == 0) + { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed"); + X509_free(x509); + sk_X509_pop_free(chain, X509_free); + return NGX_ERROR; + } + + if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, x509) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_set_ex_data() failed"); + X509_free(x509); + sk_X509_pop_free(chain, X509_free); return NGX_ERROR; } /* + * Note that x509 is not freed here, but will be instead freed in + * ngx_ssl_cleanup_ctx(). This is because we need to preserve all + * certificates to be able to iterate all of them through exdata + * (ngx_ssl_certificate_index, ngx_ssl_next_certificate_index), + * while OpenSSL can free a certificate if it is replaced with another + * certificate of the same type. + */ + +#ifdef SSL_CTX_set0_chain + + if (SSL_CTX_set0_chain(ssl->ctx, chain) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_set0_chain(\"%s\") failed", cert->data); + sk_X509_pop_free(chain, X509_free); + return NGX_ERROR; + } + +#else + { + int n; + + /* SSL_CTX_set0_chain() is only available in OpenSSL 1.0.2+ */ + + n = sk_X509_num(chain); + + while (n--) { + x509 = sk_X509_shift(chain); + + if (SSL_CTX_add_extra_chain_cert(ssl->ctx, x509) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_add_extra_chain_cert(\"%s\") failed", + cert->data); + sk_X509_pop_free(chain, X509_free); + return NGX_ERROR; + } + } + + sk_X509_free(chain); + } +#endif + + pkey = ngx_ssl_load_certificate_key(cf->pool, &err, key, passwords); + if (pkey == NULL) { + if (err != NULL) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "cannot load certificate key \"%s\": %s", + key->data, err); + } + + return NGX_ERROR; + } + + if (SSL_CTX_use_PrivateKey(ssl->ctx, pkey) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_use_PrivateKey(\"%s\") failed", key->data); + EVP_PKEY_free(pkey); + return NGX_ERROR; + } + + EVP_PKEY_free(pkey); + + return NGX_OK; +} + + +static X509 * +ngx_ssl_load_certificate(ngx_pool_t *pool, char **err, ngx_str_t *cert, + STACK_OF(X509) **chain) +{ + BIO *bio; + X509 *x509, *temp; + u_long n; + + if (ngx_get_full_name(pool, (ngx_str_t *) &ngx_cycle->conf_prefix, cert) + != NGX_OK) + { + *err = NULL; + return NULL; + } + + /* * we can't use SSL_CTX_use_certificate_chain_file() as it doesn't * allow to access certificate later from SSL_CTX, so we reimplement * it here @@ -425,62 +551,33 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ bio = BIO_new_file((char *) cert->data, "r"); if (bio == NULL) { - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "BIO_new_file(\"%s\") failed", cert->data); - return NGX_ERROR; - } + *err = "BIO_new_file() failed"; + return NULL; + } + + /* certificate itself */ x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL); if (x509 == NULL) { - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "PEM_read_bio_X509_AUX(\"%s\") failed", cert->data); - BIO_free(bio); - return NGX_ERROR; - } - - if (SSL_CTX_use_certificate(ssl->ctx, x509) == 0) { - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "SSL_CTX_use_certificate(\"%s\") failed", cert->data); - X509_free(x509); - BIO_free(bio); - return NGX_ERROR; - } - - if (X509_set_ex_data(x509, ngx_ssl_certificate_name_index, cert->data) - == 0) - { - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed"); - X509_free(x509); + *err = "PEM_read_bio_X509_AUX() failed"; BIO_free(bio); - return NGX_ERROR; - } - - if (X509_set_ex_data(x509, ngx_ssl_next_certificate_index, - SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index)) - == 0) - { - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed"); - X509_free(x509); + return NULL; + } + + /* rest of the chain */ + + *chain = sk_X509_new_null(); + if (*chain == NULL) { + *err = "sk_X509_new_null() failed"; BIO_free(bio); - return NGX_ERROR; - } - - if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, x509) - == 0) - { - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "SSL_CTX_set_ex_data() failed"); X509_free(x509); - BIO_free(bio); - return NGX_ERROR; - } - - /* read rest of the chain */ + return NULL; + } for ( ;; ) { - x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL); - if (x509 == NULL) { + temp = PEM_read_bio_X509(bio, NULL, NULL, NULL); + if (temp == NULL) { n = ERR_peek_last_error(); if (ERR_GET_LIB(n) == ERR_LIB_PEM @@ -493,43 +590,38 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ /* some real error */ - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "PEM_read_bio_X509(\"%s\") failed", cert->data); + *err = "PEM_read_bio_X509() failed"; BIO_free(bio); - return NGX_ERROR; + X509_free(x509); + sk_X509_pop_free(*chain, X509_free); + return NULL; } -#ifdef SSL_CTRL_CHAIN_CERT - - /* - * SSL_CTX_add0_chain_cert() is needed to add chain to - * a particular certificate when multiple certificates are used; - * only available in OpenSSL 1.0.2+ - */ - - if (SSL_CTX_add0_chain_cert(ssl->ctx, x509) == 0) { - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "SSL_CTX_add0_chain_cert(\"%s\") failed", - cert->data); - X509_free(x509); + if (sk_X509_push(*chain, temp) == 0) { + *err = "sk_X509_push() failed"; BIO_free(bio); - return NGX_ERROR; + X509_free(x509); + sk_X509_pop_free(*chain, X509_free); + return NULL; } - -#else - if (SSL_CTX_add_extra_chain_cert(ssl->ctx, x509) == 0) { - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "SSL_CTX_add_extra_chain_cert(\"%s\") failed", - cert->data); - X509_free(x509); - BIO_free(bio); - return NGX_ERROR; - } -#endif } BIO_free(bio); + return x509; +} + + +static EVP_PKEY * +ngx_ssl_load_certificate_key(ngx_pool_t *pool, char **err, + ngx_str_t *key, ngx_array_t *passwords) +{ + BIO *bio; + EVP_PKEY *pkey; + ngx_str_t *pwd; + ngx_uint_t tries; + pem_password_cb *cb; + if (ngx_strncmp(key->data, "engine:", sizeof("engine:") - 1) == 0) { #ifndef OPENSSL_NO_ENGINE @@ -542,9 +634,8 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ last = (u_char *) ngx_strchr(p, ':'); if (last == NULL) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid syntax in \"%V\"", key); - return NGX_ERROR; + *err = "invalid syntax"; + return NULL; } *last = '\0'; @@ -552,9 +643,8 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ engine = ENGINE_by_id((char *) p); if (engine == NULL) { - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "ENGINE_by_id(\"%s\") failed", p); - return NGX_ERROR; + *err = "ENGINE_by_id() failed"; + return NULL; } *last++ = ':'; @@ -562,76 +652,69 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ pkey = ENGINE_load_private_key(engine, (char *) last, 0, 0); if (pkey == NULL) { - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "ENGINE_load_private_key(\"%s\") failed", last); + *err = "ENGINE_load_private_key() failed"; ENGINE_free(engine); - return NGX_ERROR; + return NULL; } ENGINE_free(engine); - if (SSL_CTX_use_PrivateKey(ssl->ctx, pkey) == 0) { - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "SSL_CTX_use_PrivateKey(\"%s\") failed", last); - EVP_PKEY_free(pkey); - return NGX_ERROR; - } - - EVP_PKEY_free(pkey); - - return NGX_OK; + return pkey; #else - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "loading \"engine:...\" certificate keys " - "is not supported"); - return NGX_ERROR; + *err = "loading \"engine:...\" certificate keys is not supported"; + return NULL; #endif } - if (ngx_conf_full_name(cf->cycle, key, 1) != NGX_OK) { - return NGX_ERROR; + if (ngx_get_full_name(pool, (ngx_str_t *) &ngx_cycle->conf_prefix, key) + != NGX_OK) + { + *err = NULL; + return NULL; + } + + bio = BIO_new_file((char *) key->data, "r"); + if (bio == NULL) { + *err = "BIO_new_file() failed"; + return NULL; } if (passwords) { tries = passwords->nelts; pwd = passwords->elts; - - SSL_CTX_set_default_passwd_cb(ssl->ctx, ngx_ssl_password_callback); - SSL_CTX_set_default_passwd_cb_userdata(ssl->ctx, pwd); + cb = ngx_ssl_password_callback; } else { tries = 1; -#if (NGX_SUPPRESS_WARN) pwd = NULL; -#endif + cb = NULL; } for ( ;; ) { - if (SSL_CTX_use_PrivateKey_file(ssl->ctx, (char *) key->data, - SSL_FILETYPE_PEM) - != 0) - { + pkey = PEM_read_bio_PrivateKey(bio, NULL, cb, pwd); + if (pkey != NULL) { break; } if (--tries) { ERR_clear_error(); - SSL_CTX_set_default_passwd_cb_userdata(ssl->ctx, ++pwd); + (void) BIO_reset(bio); + pwd++; continue; } - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "SSL_CTX_use_PrivateKey_file(\"%s\") failed", key->data); - return NGX_ERROR; - } - - SSL_CTX_set_default_passwd_cb(ssl->ctx, NULL); - - return NGX_OK; + *err = "PEM_read_bio_PrivateKey() failed"; + BIO_free(bio); + return NULL; + } + + BIO_free(bio); + + return pkey; } From mdounin at mdounin.ru Mon Feb 25 13:49:41 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 25 Feb 2019 13:49:41 +0000 Subject: [nginx] SSL: loading of connection-specific certificates. Message-ID: details: https://hg.nginx.org/nginx/rev/a68799465b19 branches: changeset: 7461:a68799465b19 user: Maxim Dounin date: Mon Feb 25 16:41:44 2019 +0300 description: SSL: loading of connection-specific certificates. diffstat: src/event/ngx_event_openssl.c | 74 +++++++++++++++++++++++++++++++++++++++++++ src/event/ngx_event_openssl.h | 4 ++ 2 files changed, 78 insertions(+), 0 deletions(-) diffs (109 lines): diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -528,6 +528,77 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ } +ngx_int_t +ngx_ssl_connection_certificate(ngx_connection_t *c, ngx_pool_t *pool, + ngx_str_t *cert, ngx_str_t *key, ngx_array_t *passwords) +{ + char *err; + X509 *x509; + EVP_PKEY *pkey; + STACK_OF(X509) *chain; + + x509 = ngx_ssl_load_certificate(pool, &err, cert, &chain); + if (x509 == NULL) { + if (err != NULL) { + ngx_ssl_error(NGX_LOG_ERR, c->log, 0, + "cannot load certificate \"%s\": %s", + cert->data, err); + } + + return NGX_ERROR; + } + + if (SSL_use_certificate(c->ssl->connection, x509) == 0) { + ngx_ssl_error(NGX_LOG_ERR, c->log, 0, + "SSL_use_certificate(\"%s\") failed", cert->data); + X509_free(x509); + sk_X509_pop_free(chain, X509_free); + return NGX_ERROR; + } + + X509_free(x509); + +#ifdef SSL_set0_chain + + /* + * SSL_set0_chain() is only available in OpenSSL 1.0.2+, + * but this function is only called via certificate callback, + * which is only available in OpenSSL 1.0.2+ as well + */ + + if (SSL_set0_chain(c->ssl->connection, chain) == 0) { + ngx_ssl_error(NGX_LOG_ERR, c->log, 0, + "SSL_set0_chain(\"%s\") failed", cert->data); + sk_X509_pop_free(chain, X509_free); + return NGX_ERROR; + } + +#endif + + pkey = ngx_ssl_load_certificate_key(pool, &err, key, passwords); + if (pkey == NULL) { + if (err != NULL) { + ngx_ssl_error(NGX_LOG_ERR, c->log, 0, + "cannot load certificate key \"%s\": %s", + key->data, err); + } + + return NGX_ERROR; + } + + if (SSL_use_PrivateKey(c->ssl->connection, pkey) == 0) { + ngx_ssl_error(NGX_LOG_ERR, c->log, 0, + "SSL_use_PrivateKey(\"%s\") failed", key->data); + EVP_PKEY_free(pkey); + return NGX_ERROR; + } + + EVP_PKEY_free(pkey); + + return NGX_OK; +} + + static X509 * ngx_ssl_load_certificate(ngx_pool_t *pool, char **err, ngx_str_t *cert, STACK_OF(X509) **chain) @@ -2747,6 +2818,9 @@ ngx_ssl_connection_error(ngx_connection_ #ifdef SSL_R_INAPPROPRIATE_FALLBACK || n == SSL_R_INAPPROPRIATE_FALLBACK /* 373 */ #endif +#ifdef SSL_R_CERT_CB_ERROR + || n == SSL_R_CERT_CB_ERROR /* 377 */ +#endif #ifdef SSL_R_VERSION_TOO_LOW || n == SSL_R_VERSION_TOO_LOW /* 396 */ #endif diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h --- a/src/event/ngx_event_openssl.h +++ b/src/event/ngx_event_openssl.h @@ -161,10 +161,14 @@ typedef struct { ngx_int_t ngx_ssl_init(ngx_log_t *log); ngx_int_t ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data); + ngx_int_t ngx_ssl_certificates(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *certs, ngx_array_t *keys, ngx_array_t *passwords); ngx_int_t ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, ngx_str_t *key, ngx_array_t *passwords); +ngx_int_t ngx_ssl_connection_certificate(ngx_connection_t *c, ngx_pool_t *pool, + ngx_str_t *cert, ngx_str_t *key, ngx_array_t *passwords); + ngx_int_t ngx_ssl_ciphers(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *ciphers, ngx_uint_t prefer_server_ciphers); ngx_int_t ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, From mdounin at mdounin.ru Mon Feb 25 13:49:42 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 25 Feb 2019 13:49:42 +0000 Subject: [nginx] SSL: variables support in ssl_certificate and ssl_certificate_key. Message-ID: details: https://hg.nginx.org/nginx/rev/be2af41d3620 branches: changeset: 7462:be2af41d3620 user: Maxim Dounin date: Mon Feb 25 16:42:05 2019 +0300 description: SSL: variables support in ssl_certificate and ssl_certificate_key. To evaluate variables, a request is created in the certificate callback, and then freed. To do this without side effects on the stub_status counters and connection state, an additional function was introduced, ngx_http_alloc_request(). Only works with OpenSSL 1.0.2+, since there is no SSL_CTX_set_cert_cb() in older versions. diffstat: src/http/modules/ngx_http_ssl_module.c | 116 +++++++++++++++++++++++++++++- src/http/modules/ngx_http_ssl_module.h | 3 + src/http/ngx_http.h | 4 + src/http/ngx_http_request.c | 126 +++++++++++++++++++++++++++----- 4 files changed, 225 insertions(+), 24 deletions(-) diffs (357 lines): diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -41,6 +41,9 @@ static void *ngx_http_ssl_create_srv_con static char *ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child); +static ngx_int_t ngx_http_ssl_compile_certificates(ngx_conf_t *cf, + ngx_http_ssl_srv_conf_t *conf); + static char *ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_http_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, @@ -550,6 +553,7 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t * set by ngx_pcalloc(): * * sscf->protocols = 0; + * sscf->certificate_values = NULL; * sscf->dhparam = { 0, NULL }; * sscf->ecdh_curve = { 0, NULL }; * sscf->client_certificate = { 0, NULL }; @@ -727,13 +731,38 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * cln->handler = ngx_ssl_cleanup_ctx; cln->data = &conf->ssl; - if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates, - conf->certificate_keys, conf->passwords) - != NGX_OK) - { + if (ngx_http_ssl_compile_certificates(cf, conf) != NGX_OK) { return NGX_CONF_ERROR; } + if (conf->certificate_values) { + +#ifdef SSL_R_CERT_CB_ERROR + + /* install callback to lookup certificates */ + + SSL_CTX_set_cert_cb(conf->ssl.ctx, ngx_http_ssl_certificate, NULL); + +#else + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "variables in " + "\"ssl_certificate\" and \"ssl_certificate_key\" " + "directives are not supported on this platform"); + return NGX_CONF_ERROR; +#endif + + } else { + + /* configure certificates */ + + if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates, + conf->certificate_keys, conf->passwords) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + } + if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers, conf->prefer_server_ciphers) != NGX_OK) @@ -831,6 +860,85 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * } +static ngx_int_t +ngx_http_ssl_compile_certificates(ngx_conf_t *cf, + ngx_http_ssl_srv_conf_t *conf) +{ + ngx_str_t *cert, *key; + ngx_uint_t i, nelts; + ngx_http_complex_value_t *cv; + ngx_http_compile_complex_value_t ccv; + + cert = conf->certificates->elts; + key = conf->certificate_keys->elts; + nelts = conf->certificates->nelts; + + for (i = 0; i < nelts; i++) { + + if (ngx_http_script_variables_count(&cert[i])) { + goto found; + } + + if (ngx_http_script_variables_count(&key[i])) { + goto found; + } + } + + return NGX_OK; + +found: + + conf->certificate_values = ngx_array_create(cf->pool, nelts, + sizeof(ngx_http_complex_value_t)); + if (conf->certificate_values == NULL) { + return NGX_ERROR; + } + + conf->certificate_key_values = ngx_array_create(cf->pool, nelts, + sizeof(ngx_http_complex_value_t)); + if (conf->certificate_key_values == NULL) { + return NGX_ERROR; + } + + for (i = 0; i < nelts; i++) { + + cv = ngx_array_push(conf->certificate_values); + if (cv == NULL) { + return NGX_ERROR; + } + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &cert[i]; + ccv.complex_value = cv; + ccv.zero = 1; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_ERROR; + } + + cv = ngx_array_push(conf->certificate_key_values); + if (cv == NULL) { + return NGX_ERROR; + } + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &key[i]; + ccv.complex_value = cv; + ccv.zero = 1; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_ERROR; + } + } + + return NGX_OK; +} + + static char * ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { diff --git a/src/http/modules/ngx_http_ssl_module.h b/src/http/modules/ngx_http_ssl_module.h --- a/src/http/modules/ngx_http_ssl_module.h +++ b/src/http/modules/ngx_http_ssl_module.h @@ -36,6 +36,9 @@ typedef struct { ngx_array_t *certificates; ngx_array_t *certificate_keys; + ngx_array_t *certificate_values; + ngx_array_t *certificate_key_values; + ngx_str_t dhparam; ngx_str_t ecdh_curve; ngx_str_t client_certificate; diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h --- a/src/http/ngx_http.h +++ b/src/http/ngx_http.h @@ -88,6 +88,10 @@ void ngx_http_close_connection(ngx_conne #if (NGX_HTTP_SSL && defined SSL_CTRL_SET_TLSEXT_HOSTNAME) int ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg); #endif +#if (NGX_HTTP_SSL && defined SSL_R_CERT_CB_ERROR) +int ngx_http_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg); +#endif + ngx_int_t ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b); ngx_int_t ngx_http_parse_uri(ngx_http_request_t *r); diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -11,6 +11,7 @@ static void ngx_http_wait_request_handler(ngx_event_t *ev); +static ngx_http_request_t *ngx_http_alloc_request(ngx_connection_t *c); static void ngx_http_process_request_line(ngx_event_t *rev); static void ngx_http_process_request_headers(ngx_event_t *rev); static ssize_t ngx_http_read_request_header(ngx_http_request_t *r); @@ -503,17 +504,45 @@ ngx_http_wait_request_handler(ngx_event_ ngx_http_request_t * ngx_http_create_request(ngx_connection_t *c) { + ngx_http_request_t *r; + ngx_http_log_ctx_t *ctx; + ngx_http_core_loc_conf_t *clcf; + + r = ngx_http_alloc_request(c); + if (r == NULL) { + return NULL; + } + + c->requests++; + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + ngx_set_connection_log(c, clcf->error_log); + + ctx = c->log->data; + ctx->request = r; + ctx->current_request = r; + +#if (NGX_STAT_STUB) + (void) ngx_atomic_fetch_add(ngx_stat_reading, 1); + r->stat_reading = 1; + (void) ngx_atomic_fetch_add(ngx_stat_requests, 1); +#endif + + return r; +} + + +static ngx_http_request_t * +ngx_http_alloc_request(ngx_connection_t *c) +{ ngx_pool_t *pool; ngx_time_t *tp; ngx_http_request_t *r; - ngx_http_log_ctx_t *ctx; ngx_http_connection_t *hc; ngx_http_core_srv_conf_t *cscf; - ngx_http_core_loc_conf_t *clcf; ngx_http_core_main_conf_t *cmcf; - c->requests++; - hc = c->data; cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module); @@ -541,10 +570,6 @@ ngx_http_create_request(ngx_connection_t r->read_event_handler = ngx_http_block_reading; - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - - ngx_set_connection_log(r->connection, clcf->error_log); - r->header_in = hc->busy ? hc->busy->buf : c->buffer; if (ngx_list_init(&r->headers_out.headers, r->pool, 20, @@ -604,17 +629,8 @@ ngx_http_create_request(ngx_connection_t r->http_state = NGX_HTTP_READING_REQUEST_STATE; - ctx = c->log->data; - ctx->request = r; - ctx->current_request = r; r->log_handler = ngx_http_log_error_handler; -#if (NGX_STAT_STUB) - (void) ngx_atomic_fetch_add(ngx_stat_reading, 1); - r->stat_reading = 1; - (void) ngx_atomic_fetch_add(ngx_stat_requests, 1); -#endif - return r; } @@ -931,6 +947,74 @@ ngx_http_ssl_servername(ngx_ssl_conn_t * #endif + +#ifdef SSL_R_CERT_CB_ERROR + +int +ngx_http_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg) +{ + ngx_str_t cert, key; + ngx_uint_t i, nelts; + ngx_connection_t *c; + ngx_http_request_t *r; + ngx_http_ssl_srv_conf_t *sscf; + ngx_http_complex_value_t *certs, *keys; + + c = ngx_ssl_get_connection(ssl_conn); + + if (c->ssl->handshaked) { + return 0; + } + + r = ngx_http_alloc_request(c); + if (r == NULL) { + return 0; + } + + r->logged = 1; + + sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module); + + nelts = sscf->certificate_values->nelts; + certs = sscf->certificate_values->elts; + keys = sscf->certificate_key_values->elts; + + for (i = 0; i < nelts; i++) { + + if (ngx_http_complex_value(r, &certs[i], &cert) != NGX_OK) { + goto failed; + } + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "ssl cert: \"%s\"", cert.data); + + if (ngx_http_complex_value(r, &keys[i], &key) != NGX_OK) { + goto failed; + } + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "ssl key: \"%s\"", key.data); + + if (ngx_ssl_connection_certificate(c, r->pool, &cert, &key, NULL) + != NGX_OK) + { + goto failed; + } + } + + ngx_http_free_request(r, 0); + c->destroyed = 0; + return 1; + +failed: + + ngx_http_free_request(r, 0); + c->destroyed = 0; + return 0; +} + +#endif + #endif @@ -3514,9 +3598,11 @@ ngx_http_free_request(ngx_http_request_t r->headers_out.status = rc; } - log->action = "logging request"; - - ngx_http_log_request(r); + if (!r->logged) { + log->action = "logging request"; + + ngx_http_log_request(r); + } log->action = "closing request"; From mdounin at mdounin.ru Mon Feb 25 13:49:44 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 25 Feb 2019 13:49:44 +0000 Subject: [nginx] SSL: passwords support for dynamic certificate loading. Message-ID: details: https://hg.nginx.org/nginx/rev/180df83473a4 branches: changeset: 7463:180df83473a4 user: Maxim Dounin date: Mon Feb 25 16:42:23 2019 +0300 description: SSL: passwords support for dynamic certificate loading. Passwords have to be copied to the configuration pool to be used at runtime. Also, to prevent blocking on stdin (with "daemon off;") an empty password list is provided. To make things simpler, password handling was modified to allow an empty array (with 0 elements and elts set to NULL) as an equivalent of an array with 1 empty password. diffstat: src/event/ngx_event_openssl.c | 69 +++++++++++++++++++++++++++++++++- src/event/ngx_event_openssl.h | 2 + src/http/modules/ngx_http_ssl_module.c | 5 ++ src/http/ngx_http_request.c | 3 +- 4 files changed, 77 insertions(+), 2 deletions(-) diffs (133 lines): diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -771,7 +771,7 @@ ngx_ssl_load_certificate_key(ngx_pool_t break; } - if (--tries) { + if (tries-- > 1) { ERR_clear_error(); (void) BIO_reset(bio); pwd++; @@ -800,6 +800,10 @@ ngx_ssl_password_callback(char *buf, int return 0; } + if (pwd == NULL) { + return 0; + } + if (pwd->len > (size_t) size) { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "password is truncated to %d bytes", size); @@ -1215,6 +1219,69 @@ cleanup: } +ngx_array_t * +ngx_ssl_preserve_passwords(ngx_conf_t *cf, ngx_array_t *passwords) +{ + ngx_str_t *opwd, *pwd; + ngx_uint_t i; + ngx_array_t *pwds; + ngx_pool_cleanup_t *cln; + static ngx_array_t empty_passwords; + + if (passwords == NULL) { + + /* + * If there are no passwords, an empty array is used + * to make sure OpenSSL's default password callback + * won't block on reading from stdin. + */ + + return &empty_passwords; + } + + /* + * Passwords are normally allocated from the temporary pool + * and cleared after parsing configuration. To be used at + * runtime they have to be copied to the configuration pool. + */ + + pwds = ngx_array_create(cf->pool, passwords->nelts, sizeof(ngx_str_t)); + if (pwds == NULL) { + return NULL; + } + + cln = ngx_pool_cleanup_add(cf->pool, 0); + if (cln == NULL) { + return NULL; + } + + cln->handler = ngx_ssl_passwords_cleanup; + cln->data = pwds; + + opwd = passwords->elts; + + for (i = 0; i < passwords->nelts; i++) { + + pwd = ngx_array_push(pwds); + if (pwd == NULL) { + return NULL; + } + + pwd->len = opwd[i].len; + pwd->data = ngx_pnalloc(cf->pool, pwd->len); + + if (pwd->data == NULL) { + pwds->nelts--; + return NULL; + } + + ngx_memcpy(pwd->data, opwd[i].data, opwd[i].len); + } + + return pwds; +} + + static void ngx_ssl_passwords_cleanup(void *data) { diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h --- a/src/event/ngx_event_openssl.h +++ b/src/event/ngx_event_openssl.h @@ -183,6 +183,8 @@ ngx_int_t ngx_ssl_stapling_resolver(ngx_ RSA *ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t *ssl_conn, int is_export, int key_length); ngx_array_t *ngx_ssl_read_password_file(ngx_conf_t *cf, ngx_str_t *file); +ngx_array_t *ngx_ssl_preserve_passwords(ngx_conf_t *cf, + ngx_array_t *passwords); ngx_int_t ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file); ngx_int_t ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name); ngx_int_t ngx_ssl_early_data(ngx_conf_t *cf, ngx_ssl_t *ssl, diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -935,6 +935,11 @@ found: } } + conf->passwords = ngx_ssl_preserve_passwords(cf, conf->passwords); + if (conf->passwords == NULL) { + return NGX_ERROR; + } + return NGX_OK; } diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -995,7 +995,8 @@ ngx_http_ssl_certificate(ngx_ssl_conn_t ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "ssl key: \"%s\"", key.data); - if (ngx_ssl_connection_certificate(c, r->pool, &cert, &key, NULL) + if (ngx_ssl_connection_certificate(c, r->pool, &cert, &key, + sscf->passwords) != NGX_OK) { goto failed; From mdounin at mdounin.ru Mon Feb 25 13:49:45 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 25 Feb 2019 13:49:45 +0000 Subject: [nginx] SSL: dynamic certificate loading in the stream module. Message-ID: details: https://hg.nginx.org/nginx/rev/e970de27966a branches: changeset: 7464:e970de27966a user: Maxim Dounin date: Mon Feb 25 16:42:43 2019 +0300 description: SSL: dynamic certificate loading in the stream module. diffstat: src/stream/ngx_stream_ssl_module.c | 180 ++++++++++++++++++++++++++++++++++++- src/stream/ngx_stream_ssl_module.h | 3 + 2 files changed, 179 insertions(+), 4 deletions(-) diffs (241 lines): diff --git a/src/stream/ngx_stream_ssl_module.c b/src/stream/ngx_stream_ssl_module.c --- a/src/stream/ngx_stream_ssl_module.c +++ b/src/stream/ngx_stream_ssl_module.c @@ -22,6 +22,9 @@ static ngx_int_t ngx_stream_ssl_handler( static ngx_int_t ngx_stream_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c); static void ngx_stream_ssl_handshake_handler(ngx_connection_t *c); +#ifdef SSL_R_CERT_CB_ERROR +static int ngx_stream_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg); +#endif static ngx_int_t ngx_stream_ssl_static_variable(ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_stream_ssl_variable(ngx_stream_session_t *s, @@ -32,6 +35,9 @@ static void *ngx_stream_ssl_create_conf( static char *ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child); +static ngx_int_t ngx_stream_ssl_compile_certificates(ngx_conf_t *cf, + ngx_stream_ssl_conf_t *conf); + static char *ngx_stream_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_stream_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, @@ -408,6 +414,62 @@ ngx_stream_ssl_handshake_handler(ngx_con } +#ifdef SSL_R_CERT_CB_ERROR + +int +ngx_stream_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg) +{ + ngx_str_t cert, key; + ngx_uint_t i, nelts; + ngx_connection_t *c; + ngx_stream_session_t *s; + ngx_stream_ssl_conf_t *sslcf; + ngx_stream_complex_value_t *certs, *keys; + + c = ngx_ssl_get_connection(ssl_conn); + + if (c->ssl->handshaked) { + return 0; + } + + s = c->data; + + sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module); + + nelts = sslcf->certificate_values->nelts; + certs = sslcf->certificate_values->elts; + keys = sslcf->certificate_key_values->elts; + + for (i = 0; i < nelts; i++) { + + if (ngx_stream_complex_value(s, &certs[i], &cert) != NGX_OK) { + return 0; + } + + ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, + "ssl cert: \"%s\"", cert.data); + + if (ngx_stream_complex_value(s, &keys[i], &key) != NGX_OK) { + return 0; + } + + ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, + "ssl key: \"%s\"", key.data); + + if (ngx_ssl_connection_certificate(c, c->pool, &cert, &key, + sslcf->passwords) + != NGX_OK) + { + return 0; + } + } + + return 1; +} + +#endif + + static ngx_int_t ngx_stream_ssl_static_variable(ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data) @@ -505,6 +567,7 @@ ngx_stream_ssl_create_conf(ngx_conf_t *c * * scf->listen = 0; * scf->protocols = 0; + * scf->certificate_values = NULL; * scf->dhparam = { 0, NULL }; * scf->ecdh_curve = { 0, NULL }; * scf->client_certificate = { 0, NULL }; @@ -619,13 +682,38 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf cln->handler = ngx_ssl_cleanup_ctx; cln->data = &conf->ssl; - if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates, - conf->certificate_keys, conf->passwords) - != NGX_OK) - { + if (ngx_stream_ssl_compile_certificates(cf, conf) != NGX_OK) { return NGX_CONF_ERROR; } + if (conf->certificate_values) { + +#ifdef SSL_R_CERT_CB_ERROR + + /* install callback to lookup certificates */ + + SSL_CTX_set_cert_cb(conf->ssl.ctx, ngx_stream_ssl_certificate, NULL); + +#else + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "variables in " + "\"ssl_certificate\" and \"ssl_certificate_key\" " + "directives are not supported on this platform"); + return NGX_CONF_ERROR; +#endif + + } else { + + /* configure certificates */ + + if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates, + conf->certificate_keys, conf->passwords) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + } + if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers, conf->prefer_server_ciphers) != NGX_OK) @@ -707,6 +795,90 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf } +static ngx_int_t +ngx_stream_ssl_compile_certificates(ngx_conf_t *cf, + ngx_stream_ssl_conf_t *conf) +{ + ngx_str_t *cert, *key; + ngx_uint_t i, nelts; + ngx_stream_complex_value_t *cv; + ngx_stream_compile_complex_value_t ccv; + + cert = conf->certificates->elts; + key = conf->certificate_keys->elts; + nelts = conf->certificates->nelts; + + for (i = 0; i < nelts; i++) { + + if (ngx_stream_script_variables_count(&cert[i])) { + goto found; + } + + if (ngx_stream_script_variables_count(&key[i])) { + goto found; + } + } + + return NGX_OK; + +found: + + conf->certificate_values = ngx_array_create(cf->pool, nelts, + sizeof(ngx_stream_complex_value_t)); + if (conf->certificate_values == NULL) { + return NGX_ERROR; + } + + conf->certificate_key_values = ngx_array_create(cf->pool, nelts, + sizeof(ngx_stream_complex_value_t)); + if (conf->certificate_key_values == NULL) { + return NGX_ERROR; + } + + for (i = 0; i < nelts; i++) { + + cv = ngx_array_push(conf->certificate_values); + if (cv == NULL) { + return NGX_ERROR; + } + + ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &cert[i]; + ccv.complex_value = cv; + ccv.zero = 1; + + if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) { + return NGX_ERROR; + } + + cv = ngx_array_push(conf->certificate_key_values); + if (cv == NULL) { + return NGX_ERROR; + } + + ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &key[i]; + ccv.complex_value = cv; + ccv.zero = 1; + + if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) { + return NGX_ERROR; + } + } + + conf->passwords = ngx_ssl_preserve_passwords(cf, conf->passwords); + if (conf->passwords == NULL) { + return NGX_ERROR; + } + + return NGX_OK; +} + + static char * ngx_stream_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { diff --git a/src/stream/ngx_stream_ssl_module.h b/src/stream/ngx_stream_ssl_module.h --- a/src/stream/ngx_stream_ssl_module.h +++ b/src/stream/ngx_stream_ssl_module.h @@ -34,6 +34,9 @@ typedef struct { ngx_array_t *certificates; ngx_array_t *certificate_keys; + ngx_array_t *certificate_values; + ngx_array_t *certificate_key_values; + ngx_str_t dhparam; ngx_str_t ecdh_curve; ngx_str_t client_certificate; From mdounin at mdounin.ru Mon Feb 25 13:49:47 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 25 Feb 2019 13:49:47 +0000 Subject: [nginx] SSL: adjusted session id context with dynamic certificates. Message-ID: details: https://hg.nginx.org/nginx/rev/6708bec13757 branches: changeset: 7465:6708bec13757 user: Maxim Dounin date: Mon Feb 25 16:42:54 2019 +0300 description: SSL: adjusted session id context with dynamic certificates. Dynamic certificates re-introduce problem with incorrect session reuse (AKA "virtual host confusion", CVE-2014-3616), since there are no server certificates to generate session id context from. To prevent this, session id context is now generated from ssl_certificate directives as specified in the configuration. This approach prevents incorrect session reuse in most cases, while still allowing sharing sessions across multiple machines with ssl_session_ticket_key set as long as configurations are identical. diffstat: src/event/ngx_event_openssl.c | 30 ++++++++++++++++++++++++++---- src/event/ngx_event_openssl.h | 3 ++- src/http/modules/ngx_http_ssl_module.c | 2 +- src/mail/ngx_mail_ssl_module.c | 2 +- src/stream/ngx_stream_ssl_module.c | 2 +- 5 files changed, 31 insertions(+), 8 deletions(-) diffs (119 lines): diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -54,7 +54,7 @@ static void ngx_ssl_connection_error(ngx static void ngx_ssl_clear_error(ngx_log_t *log); static ngx_int_t ngx_ssl_session_id_context(ngx_ssl_t *ssl, - ngx_str_t *sess_ctx); + ngx_str_t *sess_ctx, ngx_array_t *certificates); static int ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess); static ngx_ssl_session_t *ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, @@ -3013,13 +3013,14 @@ ngx_ssl_error(ngx_uint_t level, ngx_log_ ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, - ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout) + ngx_array_t *certificates, ssize_t builtin_session_cache, + ngx_shm_zone_t *shm_zone, time_t timeout) { long cache_mode; SSL_CTX_set_timeout(ssl->ctx, (long) timeout); - if (ngx_ssl_session_id_context(ssl, sess_ctx) != NGX_OK) { + if (ngx_ssl_session_id_context(ssl, sess_ctx, certificates) != NGX_OK) { return NGX_ERROR; } @@ -3085,11 +3086,14 @@ ngx_ssl_session_cache(ngx_ssl_t *ssl, ng static ngx_int_t -ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx) +ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, + ngx_array_t *certificates) { int n, i; X509 *cert; X509_NAME *name; + ngx_str_t *certs; + ngx_uint_t k; EVP_MD_CTX *md; unsigned int len; STACK_OF(X509_NAME) *list; @@ -3134,6 +3138,24 @@ ngx_ssl_session_id_context(ngx_ssl_t *ss } } + if (SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index) == NULL) { + + /* + * If certificates are loaded dynamically, we use certificate + * names as specified in the configuration (with variables). + */ + + certs = certificates->elts; + for (k = 0; k < certificates->nelts; k++) { + + if (EVP_DigestUpdate(md, certs[k].data, certs[k].len) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "EVP_DigestUpdate() failed"); + goto failed; + } + } + } + list = SSL_CTX_get_client_CA_list(ssl->ctx); if (list != NULL) { diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h --- a/src/event/ngx_event_openssl.h +++ b/src/event/ngx_event_openssl.h @@ -192,7 +192,8 @@ ngx_int_t ngx_ssl_early_data(ngx_conf_t ngx_int_t ngx_ssl_client_session_cache(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_uint_t enable); ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, - ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout); + ngx_array_t *certificates, ssize_t builtin_session_cache, + ngx_shm_zone_t *shm_zone, time_t timeout); ngx_int_t ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths); ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data); diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -817,7 +817,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * } if (ngx_ssl_session_cache(&conf->ssl, &ngx_http_ssl_sess_id_ctx, - conf->builtin_session_cache, + conf->certificates, conf->builtin_session_cache, conf->shm_zone, conf->session_timeout) != NGX_OK) { diff --git a/src/mail/ngx_mail_ssl_module.c b/src/mail/ngx_mail_ssl_module.c --- a/src/mail/ngx_mail_ssl_module.c +++ b/src/mail/ngx_mail_ssl_module.c @@ -435,7 +435,7 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, } if (ngx_ssl_session_cache(&conf->ssl, &ngx_mail_ssl_sess_id_ctx, - conf->builtin_session_cache, + conf->certificates, conf->builtin_session_cache, conf->shm_zone, conf->session_timeout) != NGX_OK) { diff --git a/src/stream/ngx_stream_ssl_module.c b/src/stream/ngx_stream_ssl_module.c --- a/src/stream/ngx_stream_ssl_module.c +++ b/src/stream/ngx_stream_ssl_module.c @@ -766,7 +766,7 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf } if (ngx_ssl_session_cache(&conf->ssl, &ngx_stream_ssl_sess_id_ctx, - conf->builtin_session_cache, + conf->certificates, conf->builtin_session_cache, conf->shm_zone, conf->session_timeout) != NGX_OK) { From xeioex at nginx.com Mon Feb 25 16:01:15 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 25 Feb 2019 16:01:15 +0000 Subject: [njs] HTTP: setting exception if memory allocation fails. Message-ID: details: https://hg.nginx.org/njs/rev/7d0b45c56edf branches: changeset: 798:7d0b45c56edf user: Dmitry Volyntsev date: Mon Feb 25 19:00:54 2019 +0300 description: HTTP: setting exception if memory allocation fails. diffstat: nginx/ngx_http_js_module.c | 14 +++++++++++--- 1 files changed, 11 insertions(+), 3 deletions(-) diffs (55 lines): diff -r 1718603aae6a -r 7d0b45c56edf nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Sat Feb 23 04:21:44 2019 +0300 +++ b/nginx/ngx_http_js_module.c Mon Feb 25 19:00:54 2019 +0300 @@ -1657,6 +1657,7 @@ ngx_http_js_ext_set_variable(njs_vm_t *v if (v->set_handler != NULL) { vv = ngx_pcalloc(r->pool, sizeof(ngx_http_variable_value_t)); if (vv == NULL) { + njs_vm_error(vm, "internal error"); return NJS_ERROR; } @@ -1682,6 +1683,7 @@ ngx_http_js_ext_set_variable(njs_vm_t *v vv->data = ngx_pnalloc(r->pool, value->length); if (vv->data == NULL) { + njs_vm_error(vm, "internal error"); return NJS_ERROR; } @@ -1864,19 +1866,19 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, if (has_body) { rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); if (rb == NULL) { - return NJS_ERROR; + goto memory_error; } rb->bufs = ngx_alloc_chain_link(r->pool); if (rb->bufs == NULL) { - return NJS_ERROR; + goto memory_error; } rb->bufs->next = NULL; rb->bufs->buf = ngx_calloc_buf(r->pool); if (rb->bufs->buf == NULL) { - return NJS_ERROR; + goto memory_error; } rb->bufs->buf->memory = 1; @@ -1891,6 +1893,12 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, } return NJS_OK; + +memory_error: + + njs_vm_error(ctx->vm, "internal error"); + + return NJS_ERROR; } From xeioex at nginx.com Mon Feb 25 16:01:16 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 25 Feb 2019 16:01:16 +0000 Subject: [njs] Added labels support. Message-ID: details: https://hg.nginx.org/njs/rev/032827ab80dc branches: changeset: 799:032827ab80dc user: Dmitry Volyntsev date: Mon Feb 25 19:00:55 2019 +0300 description: Added labels support. diffstat: njs/njs_generator.c | 394 ++++++++++++++++++++++++++++++++++------------ njs/njs_lexer.c | 26 +++ njs/njs_parser.c | 140 +++++++++++----- njs/njs_parser.h | 4 + njs/njs_variable.c | 92 ++++++++++ njs/njs_variable.h | 6 + njs/test/njs_unit_test.c | 265 +++++++++++++++++++++++++++++++ 7 files changed, 776 insertions(+), 151 deletions(-) diffs (truncated from 1383 to 1000 lines): diff -r 7d0b45c56edf -r 032827ab80dc njs/njs_generator.c --- a/njs/njs_generator.c Mon Feb 25 19:00:54 2019 +0300 +++ b/njs/njs_generator.c Mon Feb 25 19:00:55 2019 +0300 @@ -20,29 +20,35 @@ struct njs_generator_patch_s { */ njs_ret_t jump_offset; njs_generator_patch_t *next; + + nxt_str_t label; }; typedef enum { - NJS_GENERATOR_BLOCK = 1, - NJS_GENERATOR_LOOP = 2, - NJS_GENERATOR_SWITCH = 4, + NJS_GENERATOR_LOOP = 1, + NJS_GENERATOR_SWITCH = 2, + NJS_GENERATOR_BLOCK = 4, NJS_GENERATOR_TRY = 8, - -#define NJS_GENERATOR_ALL (NJS_GENERATOR_BLOCK \ - | NJS_GENERATOR_LOOP \ - | NJS_GENERATOR_SWITCH \ - | NJS_GENERATOR_TRY) +#define NJS_GENERATOR_ALL (NJS_GENERATOR_LOOP | NJS_GENERATOR_SWITCH) } njs_generator_block_type_t; struct njs_generator_block_s { - njs_generator_block_type_t type; /* 2 bits */ + njs_generator_block_type_t type; /* 4 bits */ nxt_str_t label; + + /* list of "continue" instruction offsets to be patched. */ njs_generator_patch_t *continuation; + /* + * list of "return" from try-catch block and "break" + * instruction offsets to be patched. + */ njs_generator_patch_t *exit; + njs_generator_block_t *next; + /* exit value index, used only for NJS_GENERATOR_TRY blocks. */ njs_index_t index; }; @@ -78,16 +84,21 @@ static nxt_int_t njs_generate_for_in_sta static nxt_noinline nxt_int_t njs_generate_start_block(njs_vm_t *vm, njs_generator_t *generator, njs_generator_block_type_t type, const nxt_str_t *label); +static njs_generator_block_t *njs_generate_lookup_block( + njs_generator_block_t *block, uint32_t mask, const nxt_str_t *label); static njs_generator_block_t *njs_generate_find_block( - njs_generator_block_t *block, uint32_t mask); -static nxt_int_t njs_generate_make_continuation_patch(njs_vm_t *vm, - njs_generator_t *generator, njs_generator_block_t *block, njs_ret_t offset); + njs_generator_block_t *block, uint32_t mask, const nxt_str_t *label); +static njs_generator_patch_t *njs_generate_make_continuation_patch(njs_vm_t *vm, + njs_generator_block_t *block, const nxt_str_t *label, njs_ret_t offset); static nxt_noinline void njs_generate_patch_block(njs_vm_t *vm, njs_generator_t *generator, njs_generator_patch_t *list); -static nxt_int_t njs_generate_make_exit_patch(njs_vm_t *vm, - njs_generator_t *generator, njs_generator_block_t *block, njs_ret_t offset); +static njs_generator_patch_t *njs_generate_make_exit_patch(njs_vm_t *vm, + njs_generator_block_t *block, const nxt_str_t *label, njs_ret_t offset); static nxt_noinline void njs_generate_patch_block_exit(njs_vm_t *vm, njs_generator_t *generator); +static const nxt_str_t *njs_generate_jump_destination(njs_vm_t *vm, + njs_generator_block_t *block, const char *inst_type, uint32_t mask, + const nxt_str_t *label1, const nxt_str_t *label2); static nxt_int_t njs_generate_continue_statement(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node); static nxt_int_t njs_generate_break_statement(njs_vm_t *vm, @@ -208,7 +219,10 @@ static nxt_int_t njs_generate_function_d njs_parser_node_error(vm, node, NJS_OBJECT_SYNTAX_ERROR, fmt, ##__VA_ARGS__) -static const nxt_str_t no_label = { 0, NULL }; +static const nxt_str_t no_label = nxt_string(""); +static const nxt_str_t return_label = nxt_string("@return"); +/* GCC and Clang complain about NULL argument passed to memcmp(). */ +static const nxt_str_t undef_label = { 0xffffffff, (u_char *) "" }; static nxt_int_t @@ -432,7 +446,7 @@ njs_generator(njs_vm_t *vm, njs_generato default: nxt_thread_log_debug("unknown token: %d", node->token); - njs_syntax_error(vm, "unknown token"); + njs_internal_error(vm, "Generator failed: unknown token"); return NXT_ERROR; } @@ -845,7 +859,7 @@ njs_generate_switch_statement(njs_vm_t * } ret = njs_generate_start_block(vm, generator, NJS_GENERATOR_SWITCH, - &no_label); + &swtch->label); if (nxt_slow_path(ret != NXT_OK)) { return ret; } @@ -886,6 +900,7 @@ njs_generate_switch_statement(njs_vm_t * patch->jump_offset = njs_code_offset(generator, equal) + offsetof(njs_vmcode_equal_jump_t, offset); + patch->label = no_label; *last = patch; last = &patch->next; @@ -970,7 +985,7 @@ njs_generate_while_statement(njs_vm_t *v /* The loop body. */ ret = njs_generate_start_block(vm, generator, NJS_GENERATOR_LOOP, - &no_label); + &node->label); if (nxt_slow_path(ret != NXT_OK)) { return ret; } @@ -1020,7 +1035,7 @@ njs_generate_do_while_statement(njs_vm_t /* The loop body. */ ret = njs_generate_start_block(vm, generator, NJS_GENERATOR_LOOP, - &no_label); + &node->label); if (nxt_slow_path(ret != NXT_OK)) { return ret; } @@ -1067,7 +1082,7 @@ njs_generate_for_statement(njs_vm_t *vm, njs_vmcode_cond_jump_t *cond_jump; ret = njs_generate_start_block(vm, generator, NJS_GENERATOR_LOOP, - &no_label); + &node->label); if (nxt_slow_path(ret != NXT_OK)) { return ret; } @@ -1178,7 +1193,7 @@ njs_generate_for_in_statement(njs_vm_t * njs_vmcode_prop_foreach_t *prop_foreach; ret = njs_generate_start_block(vm, generator, NJS_GENERATOR_LOOP, - &no_label); + &node->label); if (nxt_slow_path(ret != NXT_OK)) { return ret; } @@ -1278,10 +1293,18 @@ njs_generate_start_block(njs_vm_t *vm, n static njs_generator_block_t * -njs_generate_find_block(njs_generator_block_t *block, uint32_t mask) +njs_generate_lookup_block(njs_generator_block_t *block, uint32_t mask, + const nxt_str_t *label) { + if (nxt_strstr_eq(label, &return_label)) { + mask = NJS_GENERATOR_TRY; + label = &no_label; + } + while (block != NULL) { - if (block->type & mask) { + if ((block->type & mask) != 0 + && (label->length == 0 || nxt_strstr_eq(&block->label, label))) + { return block; } @@ -1292,16 +1315,59 @@ njs_generate_find_block(njs_generator_bl } -static nxt_int_t -njs_generate_make_continuation_patch(njs_vm_t *vm, njs_generator_t *generator, - njs_generator_block_t *block, njs_ret_t offset) +static njs_generator_block_t * +njs_generate_find_block(njs_generator_block_t *block, uint32_t mask, + const nxt_str_t *label) +{ + njs_generator_block_t *dest_block; + + /* + * ES5.1: 12.8 The break Statement + * "break" without a label is valid only from within + * loop or switch statement. + */ + if ((mask & NJS_GENERATOR_ALL) == NJS_GENERATOR_ALL + && !nxt_strstr_eq(label, &no_label)) + { + mask |= NJS_GENERATOR_BLOCK; + } + + dest_block = njs_generate_lookup_block(block, mask, label); + + if (dest_block != NULL) { + + /* + * Looking for intermediate try-catch blocks. Before jumping to + * the destination finally blocks have to be executed. + */ + + while (block != NULL) { + if (block->type & NJS_GENERATOR_TRY) { + return block; + } + + if (block == dest_block) { + return block; + } + + block = block->next; + } + } + + return dest_block; +} + + +static njs_generator_patch_t * +njs_generate_make_continuation_patch(njs_vm_t *vm, njs_generator_block_t *block, + const nxt_str_t *label, njs_ret_t offset) { njs_generator_patch_t *patch; patch = nxt_mp_alloc(vm->mem_pool, sizeof(njs_generator_patch_t)); if (nxt_slow_path(patch == NULL)) { njs_memory_error(vm); - return NXT_ERROR; + return NULL; } patch->next = block->continuation; @@ -1309,7 +1375,9 @@ njs_generate_make_continuation_patch(njs patch->jump_offset = offset; - return NXT_OK; + patch->label = *label; + + return patch; } @@ -1328,16 +1396,16 @@ njs_generate_patch_block(njs_vm_t *vm, n } -static nxt_int_t -njs_generate_make_exit_patch(njs_vm_t *vm, njs_generator_t *generator, - njs_generator_block_t *block, njs_ret_t offset) +static njs_generator_patch_t * +njs_generate_make_exit_patch(njs_vm_t *vm, njs_generator_block_t *block, + const nxt_str_t *label, njs_ret_t offset) { njs_generator_patch_t *patch; patch = nxt_mp_alloc(vm->mem_pool, sizeof(njs_generator_patch_t)); if (nxt_slow_path(patch == NULL)) { njs_memory_error(vm); - return NXT_ERROR; + return NULL; } patch->next = block->exit; @@ -1345,7 +1413,9 @@ njs_generate_make_exit_patch(njs_vm_t *v patch->jump_offset = offset; - return NXT_OK; + patch->label = *label; + + return patch; } @@ -1363,43 +1433,79 @@ njs_generate_patch_block_exit(njs_vm_t * } +/* + * TODO: support multiple destination points from within try-catch block. + */ +static const nxt_str_t * +njs_generate_jump_destination(njs_vm_t *vm, njs_generator_block_t *block, + const char *inst_type, uint32_t mask, const nxt_str_t *label1, + const nxt_str_t *label2) +{ + njs_generator_block_t *block1, *block2; + + if (label1->length == undef_label.length) { + return label2; + } + + if (label2->length == undef_label.length) { + return label1; + } + + block1 = njs_generate_lookup_block(block, mask, label1); + block2 = njs_generate_lookup_block(block, mask, label2); + + if (block1 != block2) { + njs_internal_error(vm, "%s instructions with different labels " + "(\"%V\" vs \"%V\") " + "from try-catch block are not supported", inst_type, + label1, label2); + + return NULL; + } + + return label1; +} + + static nxt_int_t njs_generate_continue_statement(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node) { + const nxt_str_t *label, *dest; njs_vmcode_jump_t *jump; njs_generator_patch_t *patch; njs_generator_block_t *block; - block = njs_generate_find_block(generator->block, - NJS_GENERATOR_LOOP | NJS_GENERATOR_TRY); + label = &node->label; + + block = njs_generate_find_block(generator->block, NJS_GENERATOR_LOOP, + label); if (nxt_slow_path(block == NULL)) { goto syntax_error; } - if (block->type == NJS_GENERATOR_TRY - && njs_generate_find_block(block->next, NJS_GENERATOR_LOOP) == NULL) - { - goto syntax_error; + if (block->type == NJS_GENERATOR_TRY && block->continuation != NULL) { + dest = njs_generate_jump_destination(vm, block->next, "continue", + NJS_GENERATOR_LOOP, + &block->continuation->label, + label); + if (nxt_slow_path(dest == NULL)) { + return NXT_ERROR; + } } - /* TODO: LABEL */ - - patch = nxt_mp_alloc(vm->mem_pool, sizeof(njs_generator_patch_t)); - - if (nxt_fast_path(patch != NULL)) { - patch->next = block->continuation; - block->continuation = patch; - - njs_generate_code(generator, njs_vmcode_jump_t, jump); - jump->code.operation = njs_vmcode_jump; - jump->code.operands = NJS_VMCODE_NO_OPERAND; - jump->code.retval = NJS_VMCODE_NO_RETVAL; - jump->offset = offsetof(njs_vmcode_jump_t, offset); - - patch->jump_offset = njs_code_offset(generator, jump) - + offsetof(njs_vmcode_jump_t, offset); + njs_generate_code(generator, njs_vmcode_jump_t, jump); + jump->code.operation = njs_vmcode_jump; + jump->code.operands = NJS_VMCODE_NO_OPERAND; + jump->code.retval = NJS_VMCODE_NO_RETVAL; + jump->offset = offsetof(njs_vmcode_jump_t, offset); + + patch = njs_generate_make_continuation_patch(vm, block, label, + njs_code_offset(generator, jump) + + offsetof(njs_vmcode_jump_t, offset)); + if (nxt_slow_path(patch == NULL)) { + return NXT_ERROR; } return NXT_OK; @@ -1416,38 +1522,38 @@ static nxt_int_t njs_generate_break_statement(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node) { + const nxt_str_t *label, *dest; njs_vmcode_jump_t *jump; njs_generator_patch_t *patch; njs_generator_block_t *block; - block = njs_generate_find_block(generator->block, NJS_GENERATOR_ALL); - + label = &node->label; + + block = njs_generate_find_block(generator->block, NJS_GENERATOR_ALL, label); if (nxt_slow_path(block == NULL)) { goto syntax_error; } - if (block->type == NJS_GENERATOR_TRY - && njs_generate_find_block(block->next, NJS_GENERATOR_ALL) == NULL) - { - goto syntax_error; + if (block->type == NJS_GENERATOR_TRY && block->exit != NULL) { + dest = njs_generate_jump_destination(vm, block->next, "break/return", + NJS_GENERATOR_ALL, + &block->exit->label, label); + if (nxt_slow_path(dest == NULL)) { + return NXT_ERROR; + } } - /* TODO: LABEL: loop and switch may have label, block must have label. */ - - patch = nxt_mp_alloc(vm->mem_pool, sizeof(njs_generator_patch_t)); - - if (nxt_fast_path(patch != NULL)) { - patch->next = block->exit; - block->exit = patch; - - njs_generate_code(generator, njs_vmcode_jump_t, jump); - jump->code.operation = njs_vmcode_jump; - jump->code.operands = NJS_VMCODE_NO_OPERAND; - jump->code.retval = NJS_VMCODE_NO_RETVAL; - jump->offset = offsetof(njs_vmcode_jump_t, offset); - - patch->jump_offset = njs_code_offset(generator, jump) - + offsetof(njs_vmcode_jump_t, offset); + njs_generate_code(generator, njs_vmcode_jump_t, jump); + jump->code.operation = njs_vmcode_jump; + jump->code.operands = NJS_VMCODE_NO_OPERAND; + jump->code.retval = NJS_VMCODE_NO_RETVAL; + jump->offset = offsetof(njs_vmcode_jump_t, offset); + + patch = njs_generate_make_exit_patch(vm, block, label, + njs_code_offset(generator, jump) + + offsetof(njs_vmcode_jump_t, offset)); + if (nxt_slow_path(patch == NULL)) { + return NXT_ERROR; } return NXT_OK; @@ -1483,7 +1589,7 @@ njs_generate_block_statement(njs_vm_t *v nxt_int_t ret; ret = njs_generate_start_block(vm, generator, NJS_GENERATOR_BLOCK, - &no_label); + &node->label); if (nxt_slow_path(ret != NXT_OK)) { return ret; } @@ -2437,9 +2543,10 @@ njs_generate_return_statement(njs_vm_t * { nxt_int_t ret; njs_index_t index; + const nxt_str_t *dest; njs_vmcode_return_t *code; njs_generator_patch_t *patch; - njs_generator_block_t *block; + njs_generator_block_t *block, *immediate, *top; njs_vmcode_try_return_t *try_return; ret = njs_generator(vm, generator, node->right); @@ -2452,13 +2559,13 @@ njs_generate_return_statement(njs_vm_t * index = node->right->index; } else { - index = njs_value_index(vm, &njs_value_void, - generator->runtime); + index = njs_value_index(vm, &njs_value_void, generator->runtime); } - block = njs_generate_find_block(generator->block, NJS_GENERATOR_TRY); - - if (nxt_fast_path(block == NULL)) { + immediate = njs_generate_lookup_block(generator->block, NJS_GENERATOR_TRY, + &no_label); + + if (nxt_fast_path(immediate == NULL)) { njs_generate_code(generator, njs_vmcode_return_t, code); code->code.operation = njs_vmcode_return; code->code.operands = NJS_VMCODE_1OPERAND; @@ -2470,24 +2577,43 @@ njs_generate_return_statement(njs_vm_t * return NXT_OK; } - patch = nxt_mp_alloc(vm->mem_pool, sizeof(njs_generator_patch_t)); - if (nxt_slow_path(patch == NULL)) { - return NXT_ERROR; + if (immediate->type == NJS_GENERATOR_TRY && immediate->exit != NULL) { + dest = njs_generate_jump_destination(vm, immediate->next, + "break/return", + NJS_GENERATOR_ALL, + &immediate->exit->label, + &return_label); + if (nxt_slow_path(dest == NULL)) { + return NXT_ERROR; + } } - patch->next = block->exit; - block->exit = patch; + top = immediate; + block = immediate->next; + + while (block != NULL) { + if (block->type & NJS_GENERATOR_TRY) { + top = block; + } + + block = block->next; + } njs_generate_code(generator, njs_vmcode_try_return_t, try_return); try_return->code.operation = njs_vmcode_try_return; try_return->code.operands = NJS_VMCODE_2OPERANDS; try_return->code.retval = NJS_VMCODE_RETVAL; try_return->retval = index; - try_return->save = block->index; - + try_return->save = top->index; try_return->offset = offsetof(njs_vmcode_try_return_t, offset); - patch->jump_offset = njs_code_offset(generator, try_return) - + offsetof(njs_vmcode_try_return_t, offset); + + patch = njs_generate_make_exit_patch(vm, immediate, &return_label, + njs_code_offset(generator, try_return) + + offsetof(njs_vmcode_try_return_t, + offset)); + if (nxt_slow_path(patch == NULL)) { + return NXT_ERROR; + } return NXT_OK; } @@ -2648,9 +2774,13 @@ njs_generate_try_statement(njs_vm_t *vm, catch_end_offset; nxt_int_t ret; njs_index_t exception_index, exit_index, catch_index; + nxt_str_t try_cont_label, try_exit_label, + catch_cont_label, catch_exit_label; + const nxt_str_t *dest_label; njs_vmcode_catch_t *catch; njs_vmcode_finally_t *finally; njs_vmcode_try_end_t *try_end, *catch_end; + njs_generator_patch_t *patch; njs_generator_block_t *block, *try_block, *catch_block; njs_vmcode_try_start_t *try_start; njs_vmcode_try_trampoline_t *try_break, *try_continue; @@ -2694,6 +2824,9 @@ njs_generate_try_statement(njs_vm_t *vm, return ret; } + try_exit_label = undef_label; + try_cont_label = undef_label; + njs_generate_code(generator, njs_vmcode_try_end_t, try_end); try_end_offset = njs_code_offset(generator, try_end); try_end->code.operation = njs_vmcode_try_end; @@ -2701,6 +2834,8 @@ njs_generate_try_statement(njs_vm_t *vm, try_end->code.retval = NJS_VMCODE_NO_RETVAL; if (try_block->exit != NULL) { + try_exit_label = try_block->exit->label; + njs_generate_patch_block(vm, generator, try_block->exit); njs_generate_code(generator, njs_vmcode_try_trampoline_t, try_break); @@ -2717,6 +2852,8 @@ njs_generate_try_statement(njs_vm_t *vm, } if (try_block->continuation != NULL) { + try_cont_label = try_block->continuation->label; + njs_generate_patch_block(vm, generator, try_block->continuation); njs_generate_code(generator, njs_vmcode_try_trampoline_t, try_continue); @@ -2740,6 +2877,9 @@ njs_generate_try_statement(njs_vm_t *vm, node = node->right; + catch_exit_label = undef_label; + catch_cont_label = undef_label; + if (node->token == NJS_TOKEN_CATCH) { /* A "try/catch" case. */ @@ -2780,21 +2920,31 @@ njs_generate_try_statement(njs_vm_t *vm, * by njs_generate_continue_statement() */ block = njs_generate_find_block(generator->block, - NJS_GENERATOR_LOOP); - - njs_generate_make_continuation_patch(vm, generator, block, + NJS_GENERATOR_LOOP, + &try_cont_label); + + patch = njs_generate_make_continuation_patch(vm, block, + &try_cont_label, njs_code_offset(generator, finally) + offsetof(njs_vmcode_finally_t, continue_offset)); + if (nxt_slow_path(patch == NULL)) { + return NXT_ERROR; + } } if (try_block->exit != NULL) { block = njs_generate_find_block(generator->block, - NJS_GENERATOR_ALL); + NJS_GENERATOR_ALL, + &try_exit_label); if (block != NULL) { - njs_generate_make_exit_patch(vm, generator, block, + patch = njs_generate_make_exit_patch(vm, block, + &try_exit_label, njs_code_offset(generator, finally) + offsetof(njs_vmcode_finally_t, break_offset)); + if (nxt_slow_path(patch == NULL)) { + return NXT_ERROR; + } } } } @@ -2838,6 +2988,8 @@ njs_generate_try_statement(njs_vm_t *vm, catch_end->code.retval = NJS_VMCODE_NO_RETVAL; if (catch_block->exit != NULL) { + catch_exit_label = catch_block->exit->label; + njs_generate_patch_block(vm, generator, catch_block->exit); njs_generate_code(generator, njs_vmcode_try_trampoline_t, @@ -2855,6 +3007,8 @@ njs_generate_try_statement(njs_vm_t *vm, } if (catch_block->continuation != NULL) { + catch_cont_label = catch_block->continuation->label; + njs_generate_patch_block(vm, generator, catch_block->continuation); @@ -2923,27 +3077,57 @@ njs_generate_try_statement(njs_vm_t *vm, if (try_block->continuation != NULL || (catch_block && catch_block->continuation != NULL)) { + dest_label = njs_generate_jump_destination(vm, generator->block, + "try continue", + NJS_GENERATOR_LOOP, + &try_cont_label, + &catch_cont_label); + if (nxt_slow_path(dest_label == NULL)) { + return NXT_ERROR; + } + /* * block != NULL is checked * by njs_generate_continue_statement() */ block = njs_generate_find_block(generator->block, - NJS_GENERATOR_LOOP); - - njs_generate_make_continuation_patch(vm, generator, block, - njs_code_offset(generator, finally) - + offsetof(njs_vmcode_finally_t, continue_offset)); + NJS_GENERATOR_LOOP, dest_label); + + patch = njs_generate_make_continuation_patch(vm, block, dest_label, + njs_code_offset(generator, finally) + + offsetof(njs_vmcode_finally_t, continue_offset)); + if (nxt_slow_path(patch == NULL)) { + return NXT_ERROR; + } } if (try_block->exit != NULL || (catch_block != NULL && catch_block->exit != NULL)) { + dest_label = njs_generate_jump_destination(vm, generator->block, + "try break/return", + NJS_GENERATOR_ALL + | NJS_GENERATOR_TRY, + &try_exit_label, + &catch_exit_label); + if (nxt_slow_path(dest_label == NULL)) { + return NXT_ERROR; + } + + /* + * block can be NULL for "return" instruction in + * outermost try-catch block. + */ block = njs_generate_find_block(generator->block, - NJS_GENERATOR_ALL); + NJS_GENERATOR_ALL + | NJS_GENERATOR_TRY, dest_label); if (block != NULL) { - njs_generate_make_exit_patch(vm, generator, block, + patch = njs_generate_make_exit_patch(vm, block, dest_label, njs_code_offset(generator, finally) + offsetof(njs_vmcode_finally_t, break_offset)); + if (nxt_slow_path(patch == NULL)) { + return NXT_ERROR; + } } } } diff -r 7d0b45c56edf -r 032827ab80dc njs/njs_lexer.c --- a/njs/njs_lexer.c Mon Feb 25 19:00:54 2019 +0300 +++ b/njs/njs_lexer.c Mon Feb 25 19:00:55 2019 +0300 @@ -292,6 +292,32 @@ void njs_lexer_rollback(njs_lexer_t *lexer) { lexer->start = lexer->prev_start; + lexer->token = lexer->prev_token; +} + + +njs_token_t +njs_lexer_peek_token(njs_lexer_t *lexer) +{ + u_char *start; + njs_token_t token; + + start = lexer->start; + + while (start < lexer->end) { + token = njs_tokens[*start++]; + + switch (token) { + case NJS_TOKEN_SPACE: + case NJS_TOKEN_LINE_END: + continue; + + default: + return token; + } + } + + return NJS_TOKEN_END; } diff -r 7d0b45c56edf -r 032827ab80dc njs/njs_parser.c --- a/njs/njs_parser.c Mon Feb 25 19:00:54 2019 +0300 +++ b/njs/njs_parser.c Mon Feb 25 19:00:55 2019 +0300 @@ -21,6 +21,8 @@ static njs_token_t njs_parser_block_stat njs_parser_t *parser); static njs_token_t njs_parser_block(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token); +static njs_token_t njs_parser_labelled_statement(njs_vm_t *vm, + njs_parser_t *parser); static njs_token_t njs_parser_function_declaration(njs_vm_t *vm, njs_parser_t *parser); static njs_token_t njs_parser_function_lambda(njs_vm_t *vm, @@ -42,10 +44,8 @@ static njs_token_t njs_parser_for_var_in njs_parser_t *parser, njs_parser_node_t *name); static njs_token_t njs_parser_for_in_statement(njs_vm_t *vm, njs_parser_t *parser, nxt_str_t *name, njs_token_t token); -static njs_token_t njs_parser_continue_statement(njs_vm_t *vm, - njs_parser_t *parser); -static njs_token_t njs_parser_break_statement(njs_vm_t *vm, - njs_parser_t *parser); +static njs_token_t njs_parser_brk_statement(njs_vm_t *vm, + njs_parser_t *parser, njs_token_t token); static njs_token_t njs_parser_try_statement(njs_vm_t *vm, njs_parser_t *parser); static njs_token_t njs_parser_try_block(njs_vm_t *vm, njs_parser_t *parser); static njs_token_t njs_parser_throw_statement(njs_vm_t *vm, @@ -216,6 +216,7 @@ njs_parser_scope_begin(njs_vm_t *vm, njs scope->argument_closures = 0; nxt_queue_init(&scope->nested); + nxt_lvlhsh_init(&scope->labels); nxt_lvlhsh_init(&scope->variables); nxt_lvlhsh_init(&scope->references); @@ -354,19 +355,17 @@ njs_parser_statement(njs_vm_t *vm, njs_p default: + if (token == NJS_TOKEN_NAME + && njs_lexer_peek_token(parser->lexer) == NJS_TOKEN_COLON) + { + return njs_parser_labelled_statement(vm, parser); + } + switch (token) { case NJS_TOKEN_VAR: token = njs_parser_var_statement(vm, parser); break; - case NJS_TOKEN_CONTINUE: - token = njs_parser_continue_statement(vm, parser); - break; - - case NJS_TOKEN_BREAK: - token = njs_parser_break_statement(vm, parser); - break; - case NJS_TOKEN_RETURN: token = njs_parser_return_statement(vm, parser); break; @@ -375,6 +374,11 @@ njs_parser_statement(njs_vm_t *vm, njs_p token = njs_parser_throw_statement(vm, parser); break; + case NJS_TOKEN_CONTINUE: + case NJS_TOKEN_BREAK: + token = njs_parser_brk_statement(vm, parser, token); + break; + default: token = njs_parser_expression(vm, parser, token); break; @@ -506,6 +510,63 @@ njs_parser_variable_reference(njs_vm_t * static njs_token_t +njs_parser_labelled_statement(njs_vm_t *vm, njs_parser_t *parser) +{ + uint32_t hash; + njs_ret_t ret; + nxt_str_t name; + njs_token_t token; + njs_variable_t *label; + + name = parser->lexer->text; + hash = parser->lexer->key_hash; + + label = njs_label_find(vm, parser->scope, &name, hash); + if (nxt_slow_path(label != NULL)) { + njs_parser_syntax_error(vm, parser, "Label \"%V\" " + "has already been declared", &name); + return NJS_TOKEN_ILLEGAL; + } + + label = njs_label_add(vm, parser->scope, &name, hash); + if (nxt_slow_path(label == NULL)) { + return NJS_TOKEN_ERROR; + } + + token = njs_parser_token(parser); + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return token; + } + + token = njs_parser_match(vm, parser, token, NJS_TOKEN_COLON); + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return token; + } + + token = njs_parser_statement(vm, parser, token); + + if (nxt_fast_path(token > NJS_TOKEN_ILLEGAL)) { + + if (parser->node != NULL) { + /* The statement is not empty block or just semicolon. */ + + ret = njs_name_copy(vm, &parser->node->label, &name); + if (nxt_slow_path(ret != NXT_OK)) { + return NJS_TOKEN_ERROR; + } + + ret = njs_label_remove(vm, parser->scope, &name, hash); + if (nxt_slow_path(ret != NXT_OK)) { + return NJS_TOKEN_ERROR; + } + } + } + + return token; +} + + +static njs_token_t njs_parser_function_declaration(njs_vm_t *vm, njs_parser_t *parser) { njs_ret_t ret; @@ -1483,12 +1544,15 @@ njs_parser_for_in_statement(njs_vm_t *vm static njs_token_t -njs_parser_continue_statement(njs_vm_t *vm, njs_parser_t *parser) +njs_parser_brk_statement(njs_vm_t *vm, njs_parser_t *parser, + njs_token_t token) { - njs_token_t token; + uint32_t hash; + njs_ret_t ret; + nxt_str_t name; njs_parser_node_t *node; - node = njs_parser_node_new(vm, parser, NJS_TOKEN_CONTINUE); + node = njs_parser_node_new(vm, parser, token); if (nxt_slow_path(node == NULL)) { return NJS_TOKEN_ERROR; } @@ -1503,37 +1567,21 @@ njs_parser_continue_statement(njs_vm_t * case NJS_TOKEN_LINE_END: return njs_parser_token(parser); - case NJS_TOKEN_SEMICOLON: - case NJS_TOKEN_CLOSE_BRACE: - case NJS_TOKEN_END: - return token; - - default: - /* TODO: LABEL */ - return NJS_TOKEN_ILLEGAL; - } -} - - -static njs_token_t -njs_parser_break_statement(njs_vm_t *vm, njs_parser_t *parser) -{ - njs_token_t token; - njs_parser_node_t *node; - - node = njs_parser_node_new(vm, parser, NJS_TOKEN_BREAK); - if (nxt_slow_path(node == NULL)) { - return NJS_TOKEN_ERROR; - } - - node->token_line = parser->lexer->token_line; - parser->node = node; - - token = njs_lexer_token(parser->lexer); - - switch (token) { - - case NJS_TOKEN_LINE_END: + case NJS_TOKEN_NAME: + name = parser->lexer->text; + hash = parser->lexer->key_hash; + + if (njs_label_find(vm, parser->scope, &name, hash) == NULL) { + njs_parser_syntax_error(vm, parser, "Undefined label \"%V\"", + &name); + return NJS_TOKEN_ILLEGAL; + } + + ret = njs_name_copy(vm, &parser->node->label, &parser->lexer->text); + if (nxt_slow_path(ret != NXT_OK)) { + return NJS_TOKEN_ERROR; + } + return njs_parser_token(parser); case NJS_TOKEN_SEMICOLON: diff -r 7d0b45c56edf -r 032827ab80dc njs/njs_parser.h --- a/njs/njs_parser.h Mon Feb 25 19:00:54 2019 +0300 +++ b/njs/njs_parser.h Mon Feb 25 19:00:55 2019 +0300 @@ -243,6 +243,7 @@ struct njs_parser_scope_s { nxt_queue_t nested; njs_parser_scope_t *parent; + nxt_lvlhsh_t labels; nxt_lvlhsh_t variables; nxt_lvlhsh_t references; @@ -274,6 +275,8 @@ struct njs_parser_node_s { njs_parser_node_t *object; } u; + nxt_str_t label; + njs_index_t index; /* @@ -306,6 +309,7 @@ typedef struct { njs_token_t njs_lexer_token(njs_lexer_t *lexer); void njs_lexer_rollback(njs_lexer_t *lexer); +njs_token_t njs_lexer_peek_token(njs_lexer_t *lexer); nxt_int_t njs_lexer_keywords_init(nxt_mp_t *mcp, nxt_lvlhsh_t *hash); njs_token_t njs_lexer_keyword(njs_lexer_t *lexer); diff -r 7d0b45c56edf -r 032827ab80dc njs/njs_variable.c --- a/njs/njs_variable.c Mon Feb 25 19:00:54 2019 +0300 +++ b/njs/njs_variable.c Mon Feb 25 19:00:55 2019 +0300 @@ -92,6 +92,74 @@ njs_variable_add(njs_vm_t *vm, njs_parse } +njs_variable_t * +njs_label_add(njs_vm_t *vm, njs_parser_scope_t *scope, nxt_str_t *name, + uint32_t hash) +{ + nxt_int_t ret; + njs_variable_t *label; + nxt_lvlhsh_query_t lhq; + + lhq.key_hash = hash; + lhq.key = *name; + lhq.proto = &njs_variables_hash_proto; + + if (nxt_lvlhsh_find(&scope->labels, &lhq) == NXT_OK) { + return lhq.value; + } + + label = njs_variable_alloc(vm, &lhq.key, NJS_VARIABLE_CONST); From xeioex at nginx.com Mon Feb 25 16:01:16 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 25 Feb 2019 16:01:16 +0000 Subject: [njs] Moving boilerplate code into njs_generate_code(). Message-ID: details: https://hg.nginx.org/njs/rev/d49837819721 branches: changeset: 800:d49837819721 user: Dmitry Volyntsev date: Mon Feb 25 19:00:56 2019 +0300 description: Moving boilerplate code into njs_generate_code(). diffstat: njs/njs_generator.c | 497 ++++++++++++++++++--------------------------------- 1 files changed, 174 insertions(+), 323 deletions(-) diffs (truncated from 1021 to 1000 lines): diff -r 032827ab80dc -r d49837819721 njs/njs_generator.c --- a/njs/njs_generator.c Mon Feb 25 19:00:55 2019 +0300 +++ b/njs/njs_generator.c Mon Feb 25 19:00:56 2019 +0300 @@ -88,10 +88,10 @@ static njs_generator_block_t *njs_genera njs_generator_block_t *block, uint32_t mask, const nxt_str_t *label); static njs_generator_block_t *njs_generate_find_block( njs_generator_block_t *block, uint32_t mask, const nxt_str_t *label); +static nxt_noinline void njs_generate_patch_block(njs_vm_t *vm, + njs_generator_t *generator, njs_generator_patch_t *list); static njs_generator_patch_t *njs_generate_make_continuation_patch(njs_vm_t *vm, njs_generator_block_t *block, const nxt_str_t *label, njs_ret_t offset); -static nxt_noinline void njs_generate_patch_block(njs_vm_t *vm, - njs_generator_t *generator, njs_generator_patch_t *list); static njs_generator_patch_t *njs_generate_make_exit_patch(njs_vm_t *vm, njs_generator_block_t *block, const nxt_str_t *label, njs_ret_t offset); static nxt_noinline void njs_generate_patch_block_exit(njs_vm_t *vm, @@ -174,13 +174,35 @@ static nxt_int_t njs_generate_function_d njs_function_lambda_t *lambda, njs_parser_node_t *node); -#define njs_generate_code(generator, type, code) \ +#define njs_generate_code(generator, type, _code, _operation, nargs, _retval) \ do { \ - code = (type *) njs_generate_reserve(vm, generator, sizeof(type)); \ - if (nxt_slow_path(code == NULL)) { \ + _code = (type *) njs_generate_reserve(vm, generator, sizeof(type)); \ + if (nxt_slow_path(_code == NULL)) { \ return NXT_ERROR; \ } \ + \ generator->code_end += sizeof(type); \ + \ + _code->code.operation = _operation; \ + _code->code.operands = 3 - nargs; \ + _code->code.retval = _retval; \ + } while (0) + + +#define njs_generate_code_jump(generator, _code, _offset) \ + do { \ + njs_generate_code(generator, njs_vmcode_jump_t, _code, \ + njs_vmcode_jump, 0, 0); \ + _code->offset = _offset; \ + } while (0) + + +#define njs_generate_code_move(generator, _code, _dst, _src) \ + do { \ + njs_generate_code(generator, njs_vmcode_move_t, _code, \ + njs_vmcode_move, 2, 1); \ + _code->dst = _dst; \ + _code->src = _src; \ } while (0) @@ -513,10 +535,8 @@ njs_generate_name(njs_vm_t *vm, njs_gene return node->index; } - njs_generate_code(generator, njs_vmcode_object_copy_t, copy); - copy->code.operation = njs_vmcode_object_copy; - copy->code.operands = NJS_VMCODE_2OPERANDS; - copy->code.retval = NJS_VMCODE_RETVAL; + njs_generate_code(generator, njs_vmcode_object_copy_t, copy, + njs_vmcode_object_copy, 2, 1); copy->retval = node->index; copy->object = var->index; @@ -544,10 +564,8 @@ njs_generate_builtin_object(njs_vm_t *vm return NXT_ERROR; } - njs_generate_code(generator, njs_vmcode_object_copy_t, copy); - copy->code.operation = njs_vmcode_object_copy; - copy->code.operands = NJS_VMCODE_2OPERANDS; - copy->code.retval = NJS_VMCODE_RETVAL; + njs_generate_code(generator, njs_vmcode_object_copy_t, copy, + njs_vmcode_object_copy, 2, 1); copy->retval = node->index; copy->object = index; @@ -568,10 +586,8 @@ njs_generate_arguments_object(njs_vm_t * return NXT_ERROR; } - njs_generate_code(generator, njs_vmcode_arguments_t, gen); - gen->code.operation = njs_vmcode_arguments; - gen->code.operands = NJS_VMCODE_1OPERAND; - gen->code.retval = NJS_VMCODE_RETVAL; + njs_generate_code(generator, njs_vmcode_arguments_t, gen, + njs_vmcode_arguments, 1, 1); gen->retval = node->index; return NXT_OK; @@ -632,12 +648,7 @@ njs_generate_var_statement(njs_vm_t *vm, * empty object or expression result is stored directly in variable. */ if (lvalue->index != expr->index) { - njs_generate_code(generator, njs_vmcode_move_t, move); - move->code.operation = njs_vmcode_move; - move->code.operands = NJS_VMCODE_2OPERANDS; - move->code.retval = NJS_VMCODE_RETVAL; - move->dst = lvalue->index; - move->src = expr->index; + njs_generate_code_move(generator, move, lvalue->index, expr->index); } node->index = expr->index; @@ -663,10 +674,8 @@ njs_generate_if_statement(njs_vm_t *vm, return ret; } - njs_generate_code(generator, njs_vmcode_cond_jump_t, cond_jump); - cond_jump->code.operation = njs_vmcode_if_false_jump; - cond_jump->code.operands = NJS_VMCODE_2OPERANDS; - cond_jump->code.retval = NJS_VMCODE_NO_RETVAL; + njs_generate_code(generator, njs_vmcode_cond_jump_t, cond_jump, + njs_vmcode_if_false_jump, 2, 0); cond_jump->cond = node->left->index; ret = njs_generate_node_index_release(vm, generator, node->left); @@ -693,10 +702,7 @@ njs_generate_if_statement(njs_vm_t *vm, return ret; } - njs_generate_code(generator, njs_vmcode_jump_t, jump); - jump->code.operation = njs_vmcode_jump; - jump->code.operands = NJS_VMCODE_NO_OPERAND; - jump->code.retval = NJS_VMCODE_NO_RETVAL; + njs_generate_code_jump(generator, jump, 0); njs_code_set_offset(generator, label_offset, jump_offset); @@ -743,11 +749,10 @@ njs_generate_cond_expression(njs_vm_t *v return ret; } - njs_generate_code(generator, njs_vmcode_cond_jump_t, cond_jump); + njs_generate_code(generator, njs_vmcode_cond_jump_t, cond_jump, + njs_vmcode_if_false_jump, 2, 0); + cond_jump_offset = njs_code_offset(generator, cond_jump); - cond_jump->code.operation = njs_vmcode_if_false_jump; - cond_jump->code.operands = NJS_VMCODE_2OPERANDS; - cond_jump->code.retval = NJS_VMCODE_NO_RETVAL; cond_jump->cond = node->left->index; node->index = njs_generate_dest_index(vm, generator, node); @@ -771,12 +776,8 @@ njs_generate_cond_expression(njs_vm_t *v */ if (node->index != branch->left->index) { - njs_generate_code(generator, njs_vmcode_move_t, move); - move->code.operation = njs_vmcode_move; - move->code.operands = NJS_VMCODE_2OPERANDS; - move->code.retval = NJS_VMCODE_RETVAL; - move->dst = node->index; - move->src = branch->left->index; + njs_generate_code_move(generator, move, node->index, + branch->left->index); } ret = njs_generate_node_index_release(vm, generator, branch->left); @@ -784,11 +785,8 @@ njs_generate_cond_expression(njs_vm_t *v return ret; } - njs_generate_code(generator, njs_vmcode_jump_t, jump); + njs_generate_code_jump(generator, jump, 0); jump_offset = njs_code_offset(generator, jump); - jump->code.operation = njs_vmcode_jump; - jump->code.operands = NJS_VMCODE_NO_OPERAND; - jump->code.retval = NJS_VMCODE_NO_RETVAL; njs_code_set_jump_offset(generator, njs_vmcode_cond_jump_t, cond_jump_offset); @@ -801,12 +799,8 @@ njs_generate_cond_expression(njs_vm_t *v } if (node->index != branch->right->index) { - njs_generate_code(generator, njs_vmcode_move_t, move); - move->code.operation = njs_vmcode_move; - move->code.operands = NJS_VMCODE_2OPERANDS; - move->code.retval = NJS_VMCODE_RETVAL; - move->dst = node->index; - move->src = branch->right->index; + njs_generate_code_move(generator, move, node->index, + branch->right->index); } njs_code_set_jump_offset(generator, njs_vmcode_cond_jump_t, jump_offset); @@ -850,12 +844,7 @@ njs_generate_switch_statement(njs_vm_t * return NXT_ERROR; } - njs_generate_code(generator, njs_vmcode_move_t, move); - move->code.operation = njs_vmcode_move; - move->code.operands = NJS_VMCODE_2OPERANDS; - move->code.retval = NJS_VMCODE_RETVAL; - move->dst = index; - move->src = expr->index; + njs_generate_code_move(generator, move, index, expr->index); } ret = njs_generate_start_block(vm, generator, NJS_GENERATOR_SWITCH, @@ -880,10 +869,8 @@ njs_generate_switch_statement(njs_vm_t * return ret; } - njs_generate_code(generator, njs_vmcode_equal_jump_t, equal); - equal->code.operation = njs_vmcode_if_equal_jump; - equal->code.operands = NJS_VMCODE_3OPERANDS; - equal->code.retval = NJS_VMCODE_NO_RETVAL; + njs_generate_code(generator, njs_vmcode_equal_jump_t, equal, + njs_vmcode_if_equal_jump, 3, 0); equal->offset = offsetof(njs_vmcode_equal_jump_t, offset); equal->value1 = index; equal->value2 = node->left->index; @@ -913,12 +900,10 @@ njs_generate_switch_statement(njs_vm_t * return ret; } - njs_generate_code(generator, njs_vmcode_jump_t, jump); + njs_generate_code_jump(generator, jump, + offsetof(njs_vmcode_jump_t, offset)); + jump_offset = njs_code_offset(generator, jump); - jump->code.operation = njs_vmcode_jump; - jump->code.operands = NJS_VMCODE_1OPERAND; - jump->code.retval = NJS_VMCODE_NO_RETVAL; - jump->offset = offsetof(njs_vmcode_jump_t, offset); patch = patches; @@ -976,11 +961,8 @@ njs_generate_while_statement(njs_vm_t *v * the loop per each iteration. */ - njs_generate_code(generator, njs_vmcode_jump_t, jump); + njs_generate_code_jump(generator, jump, 0); jump_offset = njs_code_offset(generator, jump); - jump->code.operation = njs_vmcode_jump; - jump->code.operands = NJS_VMCODE_NO_OPERAND; - jump->code.retval = NJS_VMCODE_NO_RETVAL; /* The loop body. */ @@ -1010,10 +992,8 @@ njs_generate_while_statement(njs_vm_t *v return ret; } - njs_generate_code(generator, njs_vmcode_cond_jump_t, cond_jump); - cond_jump->code.operation = njs_vmcode_if_true_jump; - cond_jump->code.operands = NJS_VMCODE_2OPERANDS; - cond_jump->code.retval = NJS_VMCODE_NO_RETVAL; + njs_generate_code(generator, njs_vmcode_cond_jump_t, cond_jump, + njs_vmcode_if_true_jump, 2, 0); cond_jump->offset = loop_offset - njs_code_offset(generator, cond_jump); cond_jump->cond = condition->index; @@ -1058,10 +1038,8 @@ njs_generate_do_while_statement(njs_vm_t return ret; } - njs_generate_code(generator, njs_vmcode_cond_jump_t, cond_jump); - cond_jump->code.operation = njs_vmcode_if_true_jump; - cond_jump->code.operands = NJS_VMCODE_2OPERANDS; - cond_jump->code.retval = NJS_VMCODE_NO_RETVAL; + njs_generate_code(generator, njs_vmcode_cond_jump_t, cond_jump, + njs_vmcode_if_true_jump, 2, 0); cond_jump->offset = loop_offset - njs_code_offset(generator, cond_jump); cond_jump->cond = condition->index; @@ -1113,11 +1091,8 @@ njs_generate_for_statement(njs_vm_t *vm, * executed once just after the loop initialization and eliminates * execution of one additional jump inside the loop per each iteration. */ - njs_generate_code(generator, njs_vmcode_jump_t, jump); + njs_generate_code_jump(generator, jump, 0); jump_offset = njs_code_offset(generator, jump); - jump->code.operation = njs_vmcode_jump; - jump->code.operands = NJS_VMCODE_NO_OPERAND; - jump->code.retval = NJS_VMCODE_NO_RETVAL; } /* The loop body. */ @@ -1157,10 +1132,8 @@ njs_generate_for_statement(njs_vm_t *vm, return ret; } - njs_generate_code(generator, njs_vmcode_cond_jump_t, cond_jump); - cond_jump->code.operation = njs_vmcode_if_true_jump; - cond_jump->code.operands = NJS_VMCODE_2OPERANDS; - cond_jump->code.retval = NJS_VMCODE_NO_RETVAL; + njs_generate_code(generator, njs_vmcode_cond_jump_t, cond_jump, + njs_vmcode_if_true_jump, 2, 0); cond_jump->offset = loop_offset - njs_code_offset(generator, cond_jump); cond_jump->cond = condition->index; @@ -1169,11 +1142,8 @@ njs_generate_for_statement(njs_vm_t *vm, return njs_generate_node_index_release(vm, generator, condition); } - njs_generate_code(generator, njs_vmcode_jump_t, jump); - jump->code.operation = njs_vmcode_jump; - jump->code.operands = NJS_VMCODE_NO_OPERAND; - jump->code.retval = NJS_VMCODE_NO_RETVAL; - jump->offset = loop_offset - njs_code_offset(generator, jump); + njs_generate_code_jump(generator, jump, + loop_offset - njs_code_offset(generator, jump)); njs_generate_patch_block_exit(vm, generator); @@ -1207,11 +1177,9 @@ njs_generate_for_in_statement(njs_vm_t * return ret; } - njs_generate_code(generator, njs_vmcode_prop_foreach_t, prop_foreach); + njs_generate_code(generator, njs_vmcode_prop_foreach_t, prop_foreach, + njs_vmcode_property_foreach, 2, 1); prop_offset = njs_code_offset(generator, prop_foreach); - prop_foreach->code.operation = njs_vmcode_property_foreach; - prop_foreach->code.operands = NJS_VMCODE_2OPERANDS; - prop_foreach->code.retval = NJS_VMCODE_RETVAL; prop_foreach->object = foreach->right->index; index = njs_generate_temp_index_get(vm, generator, foreach->right); @@ -1241,11 +1209,9 @@ njs_generate_for_in_statement(njs_vm_t * return ret; } - njs_generate_code(generator, njs_vmcode_prop_next_t, prop_next); + njs_generate_code(generator, njs_vmcode_prop_next_t, prop_next, + njs_vmcode_property_next, 3, 0); prop_offset = njs_code_offset(generator, prop_next); - prop_next->code.operation = njs_vmcode_property_next; - prop_next->code.operands = NJS_VMCODE_3OPERANDS; - prop_next->code.retval = NJS_VMCODE_NO_RETVAL; prop_next->retval = foreach->left->index; prop_next->object = foreach->right->index; prop_next->next = index; @@ -1495,11 +1461,8 @@ njs_generate_continue_statement(njs_vm_t } } - njs_generate_code(generator, njs_vmcode_jump_t, jump); - jump->code.operation = njs_vmcode_jump; - jump->code.operands = NJS_VMCODE_NO_OPERAND; - jump->code.retval = NJS_VMCODE_NO_RETVAL; - jump->offset = offsetof(njs_vmcode_jump_t, offset); + njs_generate_code_jump(generator, jump, + offsetof(njs_vmcode_jump_t, offset)); patch = njs_generate_make_continuation_patch(vm, block, label, njs_code_offset(generator, jump) @@ -1543,11 +1506,8 @@ njs_generate_break_statement(njs_vm_t *v } } - njs_generate_code(generator, njs_vmcode_jump_t, jump); - jump->code.operation = njs_vmcode_jump; - jump->code.operands = NJS_VMCODE_NO_OPERAND; - jump->code.retval = NJS_VMCODE_NO_RETVAL; - jump->offset = offsetof(njs_vmcode_jump_t, offset); + njs_generate_code_jump(generator, jump, + offsetof(njs_vmcode_jump_t, offset)); patch = njs_generate_make_exit_patch(vm, block, label, njs_code_offset(generator, jump) @@ -1636,10 +1596,8 @@ njs_generate_stop_statement(njs_vm_t *vm ret = njs_generate_children(vm, generator, node); if (nxt_fast_path(ret == NXT_OK)) { - njs_generate_code(generator, njs_vmcode_stop_t, stop); - stop->code.operation = njs_vmcode_stop; - stop->code.operands = NJS_VMCODE_1OPERAND; - stop->code.retval = NJS_VMCODE_NO_RETVAL; + njs_generate_code(generator, njs_vmcode_stop_t, stop, + njs_vmcode_stop, 1, 0); index = NJS_INDEX_NONE; node = node->right; @@ -1680,7 +1638,7 @@ njs_generate_assignment(njs_vm_t *vm, nj njs_parser_node_t *node) { nxt_int_t ret; - njs_index_t index; + njs_index_t index, src; njs_parser_node_t *lvalue, *expr, *object, *property; njs_vmcode_move_t *move; njs_vmcode_prop_set_t *prop_set; @@ -1710,12 +1668,7 @@ njs_generate_assignment(njs_vm_t *vm, nj * empty object or expression result is stored directly in variable. */ if (lvalue->index != expr->index) { - njs_generate_code(generator, njs_vmcode_move_t, move); - move->code.operation = njs_vmcode_move; - move->code.operands = NJS_VMCODE_2OPERANDS; - move->code.retval = NJS_VMCODE_RETVAL; - move->dst = lvalue->index; - move->src = expr->index; + njs_generate_code_move(generator, move, lvalue->index, expr->index); } node->index = expr->index; @@ -1750,33 +1703,25 @@ njs_generate_assignment(njs_vm_t *vm, nj * if the variables can be changed by side effects in expression. */ if (object->token == NJS_TOKEN_NAME) { - njs_generate_code(generator, njs_vmcode_move_t, move); - move->code.operation = njs_vmcode_move; - move->code.operands = NJS_VMCODE_2OPERANDS; - move->code.retval = NJS_VMCODE_RETVAL; - move->src = object->index; + src = object->index; index = njs_generate_node_temp_index_get(vm, generator, object); if (nxt_slow_path(index == NJS_INDEX_ERROR)) { return NXT_ERROR; } - move->dst = index; + njs_generate_code_move(generator, move, index, src); } if (property->token == NJS_TOKEN_NAME) { - njs_generate_code(generator, njs_vmcode_move_t, move); - move->code.operation = njs_vmcode_move; - move->code.operands = NJS_VMCODE_2OPERANDS; - move->code.retval = NJS_VMCODE_RETVAL; - move->src = property->index; + src = property->index; index = njs_generate_node_temp_index_get(vm, generator, property); if (nxt_slow_path(index == NJS_INDEX_ERROR)) { return NXT_ERROR; } - move->dst = index; + njs_generate_code_move(generator, move, index, src); } } @@ -1785,10 +1730,8 @@ njs_generate_assignment(njs_vm_t *vm, nj return ret; } - njs_generate_code(generator, njs_vmcode_prop_set_t, prop_set); - prop_set->code.operation = njs_vmcode_property_set; - prop_set->code.operands = NJS_VMCODE_3OPERANDS; - prop_set->code.retval = NJS_VMCODE_NO_RETVAL; + njs_generate_code(generator, njs_vmcode_prop_set_t, prop_set, + njs_vmcode_property_set, 3, 0); prop_set->value = expr->index; prop_set->object = object->index; prop_set->property = property->index; @@ -1826,10 +1769,8 @@ njs_generate_operation_assignment(njs_vm if (nxt_slow_path(njs_parser_has_side_effect(expr))) { /* Preserve variable value if it may be changed by expression. */ - njs_generate_code(generator, njs_vmcode_move_t, move); - move->code.operation = njs_vmcode_move; - move->code.operands = NJS_VMCODE_2OPERANDS; - move->code.retval = NJS_VMCODE_RETVAL; + njs_generate_code(generator, njs_vmcode_move_t, move, + njs_vmcode_move, 2, 1); move->src = lvalue->index; index = njs_generate_temp_index_get(vm, generator, expr); @@ -1845,10 +1786,8 @@ njs_generate_operation_assignment(njs_vm return ret; } - njs_generate_code(generator, njs_vmcode_3addr_t, code); - code->code.operation = node->u.operation; - code->code.operands = NJS_VMCODE_3OPERANDS; - code->code.retval = NJS_VMCODE_RETVAL; + njs_generate_code(generator, njs_vmcode_3addr_t, code, + node->u.operation, 3, 1); code->dst = lvalue->index; code->src1 = index; code->src2 = expr->index; @@ -1890,10 +1829,8 @@ njs_generate_operation_assignment(njs_vm return NXT_ERROR; } - njs_generate_code(generator, njs_vmcode_prop_get_t, prop_get); - prop_get->code.operation = njs_vmcode_property_get; - prop_get->code.operands = NJS_VMCODE_3OPERANDS; - prop_get->code.retval = NJS_VMCODE_RETVAL; + njs_generate_code(generator, njs_vmcode_prop_get_t, prop_get, + njs_vmcode_property_get, 3, 1); prop_get->value = index; prop_get->object = object->index; prop_get->property = property->index; @@ -1905,18 +1842,14 @@ njs_generate_operation_assignment(njs_vm return ret; } - njs_generate_code(generator, njs_vmcode_3addr_t, code); - code->code.operation = node->u.operation; - code->code.operands = NJS_VMCODE_3OPERANDS; - code->code.retval = NJS_VMCODE_RETVAL; + njs_generate_code(generator, njs_vmcode_3addr_t, code, + node->u.operation, 3, 1); code->dst = node->index; code->src1 = node->index; code->src2 = expr->index; - njs_generate_code(generator, njs_vmcode_prop_set_t, prop_set); - prop_set->code.operation = njs_vmcode_property_set; - prop_set->code.operands = NJS_VMCODE_3OPERANDS; - prop_set->code.retval = NJS_VMCODE_NO_RETVAL; + njs_generate_code(generator, njs_vmcode_prop_set_t, prop_set, + njs_vmcode_property_set, 3, 0); prop_set->value = node->index; prop_set->object = object->index; prop_set->property = property->index; @@ -1941,10 +1874,8 @@ njs_generate_object(njs_vm_t *vm, njs_ge return NXT_ERROR; } - njs_generate_code(generator, njs_vmcode_object_t, object); - object->code.operation = njs_vmcode_object; - object->code.operands = NJS_VMCODE_1OPERAND; - object->code.retval = NJS_VMCODE_RETVAL; + njs_generate_code(generator, njs_vmcode_object_t, object, + njs_vmcode_object, 1, 1); object->retval = node->index; /* Initialize object. */ @@ -1963,10 +1894,8 @@ njs_generate_array(njs_vm_t *vm, njs_gen return NXT_ERROR; } - njs_generate_code(generator, njs_vmcode_array_t, array); - array->code.operation = njs_vmcode_array; - array->code.operands = NJS_VMCODE_1OPERAND; - array->code.retval = NJS_VMCODE_RETVAL; + njs_generate_code(generator, njs_vmcode_array_t, array, + njs_vmcode_array, 1, 1); array->code.ctor = node->ctor; array->retval = node->index; array->length = node->u.length; @@ -1999,10 +1928,8 @@ njs_generate_function(njs_vm_t *vm, njs_ } } - njs_generate_code(generator, njs_vmcode_function_t, function); - function->code.operation = njs_vmcode_function; - function->code.operands = NJS_VMCODE_1OPERAND; - function->code.retval = NJS_VMCODE_RETVAL; + njs_generate_code(generator, njs_vmcode_function_t, function, + njs_vmcode_function, 1, 1); function->lambda = lambda; node->index = njs_generate_object_dest_index(vm, generator, node); @@ -2027,10 +1954,8 @@ njs_generate_regexp(njs_vm_t *vm, njs_ge return NXT_ERROR; } - njs_generate_code(generator, njs_vmcode_regexp_t, regexp); - regexp->code.operation = njs_vmcode_regexp; - regexp->code.operands = NJS_VMCODE_1OPERAND; - regexp->code.retval = NJS_VMCODE_RETVAL; + njs_generate_code(generator, njs_vmcode_regexp_t, regexp, + njs_vmcode_regexp, 1, 1); regexp->retval = node->index; regexp->pattern = node->u.value.data.u.data; @@ -2052,11 +1977,9 @@ njs_generate_test_jump_expression(njs_vm return ret; } - njs_generate_code(generator, njs_vmcode_test_jump_t, test_jump); + njs_generate_code(generator, njs_vmcode_test_jump_t, test_jump, + node->u.operation, 2, 1); jump_offset = njs_code_offset(generator, test_jump); - test_jump->code.operation = node->u.operation; - test_jump->code.operands = NJS_VMCODE_2OPERANDS; - test_jump->code.retval = NJS_VMCODE_RETVAL; test_jump->value = node->left->index; node->index = njs_generate_node_temp_index_get(vm, generator, node); @@ -2078,12 +2001,8 @@ njs_generate_test_jump_expression(njs_vm */ if (node->index != node->right->index) { - njs_generate_code(generator, njs_vmcode_move_t, move); - move->code.operation = njs_vmcode_move; - move->code.operands = NJS_VMCODE_2OPERANDS; - move->code.retval = NJS_VMCODE_RETVAL; - move->dst = node->index; - move->src = node->right->index; + njs_generate_code_move(generator, move, node->index, + node->right->index); } njs_code_set_jump_offset(generator, njs_vmcode_test_jump_t, jump_offset); @@ -2114,10 +2033,8 @@ njs_generate_3addr_operation(njs_vm_t *v if (left->token == NJS_TOKEN_NAME) { if (nxt_slow_path(njs_parser_has_side_effect(right))) { - njs_generate_code(generator, njs_vmcode_move_t, move); - move->code.operation = njs_vmcode_move; - move->code.operands = NJS_VMCODE_2OPERANDS; - move->code.retval = NJS_VMCODE_RETVAL; + njs_generate_code(generator, njs_vmcode_move_t, move, + njs_vmcode_move, 2, 1); move->src = left->index; index = njs_generate_node_temp_index_get(vm, generator, left); @@ -2134,10 +2051,8 @@ njs_generate_3addr_operation(njs_vm_t *v return ret; } - njs_generate_code(generator, njs_vmcode_3addr_t, code); - code->code.operation = node->u.operation; - code->code.operands = NJS_VMCODE_3OPERANDS; - code->code.retval = NJS_VMCODE_RETVAL; + njs_generate_code(generator, njs_vmcode_3addr_t, code, + node->u.operation, 3, 1); if (!swap) { code->src1 = left->index; @@ -2178,10 +2093,8 @@ njs_generate_2addr_operation(njs_vm_t *v return ret; } - njs_generate_code(generator, njs_vmcode_2addr_t, code); - code->code.operation = node->u.operation; - code->code.operands = NJS_VMCODE_2OPERANDS; - code->code.retval = NJS_VMCODE_RETVAL; + njs_generate_code(generator, njs_vmcode_2addr_t, code, + node->u.operation, 2, 1); code->src = node->left->index; node->index = njs_generate_dest_index(vm, generator, node); @@ -2217,10 +2130,8 @@ njs_generate_typeof_operation(njs_vm_t * } } - njs_generate_code(generator, njs_vmcode_2addr_t, code); - code->code.operation = node->u.operation; - code->code.operands = NJS_VMCODE_2OPERANDS; - code->code.retval = NJS_VMCODE_RETVAL; + njs_generate_code(generator, njs_vmcode_2addr_t, code, + node->u.operation, 2, 1); code->src = node->left->index; node->index = njs_generate_dest_index(vm, generator, node); @@ -2263,10 +2174,8 @@ njs_generate_inc_dec_operation(njs_vm_t node->index = index; - njs_generate_code(generator, njs_vmcode_3addr_t, code); - code->code.operation = node->u.operation; - code->code.operands = NJS_VMCODE_3OPERANDS; - code->code.retval = NJS_VMCODE_RETVAL; + njs_generate_code(generator, njs_vmcode_3addr_t, code, + node->u.operation, 3, 1); code->dst = index; code->src1 = lvalue->index; code->src2 = lvalue->index; @@ -2313,26 +2222,20 @@ found: return NXT_ERROR; } - njs_generate_code(generator, njs_vmcode_prop_get_t, prop_get); - prop_get->code.operation = njs_vmcode_property_get; - prop_get->code.operands = NJS_VMCODE_3OPERANDS; - prop_get->code.retval = NJS_VMCODE_RETVAL; + njs_generate_code(generator, njs_vmcode_prop_get_t, prop_get, + njs_vmcode_property_get, 3, 1); prop_get->value = index; prop_get->object = lvalue->left->index; prop_get->property = lvalue->right->index; - njs_generate_code(generator, njs_vmcode_3addr_t, code); - code->code.operation = node->u.operation; - code->code.operands = NJS_VMCODE_3OPERANDS; - code->code.retval = NJS_VMCODE_RETVAL; + njs_generate_code(generator, njs_vmcode_3addr_t, code, + node->u.operation, 3, 1); code->dst = dest_index; code->src1 = index; code->src2 = index; - njs_generate_code(generator, njs_vmcode_prop_set_t, prop_set); - prop_set->code.operation = njs_vmcode_property_set; - prop_set->code.operands = NJS_VMCODE_3OPERANDS; - prop_set->code.retval = NJS_VMCODE_NO_RETVAL; + njs_generate_code(generator, njs_vmcode_prop_set_t, prop_set, + njs_vmcode_property_set, 3, 0); prop_set->value = index; prop_set->object = lvalue->left->index; prop_set->property = lvalue->right->index; @@ -2521,12 +2424,7 @@ njs_generate_argument_closures(njs_vm_t if (var->argument != 0) { index = njs_scope_index((var->argument - 1), NJS_SCOPE_ARGUMENTS); - njs_generate_code(generator, njs_vmcode_move_t, move); - move->code.operation = njs_vmcode_move; - move->code.operands = NJS_VMCODE_2OPERANDS; - move->code.retval = NJS_VMCODE_RETVAL; - move->dst = var->index; - move->src = index; + njs_generate_code_move(generator, move, var->index, index); n--; } @@ -2566,11 +2464,8 @@ njs_generate_return_statement(njs_vm_t * &no_label); if (nxt_fast_path(immediate == NULL)) { - njs_generate_code(generator, njs_vmcode_return_t, code); - code->code.operation = njs_vmcode_return; - code->code.operands = NJS_VMCODE_1OPERAND; - code->code.retval = NJS_VMCODE_NO_RETVAL; - + njs_generate_code(generator, njs_vmcode_return_t, code, + njs_vmcode_return, 1, 0); code->retval = index; node->index = index; @@ -2599,10 +2494,8 @@ njs_generate_return_statement(njs_vm_t * block = block->next; } - njs_generate_code(generator, njs_vmcode_try_return_t, try_return); - try_return->code.operation = njs_vmcode_try_return; - try_return->code.operands = NJS_VMCODE_2OPERANDS; - try_return->code.retval = NJS_VMCODE_RETVAL; + njs_generate_code(generator, njs_vmcode_try_return_t, try_return, + njs_vmcode_try_return, 2, 1); try_return->retval = index; try_return->save = top->index; try_return->offset = offsetof(njs_vmcode_try_return_t, offset); @@ -2645,11 +2538,9 @@ njs_generate_function_call(njs_vm_t *vm, name = node; } - njs_generate_code(generator, njs_vmcode_function_frame_t, func); + njs_generate_code(generator, njs_vmcode_function_frame_t, func, + njs_vmcode_function_frame, 2, 0); func_offset = njs_code_offset(generator, func); - func->code.operation = njs_vmcode_function_frame; - func->code.operands = NJS_VMCODE_2OPERANDS; - func->code.retval = NJS_VMCODE_NO_RETVAL; func->code.ctor = node->ctor; func->name = name->index; @@ -2691,11 +2582,9 @@ njs_generate_method_call(njs_vm_t *vm, n return ret; } - njs_generate_code(generator, njs_vmcode_method_frame_t, method); + njs_generate_code(generator, njs_vmcode_method_frame_t, method, + njs_vmcode_method_frame, 3, 0); method_offset = njs_code_offset(generator, method); - method->code.operation = njs_vmcode_method_frame; - method->code.operands = NJS_VMCODE_3OPERANDS; - method->code.retval = NJS_VMCODE_NO_RETVAL; method->code.ctor = node->ctor; method->object = prop->left->index; method->method = prop->right->index; @@ -2740,12 +2629,8 @@ njs_generate_call(njs_vm_t *vm, njs_gene } if (arg->index != arg->left->index) { - njs_generate_code(generator, njs_vmcode_move_t, move); - move->code.operation = njs_vmcode_move; - move->code.operands = NJS_VMCODE_2OPERANDS; - move->code.retval = NJS_VMCODE_RETVAL; - move->dst = arg->index; - move->src = arg->left->index; + njs_generate_code_move(generator, move, arg->index, + arg->left->index); } } @@ -2756,16 +2641,36 @@ njs_generate_call(njs_vm_t *vm, njs_gene node->index = retval; - njs_generate_code(generator, njs_vmcode_function_call_t, call); - call->code.operation = njs_vmcode_function_call; - call->code.operands = NJS_VMCODE_1OPERAND; - call->code.retval = NJS_VMCODE_NO_RETVAL; + njs_generate_code(generator, njs_vmcode_function_call_t, call, + njs_vmcode_function_call, 1, 0); call->retval = retval; return nargs; } +#define njs_generate_code_catch(generator, _code, _exception) \ + do { \ + njs_generate_code(generator, njs_vmcode_catch_t, _code, \ + njs_vmcode_catch, 2, 0); \ + _code->offset = sizeof(njs_vmcode_catch_t); \ + _code->exception = _exception; \ + } while (0) + + +#define njs_generate_code_finally(generator, _code, _retval, _exit) \ + do { \ + njs_generate_code(generator, njs_vmcode_finally_t, _code, \ + njs_vmcode_finally, 2, 0); \ + _code->retval = _retval; \ + _code->exit_value = _exit; \ + _code->continue_offset = offsetof(njs_vmcode_finally_t, \ + continue_offset); \ + _code->break_offset = offsetof(njs_vmcode_finally_t, \ + break_offset); \ + } while (0) + + static nxt_int_t njs_generate_try_statement(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node) @@ -2785,11 +2690,9 @@ njs_generate_try_statement(njs_vm_t *vm, njs_vmcode_try_start_t *try_start; njs_vmcode_try_trampoline_t *try_break, *try_continue; - njs_generate_code(generator, njs_vmcode_try_start_t, try_start); + njs_generate_code(generator, njs_vmcode_try_start_t, try_start, + njs_vmcode_try_start, 2, 0); try_offset = njs_code_offset(generator, try_start); - try_start->code.operation = njs_vmcode_try_start; - try_start->code.operands = NJS_VMCODE_2OPERANDS; - try_start->code.retval = NJS_VMCODE_NO_RETVAL; exception_index = njs_generate_temp_index_get(vm, generator, node); if (nxt_slow_path(exception_index == NJS_INDEX_ERROR)) { @@ -2827,22 +2730,17 @@ njs_generate_try_statement(njs_vm_t *vm, try_exit_label = undef_label; try_cont_label = undef_label; - njs_generate_code(generator, njs_vmcode_try_end_t, try_end); + njs_generate_code(generator, njs_vmcode_try_end_t, try_end, + njs_vmcode_try_end, 0, 0); try_end_offset = njs_code_offset(generator, try_end); - try_end->code.operation = njs_vmcode_try_end; - try_end->code.operands = NJS_VMCODE_NO_OPERAND; - try_end->code.retval = NJS_VMCODE_NO_RETVAL; if (try_block->exit != NULL) { try_exit_label = try_block->exit->label; njs_generate_patch_block(vm, generator, try_block->exit); - njs_generate_code(generator, njs_vmcode_try_trampoline_t, try_break); - try_break->code.operation = njs_vmcode_try_break; - try_break->code.operands = NJS_VMCODE_2OPERANDS; - try_break->code.retval = NJS_VMCODE_NO_RETVAL; - + njs_generate_code(generator, njs_vmcode_try_trampoline_t, try_break, + njs_vmcode_try_break, 2, 0); try_break->exit_value = exit_index; try_break->offset = -sizeof(njs_vmcode_try_end_t); @@ -2856,11 +2754,8 @@ njs_generate_try_statement(njs_vm_t *vm, njs_generate_patch_block(vm, generator, try_block->continuation); - njs_generate_code(generator, njs_vmcode_try_trampoline_t, try_continue); - try_continue->code.operation = njs_vmcode_try_continue; - try_continue->code.operands = NJS_VMCODE_2OPERANDS; - try_continue->code.retval = NJS_VMCODE_NO_RETVAL; - + njs_generate_code(generator, njs_vmcode_try_trampoline_t, try_continue, + njs_vmcode_try_continue, 2, 0); try_continue->exit_value = exit_index; try_continue->offset = -sizeof(njs_vmcode_try_end_t); @@ -2888,12 +2783,7 @@ njs_generate_try_statement(njs_vm_t *vm, return NXT_ERROR; } - njs_generate_code(generator, njs_vmcode_catch_t, catch); - catch->code.operation = njs_vmcode_catch; - catch->code.operands = NJS_VMCODE_2OPERANDS; - catch->code.retval = NJS_VMCODE_NO_RETVAL; - catch->offset = sizeof(njs_vmcode_catch_t); - catch->exception = catch_index; + njs_generate_code_catch(generator, catch, catch_index); ret = njs_generator(vm, generator, node->right); if (nxt_slow_path(ret != NXT_OK)) { @@ -2903,16 +2793,8 @@ njs_generate_try_statement(njs_vm_t *vm, njs_code_set_jump_offset(generator, njs_vmcode_try_end_t, try_offset); if (try_block->continuation != NULL || try_block->exit != NULL) { - njs_generate_code(generator, njs_vmcode_finally_t, finally); - finally->code.operation = njs_vmcode_finally; - finally->code.operands = NJS_VMCODE_2OPERANDS; - finally->code.retval = NJS_VMCODE_NO_RETVAL; - finally->retval = exception_index; - finally->exit_value = exit_index; - finally->continue_offset = offsetof(njs_vmcode_finally_t, - continue_offset); - finally->break_offset = offsetof(njs_vmcode_finally_t, - break_offset); + njs_generate_code_finally(generator, finally, exception_index, + exit_index); if (try_block->continuation != NULL) { /* @@ -2960,12 +2842,8 @@ njs_generate_try_statement(njs_vm_t *vm, return NXT_ERROR; } - njs_generate_code(generator, njs_vmcode_catch_t, catch); + njs_generate_code_catch(generator, catch, catch_index); catch_offset = njs_code_offset(generator, catch); - catch->code.operation = njs_vmcode_catch; - catch->code.operands = NJS_VMCODE_2OPERANDS; - catch->code.retval = NJS_VMCODE_NO_RETVAL; - catch->exception = catch_index; ret = njs_generate_start_block(vm, generator, NJS_GENERATOR_TRY, &no_label); @@ -2981,11 +2859,9 @@ njs_generate_try_statement(njs_vm_t *vm, return ret; } - njs_generate_code(generator, njs_vmcode_try_end_t, catch_end); + njs_generate_code(generator, njs_vmcode_try_end_t, catch_end, + njs_vmcode_try_end, 0, 0); catch_end_offset = njs_code_offset(generator, catch_end); - catch_end->code.operation = njs_vmcode_try_end; - catch_end->code.operands = NJS_VMCODE_NO_OPERAND; - catch_end->code.retval = NJS_VMCODE_NO_RETVAL; if (catch_block->exit != NULL) { catch_exit_label = catch_block->exit->label; @@ -2993,10 +2869,7 @@ njs_generate_try_statement(njs_vm_t *vm, njs_generate_patch_block(vm, generator, catch_block->exit); njs_generate_code(generator, njs_vmcode_try_trampoline_t, - try_break); - try_break->code.operation = njs_vmcode_try_break; - try_break->code.operands = NJS_VMCODE_2OPERANDS; - try_break->code.retval = NJS_VMCODE_NO_RETVAL; + try_break, njs_vmcode_try_break, 2, 0); try_break->exit_value = exit_index; @@ -3013,10 +2886,7 @@ njs_generate_try_statement(njs_vm_t *vm, catch_block->continuation); njs_generate_code(generator, njs_vmcode_try_trampoline_t, - try_continue); - try_continue->code.operation = njs_vmcode_try_continue; - try_continue->code.operands = NJS_VMCODE_2OPERANDS; - try_continue->code.retval = NJS_VMCODE_NO_RETVAL; + try_continue, njs_vmcode_try_continue, 2, 0); try_continue->exit_value = exit_index; @@ -3034,12 +2904,7 @@ njs_generate_try_statement(njs_vm_t *vm, /* TODO: release exception variable index. */ - njs_generate_code(generator, njs_vmcode_catch_t, catch); - catch->code.operation = njs_vmcode_catch; - catch->code.operands = NJS_VMCODE_2OPERANDS; - catch->code.retval = NJS_VMCODE_NO_RETVAL; - catch->offset = sizeof(njs_vmcode_catch_t); - catch->exception = exception_index; + njs_generate_code_catch(generator, catch, exception_index); njs_code_set_jump_offset(generator, njs_vmcode_try_end_t, catch_end_offset); @@ -3047,12 +2912,7 @@ njs_generate_try_statement(njs_vm_t *vm, } else { /* A try/finally case. */ - njs_generate_code(generator, njs_vmcode_catch_t, catch); - catch->code.operation = njs_vmcode_catch; - catch->code.operands = NJS_VMCODE_2OPERANDS; - catch->code.retval = NJS_VMCODE_NO_RETVAL; - catch->offset = sizeof(njs_vmcode_catch_t); - catch->exception = exception_index; + njs_generate_code_catch(generator, catch, exception_index); catch_block = NULL; } @@ -3064,15 +2924,8 @@ njs_generate_try_statement(njs_vm_t *vm, return ret; } - njs_generate_code(generator, njs_vmcode_finally_t, finally); - finally->code.operation = njs_vmcode_finally; - finally->code.operands = NJS_VMCODE_2OPERANDS; - finally->code.retval = NJS_VMCODE_NO_RETVAL; - finally->retval = exception_index; - finally->exit_value = exit_index; From mdounin at mdounin.ru Mon Feb 25 18:35:37 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 25 Feb 2019 18:35:37 +0000 Subject: [nginx] SSL: fixed possible segfault with dynamic certificates. Message-ID: details: https://hg.nginx.org/nginx/rev/48c87377aabd branches: changeset: 7466:48c87377aabd user: Maxim Dounin date: Mon Feb 25 21:16:26 2019 +0300 description: SSL: fixed possible segfault with dynamic certificates. A virtual server may have no SSL context if it does not have certificates defined, so we have to use config of the ngx_http_ssl_module from the SSL context in the certificate callback. To do so, it is now passed as the argument of the callback. The stream module doesn't really need any changes, but was modified as well to match http code. diffstat: src/http/modules/ngx_http_ssl_module.c | 2 +- src/http/ngx_http_request.c | 2 +- src/stream/ngx_stream_ssl_module.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diffs (45 lines): diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -741,7 +741,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * /* install callback to lookup certificates */ - SSL_CTX_set_cert_cb(conf->ssl.ctx, ngx_http_ssl_certificate, NULL); + SSL_CTX_set_cert_cb(conf->ssl.ctx, ngx_http_ssl_certificate, conf); #else ngx_log_error(NGX_LOG_EMERG, cf->log, 0, diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -973,7 +973,7 @@ ngx_http_ssl_certificate(ngx_ssl_conn_t r->logged = 1; - sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module); + sscf = arg; nelts = sscf->certificate_values->nelts; certs = sscf->certificate_values->elts; diff --git a/src/stream/ngx_stream_ssl_module.c b/src/stream/ngx_stream_ssl_module.c --- a/src/stream/ngx_stream_ssl_module.c +++ b/src/stream/ngx_stream_ssl_module.c @@ -434,7 +434,7 @@ ngx_stream_ssl_certificate(ngx_ssl_conn_ s = c->data; - sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module); + sslcf = arg; nelts = sslcf->certificate_values->nelts; certs = sslcf->certificate_values->elts; @@ -692,7 +692,7 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf /* install callback to lookup certificates */ - SSL_CTX_set_cert_cb(conf->ssl.ctx, ngx_stream_ssl_certificate, NULL); + SSL_CTX_set_cert_cb(conf->ssl.ctx, ngx_stream_ssl_certificate, conf); #else ngx_log_error(NGX_LOG_EMERG, cf->log, 0, From terence at honles.com Mon Feb 25 20:46:00 2019 From: terence at honles.com (Terence Honles) Date: Mon, 25 Feb 2019 12:46:00 -0800 Subject: [PATCH] better constrain IP-literal validation in ngx_http_validate_host() In-Reply-To: <20181225154234.GD99070@mdounin.ru> References: <20181217161740.GT99070@mdounin.ru> <20181224125858.GH99070@mdounin.ru> <20181225154234.GD99070@mdounin.ru> Message-ID: I followed up on this, and it is only happening via HTTPs which does not have the "host guard". When added it performed as expected, Thanks. On Tue, Dec 25, 2018 at 7:42 AM Maxim Dounin wrote: > > Hello! > > On Mon, Dec 24, 2018 at 01:47:36PM -0800, Terence Honles wrote: > > > Yes, the regex will fail for IPv future literals, but I don't believe they are > > being used in practice. When they are, I'm sure the Django project will > > welcome the change to the RegEx. > > Sure. The point is that there is no difference between perfectly > valid and invalid literals. Django will complain if it sees > anything it doesn't understand (and that's perfectly fine, > actually). > > > As for the configuration you proposed, we are already using that (with a 444 > > instead of 404), but the IP literal will still pass through because it is a > > valid match (but an invalid hostname according to RFC 3986). > > With the configuration I proposed, names you haven't explicitly > configured with the "server_name" directive will not be sent to > backends. And if you've explicitly configured an invalid name, I > don't see why nginx should refuse doing what it was explicitly > told to do. > > Most likely, you've instead configured nginx to pass everything to > Django, and this is what causes errors in your setup. Consider > switching to a more restricted configuration. > > Happy holidays. > > -- > Maxim Dounin > http://mdounin.ru/ > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > From ru at nginx.com Tue Feb 26 07:59:18 2019 From: ru at nginx.com (Ruslan Ermilov) Date: Tue, 26 Feb 2019 10:59:18 +0300 Subject: limit_rate_after support variables In-Reply-To: References: <20180827160021.GG71000@lo0.su> <20180829114230.GC43480@lo0.su> <20181120141005.GA72348@lo0.su> <20181206144522.GF50234@lo0.su> Message-ID: <20190226075918.GF86031@lo0.su> On Mon, Feb 25, 2019 at 12:06:07PM +0100, Miroslav Nov? wrote: > Hello, > how does it look with merge into the main branch? It's still under the review. Sorry. > Thank you for answer > Mira Novy > > po 10. 12. 2018 v 14:30 odes?latel Miroslav Novy > napsal: > > > Hello, > > your path is very good. I tested it and works fine for as. > > > > Reading complex value to the same local variable limit_rate was conflusing > > for me at first time. But it is correct :) > > > > if (r->limit_rate_after == 0 > > + && clcf->limit_rate_after > > + && ngx_http_complex_value_size(r, clcf->limit_rate_after, > > &val, > > + &limit_rate) > > <----------------------- > > + == NGX_OK) > > + { > > + if (limit_rate != (size_t) NGX_ERROR) { > > + r->limit_rate_after = limit_rate; > > + > > + } else if (val.len) { > > > > Please, merge your path to master branch. > > > > Best regards > > M. Nov? > > -- Ruslan Ermilov Assume stupidity not malice From xeioex at nginx.com Tue Feb 26 13:32:37 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 26 Feb 2019 13:32:37 +0000 Subject: [njs] HTTP: avoid creating empty request_body buffer in r.subrequest(). Message-ID: details: https://hg.nginx.org/njs/rev/40b6f1030873 branches: changeset: 801:40b6f1030873 user: Dmitry Volyntsev date: Tue Feb 26 16:16:08 2019 +0300 description: HTTP: avoid creating empty request_body buffer in r.subrequest(). This fixes #101 issue on Github. diffstat: nginx/ngx_http_js_module.c | 34 ++++++++++++++++++---------------- 1 files changed, 18 insertions(+), 16 deletions(-) diffs (46 lines): diff -r d49837819721 -r 40b6f1030873 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Mon Feb 25 19:00:56 2019 +0300 +++ b/nginx/ngx_http_js_module.c Tue Feb 26 16:16:08 2019 +0300 @@ -1869,24 +1869,26 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, goto memory_error; } - rb->bufs = ngx_alloc_chain_link(r->pool); - if (rb->bufs == NULL) { - goto memory_error; + if (body_arg.length != 0) { + rb->bufs = ngx_alloc_chain_link(r->pool); + if (rb->bufs == NULL) { + goto memory_error; + } + + rb->bufs->next = NULL; + + rb->bufs->buf = ngx_calloc_buf(r->pool); + if (rb->bufs->buf == NULL) { + goto memory_error; + } + + rb->bufs->buf->memory = 1; + rb->bufs->buf->last_buf = 1; + + rb->bufs->buf->pos = body_arg.start; + rb->bufs->buf->last = body_arg.start + body_arg.length; } - rb->bufs->next = NULL; - - rb->bufs->buf = ngx_calloc_buf(r->pool); - if (rb->bufs->buf == NULL) { - goto memory_error; - } - - rb->bufs->buf->memory = 1; - rb->bufs->buf->last_buf = 1; - - rb->bufs->buf->pos = body_arg.start; - rb->bufs->buf->last = body_arg.start + body_arg.length; - sr->request_body = rb; sr->headers_in.content_length_n = body_arg.length; sr->headers_in.chunked = 0; From xeioex at nginx.com Tue Feb 26 14:03:39 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 26 Feb 2019 14:03:39 +0000 Subject: [njs] Version 0.2.8. Message-ID: details: https://hg.nginx.org/njs/rev/ee190d3ace00 branches: changeset: 802:ee190d3ace00 user: Dmitry Volyntsev date: Tue Feb 26 16:36:29 2019 +0300 description: Version 0.2.8. diffstat: CHANGES | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 51 insertions(+), 0 deletions(-) diffs (58 lines): diff -r 40b6f1030873 -r ee190d3ace00 CHANGES --- a/CHANGES Tue Feb 26 16:16:08 2019 +0300 +++ b/CHANGES Tue Feb 26 16:36:29 2019 +0300 @@ -1,3 +1,54 @@ + +Changes with njs 0.2.8 26 Feb 2019 + + nginx modules: + + *) Change: properties of HTTP request deprecarted in 0.2.2 are + removed. + + *) Feature: added support for delete operation in r.headersOut. + + *) Feature: added support for setting nginx variables. + + *) Bugfix: fixed r.subrequest() for empty body value. + + *) Improvement: setting special response headers in r.headersOut. + + Core: + + *) Feature: added labels support. + + *) Feature: added setImmediate() method. + + *) Feature: added support for shorthand property names for Object + literals. + + *) Bugfix: fixed Function.prototype.bind(). + + *) Bugfix: fixed parsing of string literals containing newline + characters. + + *) Bugfix: fixed line number in reporting variable reference errors. + + *) Bugfix: fixed creation of long UTF8 strings. + + *) Bugfix: fixed String.prototype.split() for unicode strings. + + *) Bugfix: fixed heap-buffer-overflow in String.prototype.split(). + + *) Bugfix: fixed Array.prototype.fill(). + Thanks to Artem S. Povalyukhin. + + *) Improvement: code related to function invocation is refactored. + Thanks to ??? (Hong Zhi Dao). + + *) Improvement: code related to variables is refactored. + Thanks to ??? (Hong Zhi Dao). + + *) Improvement: parser is refactored. + Thanks to ??? (Hong Zhi Dao). + + *) Improvement: reporting filenames in exceptions. Changes with njs 0.2.7 25 Dec 2018 From xeioex at nginx.com Tue Feb 26 14:03:39 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 26 Feb 2019 14:03:39 +0000 Subject: [njs] Added tag 0.2.8 for changeset ee190d3ace00 Message-ID: details: https://hg.nginx.org/njs/rev/ff3116568a23 branches: changeset: 803:ff3116568a23 user: Dmitry Volyntsev date: Tue Feb 26 17:03:24 2019 +0300 description: Added tag 0.2.8 for changeset ee190d3ace00 diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff -r ee190d3ace00 -r ff3116568a23 .hgtags --- a/.hgtags Tue Feb 26 16:36:29 2019 +0300 +++ b/.hgtags Tue Feb 26 17:03:24 2019 +0300 @@ -22,3 +22,4 @@ 3e6c38f64bdbc53e783813541559034ed6890aee 3315f6aa6000ce6d2dbc74c73660becf4178a549 0.2.5 0709b8b4f11ebec95dd4f72d5bb38044682f77e6 0.2.6 4624ba4f6497a3d10fe1c0a6f45fb453579502f5 0.2.7 +ee190d3ace005f8eb063d4763b578f44d3028c68 0.2.8 From xeioex at nginx.com Tue Feb 26 15:24:29 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 26 Feb 2019 15:24:29 +0000 Subject: [njs] Version bump. Message-ID: details: https://hg.nginx.org/njs/rev/e793d1b60427 branches: changeset: 804:e793d1b60427 user: Dmitry Volyntsev date: Tue Feb 26 17:11:42 2019 +0300 description: Version bump. diffstat: njs/njs.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r ff3116568a23 -r e793d1b60427 njs/njs.h --- a/njs/njs.h Tue Feb 26 17:03:24 2019 +0300 +++ b/njs/njs.h Tue Feb 26 17:11:42 2019 +0300 @@ -11,7 +11,7 @@ #include -#define NJS_VERSION "0.2.8" +#define NJS_VERSION "0.3.0" #include From xeioex at nginx.com Tue Feb 26 15:24:30 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 26 Feb 2019 15:24:30 +0000 Subject: [njs] Renaming njs_value_void_set() to njs_value_undefined_set(). Message-ID: details: https://hg.nginx.org/njs/rev/488278bde04a branches: changeset: 805:488278bde04a user: Dmitry Volyntsev date: Tue Feb 26 17:11:47 2019 +0300 description: Renaming njs_value_void_set() to njs_value_undefined_set(). diffstat: njs/njs.h | 2 +- njs/njs_vm.c | 2 +- njs/test/njs_unit_test.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diffs (36 lines): diff -r e793d1b60427 -r 488278bde04a njs/njs.h --- a/njs/njs.h Tue Feb 26 17:11:42 2019 +0300 +++ b/njs/njs.h Tue Feb 26 17:11:47 2019 +0300 @@ -254,7 +254,7 @@ NXT_EXPORT void njs_vm_value_error_set(n const char *fmt, ...); NXT_EXPORT void njs_vm_memory_error(njs_vm_t *vm); -NXT_EXPORT void njs_value_void_set(njs_value_t *value); +NXT_EXPORT void njs_value_undefined_set(njs_value_t *value); NXT_EXPORT void njs_value_boolean_set(njs_value_t *value, int yn); NXT_EXPORT void njs_value_number_set(njs_value_t *value, double num); NXT_EXPORT void njs_value_data_set(njs_value_t *value, void *data); diff -r e793d1b60427 -r 488278bde04a njs/njs_vm.c --- a/njs/njs_vm.c Tue Feb 26 17:11:42 2019 +0300 +++ b/njs/njs_vm.c Tue Feb 26 17:11:47 2019 +0300 @@ -3295,7 +3295,7 @@ njs_vmcode_value_to_string(njs_vm_t *vm, nxt_noinline void -njs_value_void_set(njs_value_t *value) +njs_value_undefined_set(njs_value_t *value) { *value = njs_value_void; } diff -r e793d1b60427 -r 488278bde04a njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Tue Feb 26 17:11:42 2019 +0300 +++ b/njs/test/njs_unit_test.c Tue Feb 26 17:11:47 2019 +0300 @@ -11675,7 +11675,7 @@ njs_unit_test_r_get_vars(njs_vm_t *vm, n return NXT_OK; } - njs_value_void_set(value); + njs_value_undefined_set(value); return NXT_OK; } From xeioex at nginx.com Tue Feb 26 15:24:30 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 26 Feb 2019 15:24:30 +0000 Subject: [njs] Improved checking that filename is not empty. Message-ID: details: https://hg.nginx.org/njs/rev/f70566bc1e62 branches: changeset: 806:f70566bc1e62 user: Dmitry Volyntsev date: Tue Feb 26 17:11:50 2019 +0300 description: Improved checking that filename is not empty. file->start can be non NULL for empty string. diffstat: njs/njs_parser.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diffs (30 lines): diff -r 488278bde04a -r f70566bc1e62 njs/njs_parser.c --- a/njs/njs_parser.c Tue Feb 26 17:11:47 2019 +0300 +++ b/njs/njs_parser.c Tue Feb 26 17:11:50 2019 +0300 @@ -233,7 +233,7 @@ njs_parser_scope_begin(njs_vm_t *vm, njs scope->values[0] = values; scope->values[1] = NULL; - if (parser->lexer->file.start != NULL) { + if (parser->lexer->file.length != 0) { ret = njs_name_copy(vm, &scope->file, &parser->lexer->file); if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; @@ -2758,7 +2758,7 @@ njs_parser_trace_handler(nxt_trace_t *tr if (vm->parser != NULL) { lexer = vm->parser->lexer; - if (lexer->file.start != NULL) { + if (lexer->file.length != 0) { njs_internal_error(vm, "%s in %V:%uD", start, &lexer->file, lexer->line); } else { @@ -2795,7 +2795,7 @@ njs_parser_scope_error(njs_vm_t *vm, njs p = end - width; } - if (file->start != NULL) { + if (file->length != 0) { p = nxt_sprintf(p, end, " in %V:%uD", file, line); } else { From xeioex at nginx.com Tue Feb 26 15:24:30 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 26 Feb 2019 15:24:30 +0000 Subject: [njs] Style. Message-ID: details: https://hg.nginx.org/njs/rev/1d6e32892413 branches: changeset: 807:1d6e32892413 user: hongzhidao date: Tue Feb 26 17:32:59 2019 +0800 description: Style. diffstat: njs/njs_disassembler.c | 48 ++++++++++++++++++++++++------------------------ 1 files changed, 24 insertions(+), 24 deletions(-) diffs (67 lines): diff -r f70566bc1e62 -r 1d6e32892413 njs/njs_disassembler.c --- a/njs/njs_disassembler.c Tue Feb 26 17:11:50 2019 +0300 +++ b/njs/njs_disassembler.c Tue Feb 26 17:32:59 2019 +0800 @@ -412,39 +412,39 @@ njs_disassemble(u_char *start, u_char *e n = nxt_nitems(code_names); do { - if (operation == code_name->operation) { - name = &code_name->name; + if (operation == code_name->operation) { + name = &code_name->name; - if (code_name->size == sizeof(njs_vmcode_3addr_t)) { - code3 = (njs_vmcode_3addr_t *) p; + if (code_name->size == sizeof(njs_vmcode_3addr_t)) { + code3 = (njs_vmcode_3addr_t *) p; - printf("%05zd %*s %04zX %04zX %04zX\n", - p - start, (int) name->length, name->start, - (size_t) code3->dst, (size_t) code3->src1, - (size_t) code3->src2); + printf("%05zd %*s %04zX %04zX %04zX\n", + p - start, (int) name->length, name->start, + (size_t) code3->dst, (size_t) code3->src1, + (size_t) code3->src2); - } else if (code_name->size == sizeof(njs_vmcode_2addr_t)) { - code2 = (njs_vmcode_2addr_t *) p; + } else if (code_name->size == sizeof(njs_vmcode_2addr_t)) { + code2 = (njs_vmcode_2addr_t *) p; - printf("%05zd %*s %04zX %04zX\n", - p - start, (int) name->length, name->start, - (size_t) code2->dst, (size_t) code2->src); + printf("%05zd %*s %04zX %04zX\n", + p - start, (int) name->length, name->start, + (size_t) code2->dst, (size_t) code2->src); - } else if (code_name->size == sizeof(njs_vmcode_1addr_t)) { - code1 = (njs_vmcode_1addr_t *) p; + } else if (code_name->size == sizeof(njs_vmcode_1addr_t)) { + code1 = (njs_vmcode_1addr_t *) p; - printf("%05zd %*s %04zX\n", - p - start, (int) name->length, name->start, - (size_t) code1->index); - } + printf("%05zd %*s %04zX\n", + p - start, (int) name->length, name->start, + (size_t) code1->index); + } - p += code_name->size; + p += code_name->size; - goto next; - } + goto next; + } - code_name++; - n--; + code_name++; + n--; } while (n != 0); From xeioex at nginx.com Tue Feb 26 15:24:31 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 26 Feb 2019 15:24:31 +0000 Subject: [njs] Improved parser scope filename. Message-ID: details: https://hg.nginx.org/njs/rev/7345fd14d1b4 branches: changeset: 808:7345fd14d1b4 user: hongzhidao date: Tue Feb 26 17:30:02 2019 +0800 description: Improved parser scope filename. diffstat: njs/njs_parser.c | 11 +++++------ 1 files changed, 5 insertions(+), 6 deletions(-) diffs (30 lines): diff -r 1d6e32892413 -r 7345fd14d1b4 njs/njs_parser.c --- a/njs/njs_parser.c Tue Feb 26 17:32:59 2019 +0800 +++ b/njs/njs_parser.c Tue Feb 26 17:30:02 2019 +0800 @@ -164,9 +164,9 @@ njs_parser(njs_vm_t *vm, njs_parser_t *p static njs_ret_t njs_parser_scope_begin(njs_vm_t *vm, njs_parser_t *parser, njs_scope_t type) { - nxt_int_t ret; nxt_uint_t nesting; nxt_array_t *values; + njs_lexer_t *lexer; njs_parser_scope_t *scope, *parent; nesting = 0; @@ -233,11 +233,10 @@ njs_parser_scope_begin(njs_vm_t *vm, njs scope->values[0] = values; scope->values[1] = NULL; - if (parser->lexer->file.length != 0) { - ret = njs_name_copy(vm, &scope->file, &parser->lexer->file); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + lexer = parser->lexer; + + if (lexer->file.length != 0) { + nxt_file_basename(&lexer->file, &scope->file); } parent = parser->scope; From mdounin at mdounin.ru Tue Feb 26 15:34:46 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 26 Feb 2019 15:34:46 +0000 Subject: [nginx] Updated OpenSSL used for win32 builds. Message-ID: details: https://hg.nginx.org/nginx/rev/8bdf57dfa42d branches: changeset: 7467:8bdf57dfa42d user: Maxim Dounin date: Tue Feb 26 18:01:30 2019 +0300 description: Updated OpenSSL used for win32 builds. diffstat: misc/GNUmakefile | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff --git a/misc/GNUmakefile b/misc/GNUmakefile --- a/misc/GNUmakefile +++ b/misc/GNUmakefile @@ -6,7 +6,7 @@ TEMP = tmp CC = cl OBJS = objs.msvc8 -OPENSSL = openssl-1.0.2q +OPENSSL = openssl-1.1.1b ZLIB = zlib-1.2.11 PCRE = pcre-8.42 From mdounin at mdounin.ru Tue Feb 26 15:34:48 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 26 Feb 2019 15:34:48 +0000 Subject: [nginx] nginx-1.15.9-RELEASE Message-ID: details: https://hg.nginx.org/nginx/rev/d2fd76709909 branches: changeset: 7468:d2fd76709909 user: Maxim Dounin date: Tue Feb 26 18:29:22 2019 +0300 description: nginx-1.15.9-RELEASE diffstat: docs/xml/nginx/changes.xml | 53 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 53 insertions(+), 0 deletions(-) diffs (63 lines): diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml --- a/docs/xml/nginx/changes.xml +++ b/docs/xml/nginx/changes.xml @@ -5,6 +5,59 @@ + + + + +????????? ssl_certificate ? ssl_certificate_key +???????????? ??????????. + + +variables support +in the "ssl_certificate" and "ssl_certificate_key" directives. + + + + + +????? poll ?????? ???????? ?? Windows +??? ????????????? Windows Vista ? ?????. + + +the "poll" method is now available on Windows +when using Windows Vista or newer. + + + + + +???? ??? ????????????? ?????? select ?? Windows +??????????? ?????? ??? ???????????? ?????????? ? ????????, +nginx ?????? ????????? ???????? ?? ???????????? ??????????. + + +if the "select" method was used on Windows +and an error occurred while establishing a backend connection, +nginx waited for the connection establishment timeout to expire. + + + + + +????????? proxy_upload_rate ? proxy_download_rate +? ?????? stream +???????? ??????????? ??? ????????????? UDP-???????. + + +the "proxy_upload_rate" and "proxy_download_rate" directives +in the stream module +worked incorrectly when proxying UDP datagrams. + + + + + + From mdounin at mdounin.ru Tue Feb 26 15:34:50 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 26 Feb 2019 15:34:50 +0000 Subject: [nginx] release-1.15.9 tag Message-ID: details: https://hg.nginx.org/nginx/rev/bd1bba6c0184 branches: changeset: 7469:bd1bba6c0184 user: Maxim Dounin date: Tue Feb 26 18:29:22 2019 +0300 description: release-1.15.9 tag diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -434,3 +434,4 @@ f062e43d74fc2578bb100a9e82a953efa1eb9e4e 2351853ce6867b6166823bdf94333c0a76633c0a release-1.15.6 051a039ce1c7e09144de4a4846669ec7116cecea release-1.15.7 ee551e3f6dba336c0d875e266d7d55385f379b42 release-1.15.8 +d2fd76709909767fc727a5b4affcf1dc9ca488a7 release-1.15.9 From xeioex at nginx.com Wed Feb 27 13:41:24 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 27 Feb 2019 13:41:24 +0000 Subject: [njs] Shell: fixed function redeclarations. Message-ID: details: https://hg.nginx.org/njs/rev/fc69d402ec6d branches: changeset: 810:fc69d402ec6d user: hongzhidao date: Wed Feb 27 17:52:50 2019 +0800 description: Shell: fixed function redeclarations. This closes #108 issue on Github. diffstat: njs/njs_parser.c | 39 +++++++++++++++++++++++++++++---------- njs/njs_parser.h | 4 ++++ njs/njs_variable.c | 2 +- njs/test/njs_expect_test.exp | 12 ++++++++++++ 4 files changed, 46 insertions(+), 11 deletions(-) diffs (119 lines): diff -r 984b7794c5f2 -r fc69d402ec6d njs/njs_parser.c --- a/njs/njs_parser.c Wed Feb 27 17:49:03 2019 +0800 +++ b/njs/njs_parser.c Wed Feb 27 17:52:50 2019 +0800 @@ -565,6 +565,33 @@ njs_parser_labelled_statement(njs_vm_t * } +static njs_function_t * +njs_parser_function_alloc(njs_vm_t *vm, njs_parser_t *parser, + njs_variable_t *var) +{ + njs_value_t *value; + njs_function_t *function; + + function = njs_function_alloc(vm); + if (nxt_slow_path(function == NULL)) { + return NULL; + } + + var->value.data.u.function = function; + var->value.type = NJS_FUNCTION; + var->value.data.truth = 1; + + if (var->index != NJS_INDEX_NONE + && njs_scope_accumulative(vm, parser->scope)) + { + value = (njs_value_t *) var->index; + *value = var->value; + } + + return function; +} + + static njs_token_t njs_parser_function_declaration(njs_vm_t *vm, njs_parser_t *parser) { @@ -613,15 +640,11 @@ njs_parser_function_declaration(njs_vm_t parser->node = node; - function = njs_function_alloc(vm); + function = njs_parser_function_alloc(vm, parser, var); if (nxt_slow_path(function == NULL)) { return NJS_TOKEN_ERROR; } - var->value.data.u.function = function; - var->value.type = NJS_FUNCTION; - var->value.data.truth = 1; - token = njs_parser_function_lambda(vm, parser, function->u.lambda, token); return token; @@ -671,15 +694,11 @@ njs_parser_function_expression(njs_vm_t return token; } - function = njs_function_alloc(vm); + function = njs_parser_function_alloc(vm, parser, var); if (nxt_slow_path(function == NULL)) { return NJS_TOKEN_ERROR; } - var->value.data.u.function = function; - var->value.type = NJS_FUNCTION; - var->value.data.truth = 1; - lambda = function->u.lambda; } else { diff -r 984b7794c5f2 -r fc69d402ec6d njs/njs_parser.h --- a/njs/njs_parser.h Wed Feb 27 17:49:03 2019 +0800 +++ b/njs/njs_parser.h Wed Feb 27 17:52:50 2019 +0800 @@ -379,6 +379,10 @@ njs_parser_global_scope(njs_vm_t *vm) } +#define njs_scope_accumulative(vm, scope) \ + ((vm)->options.accumulative && (scope)->type == NJS_SCOPE_GLOBAL) + + extern const nxt_lvlhsh_proto_t njs_keyword_hash_proto; diff -r 984b7794c5f2 -r fc69d402ec6d njs/njs_variable.c --- a/njs/njs_variable.c Wed Feb 27 17:49:03 2019 +0800 +++ b/njs/njs_variable.c Wed Feb 27 17:52:50 2019 +0800 @@ -508,7 +508,7 @@ njs_scope_next_index(njs_vm_t *vm, njs_p njs_value_t *value; nxt_array_t *values; - if (vm->options.accumulative && scope->type == NJS_SCOPE_GLOBAL) { + if (njs_scope_accumulative(vm, scope)) { /* * When non-clonable VM runs in accumulative mode all * global variables should be allocated in absolute scope diff -r 984b7794c5f2 -r fc69d402ec6d njs/test/njs_expect_test.exp --- a/njs/test/njs_expect_test.exp Wed Feb 27 17:49:03 2019 +0800 +++ b/njs/test/njs_expect_test.exp Wed Feb 27 17:52:50 2019 +0800 @@ -172,6 +172,18 @@ njs_test { "o.a.toDateString*o.a.toLocaleDateString*o.a.toString"} } +# function declarations in interactive mode +njs_test { + {"function a() { return 1; }\r\n" + "undefined\r\n>> "} + {"a();\r\n" + "1\r\n>> "} + {"function a() { return 2; }\r\n" + "undefined\r\n>> "} + {"a();\r\n" + "2\r\n>> "} +} + # console object njs_test { {"console.log()\r\n" From xeioex at nginx.com Wed Feb 27 13:41:23 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 27 Feb 2019 13:41:23 +0000 Subject: [njs] Style. Message-ID: details: https://hg.nginx.org/njs/rev/984b7794c5f2 branches: changeset: 809:984b7794c5f2 user: hongzhidao date: Wed Feb 27 17:49:03 2019 +0800 description: Style. diffstat: njs/njs_lexer_keyword.c | 4 ++-- njs/njs_parser.h | 2 +- njs/njs_variable.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diffs (54 lines): diff -r 7345fd14d1b4 -r 984b7794c5f2 njs/njs_lexer_keyword.c --- a/njs/njs_lexer_keyword.c Tue Feb 26 17:30:02 2019 +0800 +++ b/njs/njs_lexer_keyword.c Wed Feb 27 17:49:03 2019 +0800 @@ -142,7 +142,7 @@ const nxt_lvlhsh_proto_t njs_keyword_ha nxt_int_t -njs_lexer_keywords_init(nxt_mp_t *mcp, nxt_lvlhsh_t *hash) +njs_lexer_keywords_init(nxt_mp_t *mp, nxt_lvlhsh_t *hash) { nxt_uint_t n; nxt_lvlhsh_query_t lhq; @@ -153,7 +153,7 @@ njs_lexer_keywords_init(nxt_mp_t *mcp, n lhq.replace = 0; lhq.proto = &njs_keyword_hash_proto; - lhq.pool = mcp; + lhq.pool = mp; do { lhq.key_hash = nxt_djb_hash(keyword->name.start, keyword->name.length); diff -r 7345fd14d1b4 -r 984b7794c5f2 njs/njs_parser.h --- a/njs/njs_parser.h Tue Feb 26 17:30:02 2019 +0800 +++ b/njs/njs_parser.h Wed Feb 27 17:49:03 2019 +0800 @@ -310,7 +310,7 @@ typedef struct { njs_token_t njs_lexer_token(njs_lexer_t *lexer); void njs_lexer_rollback(njs_lexer_t *lexer); njs_token_t njs_lexer_peek_token(njs_lexer_t *lexer); -nxt_int_t njs_lexer_keywords_init(nxt_mp_t *mcp, nxt_lvlhsh_t *hash); +nxt_int_t njs_lexer_keywords_init(nxt_mp_t *mp, nxt_lvlhsh_t *hash); njs_token_t njs_lexer_keyword(njs_lexer_t *lexer); nxt_int_t njs_parser(njs_vm_t *vm, njs_parser_t *parser, diff -r 7345fd14d1b4 -r 984b7794c5f2 njs/njs_variable.c --- a/njs/njs_variable.c Tue Feb 26 17:30:02 2019 +0800 +++ b/njs/njs_variable.c Wed Feb 27 17:49:03 2019 +0800 @@ -175,7 +175,7 @@ njs_reference_hash_test(nxt_lvlhsh_query } -const nxt_lvlhsh_proto_t njs_reference_hash_proto +const nxt_lvlhsh_proto_t njs_references_hash_proto nxt_aligned(64) = { NXT_LVLHSH_DEFAULT, @@ -205,7 +205,7 @@ njs_variable_reference(njs_vm_t *vm, njs lhq.key_hash = hash; lhq.key = vr->name; - lhq.proto = &njs_reference_hash_proto; + lhq.proto = &njs_references_hash_proto; lhq.replace = 0; lhq.value = node; lhq.pool = vm->mem_pool; From xeioex at nginx.com Wed Feb 27 17:40:43 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 27 Feb 2019 17:40:43 +0000 Subject: [njs] Improved parser syntax error. Message-ID: details: https://hg.nginx.org/njs/rev/d62d0d255b15 branches: changeset: 811:d62d0d255b15 user: hongzhidao date: Tue Feb 26 10:11:53 2019 +0800 description: Improved parser syntax error. diffstat: njs/njs_parser.c | 46 ++++++++++++++++++++++++---------------------- 1 files changed, 24 insertions(+), 22 deletions(-) diffs (65 lines): diff -r fc69d402ec6d -r d62d0d255b15 njs/njs_parser.c --- a/njs/njs_parser.c Wed Feb 27 17:52:50 2019 +0800 +++ b/njs/njs_parser.c Tue Feb 26 10:11:53 2019 +0800 @@ -278,30 +278,28 @@ njs_parser_statement_chain(njs_vm_t *vm, token = njs_parser_statement(vm, parser, token); - if (nxt_fast_path(token > NJS_TOKEN_ILLEGAL)) { - - if (parser->node != NULL) { - /* The statement is not empty block or just semicolon. */ - - node = njs_parser_node_new(vm, parser, NJS_TOKEN_STATEMENT); - if (nxt_slow_path(node == NULL)) { - return NJS_TOKEN_ERROR; - } - - node->left = last; - node->right = parser->node; - *dest = node; - - while (token == NJS_TOKEN_SEMICOLON) { - token = njs_parser_token(parser); - if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { - break; - } + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return njs_parser_unexpected_token(vm, parser, token); + } + + if (parser->node != NULL) { + /* The statement is not empty block or just semicolon. */ + + node = njs_parser_node_new(vm, parser, NJS_TOKEN_STATEMENT); + if (nxt_slow_path(node == NULL)) { + return NJS_TOKEN_ERROR; + } + + node->left = last; + node->right = parser->node; + *dest = node; + + while (token == NJS_TOKEN_SEMICOLON) { + token = njs_parser_token(parser); + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + break; } } - - } else if (!njs_is_error(&vm->retval)) { - (void) njs_parser_unexpected_token(vm, parser, token); } return token; @@ -2830,6 +2828,10 @@ njs_parser_lexer_error(njs_vm_t *vm, njs { va_list args; + if (njs_is_error(&vm->retval)) { + return; + } + va_start(args, fmt); njs_parser_scope_error(vm, parser->scope, type, parser->lexer->line, fmt, args); From xeioex at nginx.com Wed Feb 27 17:40:43 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 27 Feb 2019 17:40:43 +0000 Subject: [njs] Improved njs_value_index(). Message-ID: details: https://hg.nginx.org/njs/rev/4276436234aa branches: changeset: 812:4276436234aa user: hongzhidao date: Tue Feb 26 10:19:14 2019 +0800 description: Improved njs_value_index(). diffstat: njs/njs_string.c | 41 +++++++++++++++++++++++------------------ 1 files changed, 23 insertions(+), 18 deletions(-) diffs (92 lines): diff -r d62d0d255b15 -r 4276436234aa njs/njs_string.c --- a/njs/njs_string.c Tue Feb 26 10:11:53 2019 +0800 +++ b/njs/njs_string.c Tue Feb 26 10:19:14 2019 +0800 @@ -4313,22 +4313,23 @@ uri_error: static nxt_int_t njs_values_hash_test(nxt_lvlhsh_query_t *lhq, void *data) { + u_char *start; njs_value_t *value; value = data; - if (lhq->key.length == sizeof(njs_value_t) - && memcmp(lhq->key.start, value, sizeof(njs_value_t)) == 0) - { - return NXT_OK; + if (lhq->key.length == sizeof(njs_value_t)) { + start = (u_char *) value; + + } else { + /* + * Only primitive values are added into values_hash. + * If size != sizeof(njs_value_t) it is a long string. + */ + start = value->long_string.data->start; } - if (njs_is_string(value) - && value->long_string.size == lhq->key.length - && memcmp(value->long_string.data->start, lhq->key.start, - lhq->key.length) - == 0) - { + if (memcmp(lhq->key.start, start, lhq->key.length) == 0) { return NXT_OK; } @@ -4349,7 +4350,7 @@ static const nxt_lvlhsh_proto_t njs_val /* * Constant values such as njs_value_true are copied to values_hash during - * code generation when them are used as operands to guarantee aligned value. + * code generation when they are used as operands to guarantee aligned value. */ njs_index_t @@ -4358,18 +4359,22 @@ njs_value_index(njs_vm_t *vm, const njs_ u_char *start; uint32_t value_size, size, length; nxt_int_t ret; + nxt_bool_t long_string; njs_value_t *value; njs_string_t *string; nxt_lvlhsh_t *values_hash; nxt_lvlhsh_query_t lhq; - if (src->type != NJS_STRING || src->short_string.size != NJS_STRING_LONG) { + long_string = src->type == NJS_STRING + && src->short_string.size == NJS_STRING_LONG; + + if (long_string) { + size = src->long_string.size; + start = src->long_string.data->start; + + } else { size = sizeof(njs_value_t); start = (u_char *) src; - - } else { - size = src->long_string.size; - start = src->long_string.data->start; } lhq.key_hash = nxt_djb_hash(start, size); @@ -4386,7 +4391,7 @@ njs_value_index(njs_vm_t *vm, const njs_ } else { value_size = 0; - if (start != (u_char *) src) { + if (long_string) { /* Long string value is allocated together with string. */ value_size = sizeof(njs_value_t) + sizeof(njs_string_t); @@ -4406,7 +4411,7 @@ njs_value_index(njs_vm_t *vm, const njs_ *value = *src; - if (start != (u_char *) src) { + if (long_string) { string = (njs_string_t *) ((u_char *) value + sizeof(njs_value_t)); value->long_string.data = string; From xeioex at nginx.com Thu Feb 28 13:09:41 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 28 Feb 2019 13:09:41 +0000 Subject: [njs] Shell: passing original filename to parser. Message-ID: details: https://hg.nginx.org/njs/rev/21925caaa3c5 branches: changeset: 813:21925caaa3c5 user: Dmitry Volyntsev date: Thu Feb 28 15:32:15 2019 +0300 description: Shell: passing original filename to parser. diffstat: njs/njs_shell.c | 19 +++++++++++++------ 1 files changed, 13 insertions(+), 6 deletions(-) diffs (45 lines): diff -r 4276436234aa -r 21925caaa3c5 njs/njs_shell.c --- a/njs/njs_shell.c Tue Feb 26 10:19:14 2019 +0800 +++ b/njs/njs_shell.c Thu Feb 28 15:32:15 2019 +0300 @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -195,6 +196,7 @@ static njs_console_t njs_console; int main(int argc, char **argv) { + char path[MAXPATHLEN], *p; nxt_int_t ret; njs_opts_t opts; njs_vm_opt_t vm_options; @@ -215,14 +217,19 @@ main(int argc, char **argv) nxt_memzero(&vm_options, sizeof(njs_vm_opt_t)); if (!opts.quiet) { - if (opts.file != NULL) { - vm_options.file.start = (u_char *) opts.file; - vm_options.file.length = strlen(opts.file); - nxt_file_basename(&vm_options.file, &vm_options.file); + if (opts.file == NULL) { + p = getcwd(path, sizeof(path)); + if (p == NULL) { + fprintf(stderr, "getcwd() failed:%s\n", strerror(errno)); + return EXIT_FAILURE; + } - } else { - vm_options.file = nxt_string_value("shell"); + memcpy(path + strlen(path), "/shell", sizeof("/shell")); + opts.file = path; } + + vm_options.file.start = (u_char *) opts.file; + vm_options.file.length = strlen(opts.file); } vm_options.init = !opts.interactive; From xeioex at nginx.com Thu Feb 28 17:35:08 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 28 Feb 2019 17:35:08 +0000 Subject: [njs] Fixed lexer referencing in runtime. Message-ID: details: https://hg.nginx.org/njs/rev/33c663d84114 branches: changeset: 814:33c663d84114 user: Dmitry Volyntsev date: Thu Feb 28 19:30:32 2019 +0300 description: Fixed lexer referencing in runtime. diffstat: njs/njs.c | 4 ++++ njs/njs_parser.c | 2 +- njs/njs_regexp.c | 2 +- njs/test/njs_unit_test.c | 3 +++ 4 files changed, 9 insertions(+), 2 deletions(-) diffs (59 lines): diff -r 21925caaa3c5 -r 33c663d84114 njs/njs.c --- a/njs/njs.c Thu Feb 28 15:32:15 2019 +0300 +++ b/njs/njs.c Thu Feb 28 19:30:32 2019 +0300 @@ -255,6 +255,8 @@ njs_vm_compile(njs_vm_t *vm, u_char **st goto fail; } + parser->lexer = NULL; + scope = parser->scope; ret = njs_variables_scope_reference(vm, scope); @@ -327,7 +329,9 @@ njs_vm_clone(njs_vm_t *vm, njs_external_ nvm->mem_pool = nmp; nvm->shared = vm->shared; + nvm->trace = vm->trace; + nvm->trace.data = nvm; nvm->variables_hash = vm->variables_hash; nvm->values_hash = vm->values_hash; diff -r 21925caaa3c5 -r 33c663d84114 njs/njs_parser.c --- a/njs/njs_parser.c Thu Feb 28 15:32:15 2019 +0300 +++ b/njs/njs_parser.c Thu Feb 28 19:30:32 2019 +0300 @@ -2771,7 +2771,7 @@ njs_parser_trace_handler(nxt_trace_t *tr trace = trace->next; p = trace->handler(trace, td, p); - if (vm->parser != NULL) { + if (vm->parser != NULL && vm->parser->lexer != NULL) { lexer = vm->parser->lexer; if (lexer->file.length != 0) { diff -r 21925caaa3c5 -r 33c663d84114 njs/njs_regexp.c --- a/njs/njs_regexp.c Thu Feb 28 15:32:15 2019 +0300 +++ b/njs/njs_regexp.c Thu Feb 28 19:30:32 2019 +0300 @@ -376,7 +376,7 @@ njs_regexp_compile_trace_handler(nxt_tra trace = trace->next; p = trace->handler(trace, td, start); - if (vm->parser != NULL) { + if (vm->parser != NULL && vm->parser->lexer != NULL) { njs_syntax_error(vm, "%*s in %uD", p - start, start, vm->parser->lexer->line); diff -r 21925caaa3c5 -r 33c663d84114 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Thu Feb 28 15:32:15 2019 +0300 +++ b/njs/test/njs_unit_test.c Thu Feb 28 19:30:32 2019 +0300 @@ -6651,6 +6651,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("new RegExp('', 'x')"), nxt_string("SyntaxError: Invalid RegExp flags \"x\"") }, + { nxt_string("new RegExp('[')"), + nxt_string("SyntaxError: pcre_compile(\"[\") failed: missing terminating ] for character class") }, + { nxt_string("[0].map(RegExp().toString)"), nxt_string("TypeError: \"this\" argument is not a regexp") }, From xeioex at nginx.com Thu Feb 28 17:35:08 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 28 Feb 2019 17:35:08 +0000 Subject: [njs] Added additional RegExp tests. Message-ID: details: https://hg.nginx.org/njs/rev/195158f4a6a7 branches: changeset: 815:195158f4a6a7 user: Dmitry Volyntsev date: Thu Feb 28 20:34:47 2019 +0300 description: Added additional RegExp tests. diffstat: njs/test/njs_unit_test.c | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diffs (16 lines): diff -r 33c663d84114 -r 195158f4a6a7 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Thu Feb 28 19:30:32 2019 +0300 +++ b/njs/test/njs_unit_test.c Thu Feb 28 20:34:47 2019 +0300 @@ -6627,6 +6627,12 @@ static njs_unit_test_t njs_test[] = { nxt_string("var r = /LS/i.exec(false); r[0]"), nxt_string("ls") }, + { nxt_string("var r = (/^.+$/mg), s = 'ab\\nc'; [r.exec(s), r.exec(s)]"), + nxt_string("ab,c") }, + + { nxt_string("var r = (/^.+$/mg); [r.global, r.multiline, r.ignoreCase]"), + nxt_string("true,true,false") }, + { nxt_string("var r = /./; r"), nxt_string("/./") },