From mdounin at mdounin.ru Sun Mar 3 14:26:59 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sun, 03 Mar 2019 14:26:59 +0000 Subject: [nginx] Version bump. Message-ID: details: https://hg.nginx.org/nginx/rev/48af42db14ab branches: changeset: 7470:48af42db14ab user: Maxim Dounin date: Sun Mar 03 16:47:41 2019 +0300 description: Version bump. diffstat: src/core/nginx.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1015009 -#define NGINX_VERSION "1.15.9" +#define nginx_version 1015010 +#define NGINX_VERSION "1.15.10" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD From mdounin at mdounin.ru Sun Mar 3 14:27:01 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sun, 03 Mar 2019 14:27:01 +0000 Subject: [nginx] SSL: server name callback changed to return SSL_TLSEXT_ERR_OK. Message-ID: details: https://hg.nginx.org/nginx/rev/7e8bcba6d039 branches: changeset: 7471:7e8bcba6d039 user: Maxim Dounin date: Sun Mar 03 16:47:44 2019 +0300 description: SSL: server name callback changed to return SSL_TLSEXT_ERR_OK. OpenSSL 1.1.1 does not save server name to the session if server name callback returns anything but SSL_TLSEXT_ERR_OK, thus breaking the $ssl_server_name variable in resumed sessions. Since $ssl_server_name can be used even if we've selected the default server and there are no other servers, it looks like the only viable solution is to always return SSL_TLSEXT_ERR_OK regardless of the actual result. To fix things in the stream module as well, added a dummy server name callback which always returns SSL_TLSEXT_ERR_OK. diffstat: src/http/ngx_http_request.c | 12 ++++++------ src/stream/ngx_stream_ssl_module.c | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 6 deletions(-) diffs (93 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 @@ -866,13 +866,13 @@ ngx_http_ssl_servername(ngx_ssl_conn_t * servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name); if (servername == NULL) { - return SSL_TLSEXT_ERR_NOACK; + return SSL_TLSEXT_ERR_OK; } c = ngx_ssl_get_connection(ssl_conn); if (c->ssl->handshaked) { - return SSL_TLSEXT_ERR_NOACK; + return SSL_TLSEXT_ERR_OK; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, @@ -881,13 +881,13 @@ ngx_http_ssl_servername(ngx_ssl_conn_t * host.len = ngx_strlen(servername); if (host.len == 0) { - return SSL_TLSEXT_ERR_NOACK; + return SSL_TLSEXT_ERR_OK; } host.data = (u_char *) servername; if (ngx_http_validate_host(&host, c->pool, 1) != NGX_OK) { - return SSL_TLSEXT_ERR_NOACK; + return SSL_TLSEXT_ERR_OK; } hc = c->data; @@ -896,12 +896,12 @@ ngx_http_ssl_servername(ngx_ssl_conn_t * NULL, &cscf) != NGX_OK) { - return SSL_TLSEXT_ERR_NOACK; + return SSL_TLSEXT_ERR_OK; } hc->ssl_servername = ngx_palloc(c->pool, sizeof(ngx_str_t)); if (hc->ssl_servername == NULL) { - return SSL_TLSEXT_ERR_NOACK; + return SSL_TLSEXT_ERR_OK; } *hc->ssl_servername = host; 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_CTRL_SET_TLSEXT_HOSTNAME +int ngx_stream_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg); +#endif #ifdef SSL_R_CERT_CB_ERROR static int ngx_stream_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg); #endif @@ -414,6 +417,17 @@ ngx_stream_ssl_handshake_handler(ngx_con } +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + +int +ngx_stream_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) +{ + return SSL_TLSEXT_ERR_OK; +} + +#endif + + #ifdef SSL_R_CERT_CB_ERROR int @@ -682,6 +696,11 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf cln->handler = ngx_ssl_cleanup_ctx; cln->data = &conf->ssl; +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + SSL_CTX_set_tlsext_servername_callback(conf->ssl.ctx, + ngx_stream_ssl_servername); +#endif + if (ngx_stream_ssl_compile_certificates(cf, conf) != NGX_OK) { return NGX_CONF_ERROR; } From mdounin at mdounin.ru Sun Mar 3 14:27:03 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sun, 03 Mar 2019 14:27:03 +0000 Subject: [nginx] SSL: server name callback changed to return fatal errors. Message-ID: details: https://hg.nginx.org/nginx/rev/d430babbe643 branches: changeset: 7472:d430babbe643 user: Maxim Dounin date: Sun Mar 03 16:48:06 2019 +0300 description: SSL: server name callback changed to return fatal errors. Notably this affects various allocation errors, and should generally improve things if an allocation error actually happens during a callback. Depending on the OpenSSL version, returning an error can result in either SSL_R_CALLBACK_FAILED or SSL_R_CLIENTHELLO_TLSEXT error from SSL_do_handshake(), so both errors were switched to the "info" level. diffstat: src/event/ngx_event_openssl.c | 6 ++++++ src/http/ngx_http_request.c | 29 ++++++++++++++++++++++------- 2 files changed, 28 insertions(+), 7 deletions(-) diffs (82 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 @@ -2855,9 +2855,15 @@ ngx_ssl_connection_error(ngx_connection_ || n == SSL_R_NO_COMPRESSION_SPECIFIED /* 187 */ || n == SSL_R_NO_SHARED_CIPHER /* 193 */ || n == SSL_R_RECORD_LENGTH_MISMATCH /* 213 */ +#ifdef SSL_R_CLIENTHELLO_TLSEXT + || n == SSL_R_CLIENTHELLO_TLSEXT /* 226 */ +#endif #ifdef SSL_R_PARSE_TLSEXT || n == SSL_R_PARSE_TLSEXT /* 227 */ #endif +#ifdef SSL_R_CALLBACK_FAILED + || n == SSL_R_CALLBACK_FAILED /* 234 */ +#endif || n == SSL_R_UNEXPECTED_MESSAGE /* 244 */ || n == SSL_R_UNEXPECTED_RECORD /* 245 */ || n == SSL_R_UNKNOWN_ALERT_TYPE /* 246 */ 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 @@ -855,6 +855,7 @@ ngx_http_ssl_handshake_handler(ngx_conne int ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) { + ngx_int_t rc; ngx_str_t host; const char *servername; ngx_connection_t *c; @@ -872,7 +873,8 @@ ngx_http_ssl_servername(ngx_ssl_conn_t * c = ngx_ssl_get_connection(ssl_conn); if (c->ssl->handshaked) { - return SSL_TLSEXT_ERR_OK; + *ad = SSL_AD_NO_RENEGOTIATION; + return SSL_TLSEXT_ERR_ALERT_FATAL; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, @@ -886,22 +888,35 @@ ngx_http_ssl_servername(ngx_ssl_conn_t * host.data = (u_char *) servername; - if (ngx_http_validate_host(&host, c->pool, 1) != NGX_OK) { + rc = ngx_http_validate_host(&host, c->pool, 1); + + if (rc == NGX_ERROR) { + *ad = SSL_AD_INTERNAL_ERROR; + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + + if (rc == NGX_DECLINED) { return SSL_TLSEXT_ERR_OK; } hc = c->data; - if (ngx_http_find_virtual_server(c, hc->addr_conf->virtual_names, &host, - NULL, &cscf) - != NGX_OK) - { + rc = ngx_http_find_virtual_server(c, hc->addr_conf->virtual_names, &host, + NULL, &cscf); + + if (rc == NGX_ERROR) { + *ad = SSL_AD_INTERNAL_ERROR; + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + + if (rc == NGX_DECLINED) { return SSL_TLSEXT_ERR_OK; } hc->ssl_servername = ngx_palloc(c->pool, sizeof(ngx_str_t)); if (hc->ssl_servername == NULL) { - return SSL_TLSEXT_ERR_OK; + *ad = SSL_AD_INTERNAL_ERROR; + return SSL_TLSEXT_ERR_ALERT_FATAL; } *hc->ssl_servername = host; From mdounin at mdounin.ru Sun Mar 3 14:27:04 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sun, 03 Mar 2019 14:27:04 +0000 Subject: [nginx] SSL: fixed potential leak on memory allocation errors. Message-ID: details: https://hg.nginx.org/nginx/rev/8981dbb12254 branches: changeset: 7473:8981dbb12254 user: Maxim Dounin date: Sun Mar 03 16:48:39 2019 +0300 description: SSL: fixed potential leak on memory allocation errors. If ngx_pool_cleanup_add() fails, we have to clean just created SSL context manually, thus appropriate call added. Additionally, ngx_pool_cleanup_add() moved closer to ngx_ssl_create() in the ngx_http_ssl_module, to make sure there are no leaks due to intermediate code. diffstat: src/http/modules/ngx_http_grpc_module.c | 1 + src/http/modules/ngx_http_proxy_module.c | 1 + src/http/modules/ngx_http_ssl_module.c | 17 +++++++++-------- src/http/modules/ngx_http_uwsgi_module.c | 1 + src/mail/ngx_mail_ssl_module.c | 1 + src/stream/ngx_stream_proxy_module.c | 1 + src/stream/ngx_stream_ssl_module.c | 1 + 7 files changed, 15 insertions(+), 8 deletions(-) diffs (100 lines): diff --git a/src/http/modules/ngx_http_grpc_module.c b/src/http/modules/ngx_http_grpc_module.c --- a/src/http/modules/ngx_http_grpc_module.c +++ b/src/http/modules/ngx_http_grpc_module.c @@ -4650,6 +4650,7 @@ ngx_http_grpc_set_ssl(ngx_conf_t *cf, ng cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { + ngx_ssl_cleanup_ctx(glcf->upstream.ssl); return NGX_ERROR; } diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -4270,6 +4270,7 @@ ngx_http_proxy_set_ssl(ngx_conf_t *cf, n cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { + ngx_ssl_cleanup_ctx(plcf->upstream.ssl); return NGX_ERROR; } 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 @@ -700,6 +700,15 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * return NGX_CONF_ERROR; } + cln = ngx_pool_cleanup_add(cf->pool, 0); + if (cln == NULL) { + ngx_ssl_cleanup_ctx(&conf->ssl); + return NGX_CONF_ERROR; + } + + cln->handler = ngx_ssl_cleanup_ctx; + cln->data = &conf->ssl; + #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME if (SSL_CTX_set_tlsext_servername_callback(conf->ssl.ctx, @@ -723,14 +732,6 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * ngx_http_ssl_npn_advertised, NULL); #endif - cln = ngx_pool_cleanup_add(cf->pool, 0); - if (cln == NULL) { - return NGX_CONF_ERROR; - } - - cln->handler = ngx_ssl_cleanup_ctx; - cln->data = &conf->ssl; - if (ngx_http_ssl_compile_certificates(cf, conf) != NGX_OK) { return NGX_CONF_ERROR; } diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c --- a/src/http/modules/ngx_http_uwsgi_module.c +++ b/src/http/modules/ngx_http_uwsgi_module.c @@ -2359,6 +2359,7 @@ ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, n cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { + ngx_ssl_cleanup_ctx(uwcf->upstream.ssl); return NGX_ERROR; } 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 @@ -370,6 +370,7 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { + ngx_ssl_cleanup_ctx(&conf->ssl); return NGX_CONF_ERROR; } diff --git a/src/stream/ngx_stream_proxy_module.c b/src/stream/ngx_stream_proxy_module.c --- a/src/stream/ngx_stream_proxy_module.c +++ b/src/stream/ngx_stream_proxy_module.c @@ -2096,6 +2096,7 @@ ngx_stream_proxy_set_ssl(ngx_conf_t *cf, cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { + ngx_ssl_cleanup_ctx(pscf->ssl); return NGX_ERROR; } 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 @@ -690,6 +690,7 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { + ngx_ssl_cleanup_ctx(&conf->ssl); return NGX_CONF_ERROR; } From mdounin at mdounin.ru Sun Mar 3 14:27:06 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sun, 03 Mar 2019 14:27:06 +0000 Subject: [nginx] SSL: use of the SSL_OP_NO_CLIENT_RENEGOTIATION option. Message-ID: details: https://hg.nginx.org/nginx/rev/3f1db95d758a branches: changeset: 7474:3f1db95d758a user: Maxim Dounin date: Sun Mar 03 16:49:02 2019 +0300 description: SSL: use of the SSL_OP_NO_CLIENT_RENEGOTIATION option. The SSL_OP_NO_CLIENT_RENEGOTIATION option was introduced in LibreSSL 2.5.1. Unlike OpenSSL's SSL_OP_NO_RENEGOTIATION, it only disables client-initiated renegotiation, and hence can be safely used on all SSL contexts. diffstat: src/event/ngx_event_openssl.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diffs (14 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 @@ -368,6 +368,10 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_ SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_ANTI_REPLAY); #endif +#ifdef SSL_OP_NO_CLIENT_RENEGOTIATION + SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_CLIENT_RENEGOTIATION); +#endif + #ifdef SSL_MODE_RELEASE_BUFFERS SSL_CTX_set_mode(ssl->ctx, SSL_MODE_RELEASE_BUFFERS); #endif From Maciej.Grochowski at sony.com Sun Mar 3 21:33:57 2019 From: Maciej.Grochowski at sony.com (Maciej.Grochowski at sony.com) Date: Sun, 3 Mar 2019 21:33:57 +0000 Subject: Why Subrequests are get only? Message-ID: <0B243603C69C594B878E7AED7774F3760565B73B@USCULXMSG15.am.sony.com> I am trying to use mirror module for multiple requests, one usecase that I am interested in is sending PUT request to additional/mirror location. During that process I realized that PUT request became GET. When I took deeper look on subrequest function "ngx_http_subrequest(...)" I noticed that new request is always setup as GET. I was expecting behavior to be something like: --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -2297,8 +2297,11 @@ ngx_http_subrequest(ngx_http_request_t *r, #if (NGX_HTTP_V2) sr->stream = r->stream; #endif - - sr->method = NGX_HTTP_GET; + if (r->method != 0) { + sr->method = r->method; + } else { + sr->method = NGX_HTTP_GET; + } sr->http_version = r->http_version; sr->request_line = r->request_line; @@ -2314,9 +2317,14 @@ ngx_http_subrequest(ngx_http_request_t *r, sr->subrequest_in_memory = (flags & NGX_HTTP_SUBREQUEST_IN_MEMORY) != 0; sr->waited = (flags & NGX_HTTP_SUBREQUEST_WAITED) != 0; sr->background = (flags & NGX_HTTP_SUBREQUEST_BACKGROUND) != 0; sr->unparsed_uri = r->unparsed_uri; - sr->method_name = ngx_http_core_get_method; + + if (r->method_name.data != NULL) { + sr->method_name.len = ngx_strlen(r->method_name.data); + sr->method_name.data = r->method_name.data; + } else { + sr->method_name = ngx_http_core_get_method; + } sr->http_protocol = r->http_protocol; sr->schema = r->schema; What is the reason that I am missing and make Subrequests suitable for GET only requests? Thank you Maciej -------------- next part -------------- An HTML attachment was scrubbed... URL: From bouzid.anas.1 at gmail.com Mon Mar 4 05:05:02 2019 From: bouzid.anas.1 at gmail.com (Anas Bouzid) Date: Mon, 4 Mar 2019 06:05:02 +0100 Subject: MIME: add application/manifest+json type Message-ID: # HG changeset patch # User Anas Bouzid # Date 1551674425 -3600 # Mon Mar 04 05:40:25 2019 +0100 # Node ID 4424fc3aec3eb5de188de2f95adcbf095bf14816 # Parent 3f1db95d758ab6b331065e99df47666bb1ed5e06 MIME: add application/manifest+json type The .webmanifest extension should be served using the application/manifest+json MIME type. https://w3c.github.io/manifest/#media-type-registration diff -r 3f1db95d758a -r 4424fc3aec3e conf/mime.types --- a/conf/mime.types Sun Mar 03 16:49:02 2019 +0300 +++ b/conf/mime.types Mon Mar 04 05:40:25 2019 +0100 @@ -30,6 +30,7 @@ application/java-archive jar war ear; application/json json; application/mac-binhex40 hqx; + application/manifest+json webmanifest; application/msword doc; application/pdf pdf; application/postscript ps eps ai; -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Mon Mar 4 13:33:18 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 4 Mar 2019 16:33:18 +0300 Subject: Why Subrequests are get only? In-Reply-To: <0B243603C69C594B878E7AED7774F3760565B73B@USCULXMSG15.am.sony.com> References: <0B243603C69C594B878E7AED7774F3760565B73B@USCULXMSG15.am.sony.com> Message-ID: <20190304133318.GR1877@mdounin.ru> Hello! On Sun, Mar 03, 2019 at 09:33:57PM +0000, Maciej.Grochowski at sony.com wrote: > I am trying to use mirror module for multiple requests, one usecase that I am interested in is sending PUT request to additional/mirror location. > > During that process I realized that PUT request became GET. > When I took deeper look on subrequest function "ngx_http_subrequest(...)" I noticed that new request is always setup as GET. > I was expecting behavior to be something like: [...] > What is the reason that I am missing and make Subrequests suitable for GET only requests? Subrequests were originally developed to for the SSI include command, and they are expected to return content of a particular resource - that is, they are GET. If you want them to act differently, you can modify the method after a subrequest is created and/or use the NGX_HTTP_SUBREQUEST_CLONE flag. -- Maxim Dounin http://mdounin.ru/ From mdounin at mdounin.ru Mon Mar 4 14:07:17 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 4 Mar 2019 17:07:17 +0300 Subject: MIME: add application/manifest+json type In-Reply-To: References: Message-ID: <20190304140717.GS1877@mdounin.ru> Hello! On Mon, Mar 04, 2019 at 06:05:02AM +0100, Anas Bouzid wrote: > # HG changeset patch > # User Anas Bouzid > # Date 1551674425 -3600 > # Mon Mar 04 05:40:25 2019 +0100 > # Node ID 4424fc3aec3eb5de188de2f95adcbf095bf14816 > # Parent 3f1db95d758ab6b331065e99df47666bb1ed5e06 > MIME: add application/manifest+json type > > The .webmanifest extension should be served using > the application/manifest+json MIME type. > https://w3c.github.io/manifest/#media-type-registration > > diff -r 3f1db95d758a -r 4424fc3aec3e conf/mime.types > --- a/conf/mime.types Sun Mar 03 16:49:02 2019 +0300 > +++ b/conf/mime.types Mon Mar 04 05:40:25 2019 +0100 > @@ -30,6 +30,7 @@ > application/java-archive jar war ear; > application/json json; > application/mac-binhex40 hqx; > + application/manifest+json webmanifest; > application/msword doc; > application/pdf pdf; > application/postscript ps eps ai; Thanks for the patch. For the record: - The application/manifest+json is not something officially registered (https://www.iana.org/assignments/media-types/media-types.xhtml). - The specification does not seem to be complete, only a working draft is available. - The MIME type isn't present in Apache mime.types (http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types). Note that we generally only add most popular types to the mime.types as shipped with nginx. It currently doesn't look like the "application/manifest+json" type qualify. Note that if you want to add additional types or serve some files with specific custom types, you can do so using the "types" directive, see http://nginx.org/r/types for examples. -- Maxim Dounin http://mdounin.ru/ From lists at packetmail.net Mon Mar 4 19:06:58 2019 From: lists at packetmail.net (Community Proposed) Date: Mon, 04 Mar 2019 13:06:58 -0600 Subject: Proposed patch to enforce STARTTLS before MAIL FROM Message-ID: <09c649309d9c30592b8937cb14f49cf5@www.packetmail.net> Hello, in nginx 1.14.2 using a configuration directive of 'starttls only;' and 'smtp_auth none;' I noticed this was only applied to the AUTH section of the SMTP transaction. I have written the below to be applied to the MAIL FROM section which should be enforced over STARTTLS. MAIL FROM should occur before RCPT TO and DATA to avoid out of sequence errors. Scenarios where the patch changes would be seen in the real world would be for NGINX in front of an MTA which is the final destination. Without enforcing STARTTLS before the MAIL FROM the full conversation inclusive of the DATA command can occur in clear text during testing. --- /tmp/nginx-1.14.2/src/mail/ngx_mail_smtp_handler.c 2018-12-04 09:52:24.000000000 -0500 +++ /root/src/nginx-1.14.2/src/mail/ngx_mail_smtp_handler.c 2019-03-04 13:27:56.514409692 -0500 @@ -46,7 +46,7 @@ static u_char smtp_invalid_argument[] = "501 5.5.4 Invalid argument" CRLF; static u_char smtp_auth_required[] = "530 5.7.1 Authentication required" CRLF; static u_char smtp_bad_sequence[] = "503 5.5.1 Bad sequence of commands" CRLF; - +static u_char smtp_tls_required[] = "530 5.7.0 Must issue a STARTTLS command first" CRLF; static ngx_str_t smtp_unavailable = ngx_string("[UNAVAILABLE]"); static ngx_str_t smtp_tempunavail = ngx_string("[TEMPUNAVAIL]"); @@ -441,6 +441,13 @@ break; case NGX_SMTP_MAIL: +/* Nathan Fowler , 2019-03-04 */ +#if (NGX_MAIL_SSL) + if (ngx_mail_starttls_only(s, c)) { + ngx_str_set(&s->out, smtp_tls_required); + break; + } +#endif rc = ngx_mail_smtp_mail(s, c); Cheers, Nathan From xeioex at nginx.com Tue Mar 5 09:51:29 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 05 Mar 2019 09:51:29 +0000 Subject: [njs] Style. Message-ID: details: https://hg.nginx.org/njs/rev/109697757094 branches: changeset: 816:109697757094 user: hongzhidao date: Tue Mar 05 08:32:54 2019 +0800 description: Style. diffstat: njs/njs_lexer.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (21 lines): diff -r 195158f4a6a7 -r 109697757094 njs/njs_lexer.c --- a/njs/njs_lexer.c Thu Feb 28 20:34:47 2019 +0300 +++ b/njs/njs_lexer.c Tue Mar 05 08:32:54 2019 +0800 @@ -244,7 +244,7 @@ static const njs_lexer_multi_t njs_less }; -static const njs_lexer_multi_t njs_less_equal_token[] = { +static const njs_lexer_multi_t njs_strict_equal_token[] = { { '=', NJS_TOKEN_STRICT_EQUAL, 0, NULL }, }; @@ -268,7 +268,7 @@ static const njs_lexer_multi_t njs_grea static const njs_lexer_multi_t njs_assignment_token[] = { - { '=', NJS_TOKEN_EQUAL, 1, njs_less_equal_token }, + { '=', NJS_TOKEN_EQUAL, 1, njs_strict_equal_token }, }; From mdounin at mdounin.ru Tue Mar 5 13:56:07 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 05 Mar 2019 13:56:07 +0000 Subject: [nginx] SSL: moved c->ssl->handshaked check in server name callback. Message-ID: details: https://hg.nginx.org/nginx/rev/49f9d2f7d887 branches: changeset: 7475:49f9d2f7d887 user: Maxim Dounin date: Tue Mar 05 16:34:19 2019 +0300 description: SSL: moved c->ssl->handshaked check in server name callback. Server name callback is always called by OpenSSL, even if server_name extension is not present in ClientHello. As such, checking c->ssl->handshaked before the SSL_get_servername() result should help to more effectively prevent renegotiation in OpenSSL 1.1.0 - 1.1.0g, where neither SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS nor SSL_OP_NO_RENEGOTIATION is available. diffstat: src/http/ngx_http_request.c | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diffs (29 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 @@ -864,12 +864,6 @@ ngx_http_ssl_servername(ngx_ssl_conn_t * ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; - servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name); - - if (servername == NULL) { - return SSL_TLSEXT_ERR_OK; - } - c = ngx_ssl_get_connection(ssl_conn); if (c->ssl->handshaked) { @@ -877,6 +871,12 @@ ngx_http_ssl_servername(ngx_ssl_conn_t * return SSL_TLSEXT_ERR_ALERT_FATAL; } + servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name); + + if (servername == NULL) { + return SSL_TLSEXT_ERR_OK; + } + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "SSL server name: \"%s\"", servername); From xeioex at nginx.com Tue Mar 5 16:54:51 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 05 Mar 2019 16:54:51 +0000 Subject: [njs] Fixed RegExp literal parsing. Message-ID: details: https://hg.nginx.org/njs/rev/acc5fc4be35b branches: changeset: 817:acc5fc4be35b user: Dmitry Volyntsev date: Tue Mar 05 19:54:23 2019 +0300 description: Fixed RegExp literal parsing. diffstat: njs/njs_regexp.c | 11 ++++++----- njs/test/njs_unit_test.c | 15 +++++++++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diffs (55 lines): diff -r 109697757094 -r acc5fc4be35b njs/njs_regexp.c --- a/njs/njs_regexp.c Tue Mar 05 08:32:54 2019 +0800 +++ b/njs/njs_regexp.c Tue Mar 05 19:54:23 2019 +0300 @@ -138,7 +138,7 @@ njs_regexp_create(njs_vm_t *vm, njs_valu njs_token_t njs_regexp_literal(njs_vm_t *vm, njs_parser_t *parser, njs_value_t *value) { - u_char *p; + u_char *p, c; njs_lexer_t *lexer; njs_regexp_flags_t flags; njs_regexp_pattern_t *pattern; @@ -147,12 +147,13 @@ njs_regexp_literal(njs_vm_t *vm, njs_par for (p = lexer->start; p < lexer->end; p++) { - if (*p == '\\') { - p++; - continue; + c = *p; + + if (c == '\n' || c == '\r') { + break; } - if (*p == '/') { + if (c == '/' && !(p > lexer->start && p[-1] == '\\')) { lexer->text.start = lexer->start; lexer->text.length = p - lexer->text.start; p++; diff -r 109697757094 -r acc5fc4be35b njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Tue Mar 05 08:32:54 2019 +0800 +++ b/njs/test/njs_unit_test.c Tue Mar 05 19:54:23 2019 +0300 @@ -6526,6 +6526,21 @@ static njs_unit_test_t njs_test[] = { nxt_string("/"), nxt_string("SyntaxError: Unterminated RegExp \"/\" in 1") }, + { nxt_string("/a\n/"), + nxt_string("SyntaxError: Unterminated RegExp \"/a\" in 1") }, + + { nxt_string("/a\r/"), + nxt_string("SyntaxError: Unterminated RegExp \"/a\" in 1") }, + + { nxt_string("/a\\q/"), + nxt_string("/a\\q/") }, + + { nxt_string("/a\\q/.test('a\\q')"), + nxt_string("true") }, + + { nxt_string("/(\\.(?!com|org)|\\/)/.test('ah.info')"), + nxt_string("true") }, + { nxt_string("/(/.test('')"), nxt_string("SyntaxError: pcre_compile(\"(\") failed: missing ) in 1") }, From mdounin at mdounin.ru Tue Mar 5 18:23:03 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 5 Mar 2019 21:23:03 +0300 Subject: Proposed patch to enforce STARTTLS before MAIL FROM In-Reply-To: <09c649309d9c30592b8937cb14f49cf5@www.packetmail.net> References: <09c649309d9c30592b8937cb14f49cf5@www.packetmail.net> Message-ID: <20190305182303.GW1877@mdounin.ru> Hello! On Mon, Mar 04, 2019 at 01:06:58PM -0600, Community Proposed via nginx-devel wrote: > Hello, in nginx 1.14.2 using a configuration directive of 'starttls only;' and > 'smtp_auth none;' I noticed this was only applied to the AUTH section of the > SMTP transaction. I have written the below to be applied to the MAIL FROM > section which should be enforced over STARTTLS. MAIL FROM should occur before > RCPT TO and DATA to avoid out of sequence errors. Scenarios where the patch > changes would be seen in the real world would be for NGINX in front of an MTA > which is the final destination. Without enforcing STARTTLS before the MAIL > FROM the full conversation inclusive of the DATA command can occur in clear > text during testing. Not sure it is a good change. The main goal of "starttls only;" used to be to ensure that authenticated clients are using encryption and client credentials are not transferred in clear text. While "smtp_auth none;" is to be used on public SMTP servers, and RFC 3207 clearly says that: A publicly-referenced SMTP server MUST NOT require use of the STARTTLS extension in order to deliver mail locally. This rule prevents the STARTTLS extension from damaging the interoperability of the Internet's SMTP infrastructure. For example, with starttls only; smtp_auth none plain; current behaviour is to require SSL/TLS for authentication, but allow non-encrypted connections without authentication for mail delivery. This matches RFC 3207 requirements out of the box. With the suggested change such a configuration would violate the above "MUST NOT" clause of RFC 3207. Moreover, it would be impossible to configure nginx with a single listening socket to accept only encrypted connections from clients, while accepting mail delivery without encryption as required by RFC 3207. If you want unathenticated clients to use SSL/TLS encryption, a better solution might be to enforce this requirement with auth_http script. [...] -- Maxim Dounin http://mdounin.ru/ From lists at packetmail.net Tue Mar 5 19:48:06 2019 From: lists at packetmail.net (lists at packetmail.net) Date: Tue, 5 Mar 2019 13:48:06 -0600 Subject: Proposed patch to enforce STARTTLS before MAIL FROM In-Reply-To: <20190305182303.GW1877@mdounin.ru> Message-ID: <9deabc11-ae8a-32db-44eb-9ba5fd17a4be@packetmail.net> On 3/5/19 12:23 PM, Maxim Dounin wrote: > Not sure it is a good change. Thank you for your detailed reply and explanation.? I agree with you on all facets with respect to RFC compliance.? I believe the core issue at hand is the antiquated language in the current RFC conflicting with common practice -- several final destination MTAs on the public Internet, depending on their role/use, do require and enforce TLS communication only either on a per-sender, per-recipient, or per-server basis.? That said your rationale for rejecting the patch is accurate and mirrors similar expressed in Postfix at www.postfix.org/postconf.5.html#smtpd_tls_security_level regarding 'encypt'. If you find the proposed patch satisfactory from a technical aspect I will commit the patch locally for a specific use case which would fall under the category of 'dedicated servers'. For your consideration, perhaps a configuration option of: starttls dedicated; With the proposed patch would meet both a use case and RFC requirement aspect.Thanks, Nathan From xeioex at nginx.com Wed Mar 6 16:40:37 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 06 Mar 2019 16:40:37 +0000 Subject: [njs] Correctly setting length of UTF8 string in fs.readFileSync(). Message-ID: details: https://hg.nginx.org/njs/rev/bfd57048376e branches: changeset: 818:bfd57048376e user: Dmitry Volyntsev date: Wed Mar 06 19:39:21 2019 +0300 description: Correctly setting length of UTF8 string in fs.readFileSync(). This closes #109 issue on Github. diffstat: njs/njs_fs.c | 22 ++++++++++++++++- njs/test/fs/ascii | 1 + njs/test/fs/non_utf8 | 1 + njs/test/fs/utf8 | 1 + njs/test/njs_expect_test.exp | 52 ++++++++++++++++++++++++++----------------- njs/test/non_utf8 | 1 - 6 files changed, 54 insertions(+), 24 deletions(-) diffs (210 lines): diff -r acc5fc4be35b -r bfd57048376e njs/njs_fs.c --- a/njs/njs_fs.c Tue Mar 05 19:54:23 2019 +0300 +++ b/njs/njs_fs.c Wed Mar 06 19:39:21 2019 +0300 @@ -213,6 +213,16 @@ njs_fs_read_file(njs_vm_t *vm, njs_value if (encoding.length != 0) { length = sb.st_size; + if (length > NJS_STRING_MAP_STRIDE) { + /* + * At this point length is not known, in order to set it to + * the correct value after file is read, we need to ensure that + * offset_map is allocated by njs_string_alloc(). This can be + * achieved by making length != size. + */ + length += 1; + } + } else { length = 0; } @@ -245,7 +255,6 @@ njs_fs_read_file(njs_vm_t *vm, njs_value length = nxt_utf8_length(start, sb.st_size); if (length >= 0) { - njs_string_offset_map_init(start, sb.st_size); njs_string_length_set(&arguments[2], length); } else { @@ -408,6 +417,16 @@ njs_fs_read_file_sync(njs_vm_t *vm, njs_ if (encoding.length != 0) { length = sb.st_size; + if (length > NJS_STRING_MAP_STRIDE) { + /* + * At this point length is not known, in order to set it to + * the correct value after file is read, we need to ensure that + * offset_map is allocated by njs_string_alloc(). This can be + * achieved by making length != size. + */ + length += 1; + } + } else { length = 0; } @@ -440,7 +459,6 @@ njs_fs_read_file_sync(njs_vm_t *vm, njs_ length = nxt_utf8_length(start, sb.st_size); if (length >= 0) { - njs_string_offset_map_init(start, sb.st_size); njs_string_length_set(&vm->retval, length); } else { diff -r acc5fc4be35b -r bfd57048376e njs/test/fs/ascii --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/njs/test/fs/ascii Wed Mar 06 19:39:21 2019 +0300 @@ -0,0 +1,1 @@ +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \ No newline at end of file diff -r acc5fc4be35b -r bfd57048376e njs/test/fs/non_utf8 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/njs/test/fs/non_utf8 Wed Mar 06 19:39:21 2019 +0300 @@ -0,0 +1,1 @@ +?? \ No newline at end of file diff -r acc5fc4be35b -r bfd57048376e njs/test/fs/utf8 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/njs/test/fs/utf8 Wed Mar 06 19:39:21 2019 +0300 @@ -0,0 +1,1 @@ +????Z?? \ No newline at end of file diff -r acc5fc4be35b -r bfd57048376e njs/test/njs_expect_test.exp --- a/njs/test/njs_expect_test.exp Tue Mar 05 19:54:23 2019 +0300 +++ b/njs/test/njs_expect_test.exp Wed Mar 06 19:39:21 2019 +0300 @@ -367,10 +367,6 @@ njs_test { # require('fs') -set file [open njs_test_file w] -puts -nonewline $file "????Z??" -flush $file - njs_test { {"var fs = require('fs')\r\n" "undefined\r\n>> "} @@ -383,37 +379,44 @@ njs_test { njs_test { {"var fs = require('fs')\r\n" "undefined\r\n>> "} - {"fs.readFile('njs_test_file', 'utf8', function (e, data) {console.log(data[2]+data.length)})\r\n" + {"fs.readFile('njs/test/fs/utf8', 'utf8', function (e, data) {console.log(data[2]+data.length)})\r\n" "'Z4'\r\nundefined\r\n>> "} } njs_test { {"var fs = require('fs')\r\n" "undefined\r\n>> "} - {"fs.readFile('njs_test_file', function (e, data) {console.log(data[4]+data.length)})\r\n" + {"fs.readFile('njs/test/fs/utf8', function (e, data) {console.log(data[4]+data.length)})\r\n" "'Z7'\r\nundefined\r\n>> "} } njs_test { {"var fs = require('fs')\r\n" "undefined\r\n>> "} - {"fs.readFile('njs_test_file', {encoding:'utf8',flag:'r+'}, function (e, data) {console.log(data)})\r\n" + {"fs.readFile('njs/test/fs/utf8', {encoding:'utf8',flag:'r+'}, function (e, data) {console.log(data)})\r\n" "'????Z??'\r\nundefined\r\n>> "} } -exec rm -fr njs_unknown_path - njs_test { - {"var fs = require('fs'); \r\n" + {"var fs = require('fs')\r\n" "undefined\r\n>> "} - {"fs.readFile('njs_unknown_path', 'utf8', function (e) {console.log(JSON.stringify(e))})\r\n" - "'{\"errno\":2,\"path\":\"njs_unknown_path\",\"syscall\":\"open\"}'\r\nundefined\r\n>> "} + {"fs.readFile('njs/test/fs/ascii', function (e, data) {console.log(data[599])})\r\n" + "'x'\r\nundefined\r\n>> "} + {"fs.readFile('njs/test/fs/ascii', {encoding:'utf8',flag:'r+'}, function (e, data) {console.log(data[599])})\r\n" + "'x'\r\nundefined\r\n>> "} } njs_test { {"var fs = require('fs'); \r\n" "undefined\r\n>> "} - {"fs.readFile('njs_unknown_path', {encoding:'utf8', flag:'r+'}, function (e) {console.log(e)})\r\n" + {"fs.readFile('njs/test/fs/nonexistent', 'utf8', function (e) {console.log(JSON.stringify(e))})\r\n" + "'{\"errno\":2,\"path\":\"njs/test/fs/nonexistent\",\"syscall\":\"open\"}'\r\nundefined\r\n>> "} +} + +njs_test { + {"var fs = require('fs'); \r\n" + "undefined\r\n>> "} + {"fs.readFile('njs/test/fs/nonexistent', {encoding:'utf8', flag:'r+'}, function (e) {console.log(e)})\r\n" "Error: No such file or directory\r\nundefined\r\n>> "} } @@ -422,49 +425,56 @@ njs_test { njs_test { {"var fs = require('fs')\r\n" "undefined\r\n>> "} - {"fs.readFileSync('njs_test_file').toString('base64')\r\n" + {"fs.readFileSync('njs/test/fs/utf8').toString('base64')\r\n" "'zrHOslrOsw=='\r\n>> "} } njs_test { {"var fs = require('fs')\r\n" "undefined\r\n>> "} - {"fs.readFileSync('njs_test_file', 'utf8')[2]\r\n" + {"fs.readFileSync('njs/test/fs/utf8', 'utf8')[2]\r\n" "'Z'\r\n>> "} } njs_test { {"var fs = require('fs')\r\n" "undefined\r\n>> "} - {"fs.readFileSync('njs_test_file')[4]\r\n" + {"fs.readFileSync('njs/test/fs/utf8')[4]\r\n" "'Z'\r\n>> "} } njs_test { {"var fs = require('fs')\r\n" "undefined\r\n>> "} - {"fs.readFileSync('njs_test_file', {encoding:'utf8',flag:'r+'})\r\n" + {"fs.readFileSync('njs/test/fs/utf8', {encoding:'utf8',flag:'r+'})\r\n" "'????Z??'\r\n>> "} } njs_test { + {"var fs = require('fs'), fn = 'njs/test/fs/ascii'\r\n" + "undefined\r\n>> "} + {"fs.readFileSync(fn)[599] + fs.readFileSync(fn, 'utf8')[599]\r\n" + "'xx'\r\n>> "} +} + +njs_test { {"var fs = require('fs'); \r\n" "undefined\r\n>> "} - {"try { fs.readFileSync('njs_unknown_path')} catch (e) {console.log(JSON.stringify(e))}\r\n" - "'{\"errno\":2,\"path\":\"njs_unknown_path\",\"syscall\":\"open\"}'\r\nundefined\r\n>> "} + {"try { fs.readFileSync('njs/test/fs/nonexistent')} catch (e) {console.log(JSON.stringify(e))}\r\n" + "'{\"errno\":2,\"path\":\"njs/test/fs/nonexistent\",\"syscall\":\"open\"}'\r\nundefined\r\n>> "} } njs_test { {"var fs = require('fs')\r\n" "undefined\r\n>> "} - {"fs.readFileSync('./njs/test/non_utf8').charCodeAt(1)\r\n" + {"fs.readFileSync('njs/test/fs/non_utf8').charCodeAt(1)\r\n" "128"} } njs_test { {"var fs = require('fs')\r\n" "undefined\r\n>> "} - {"fs.readFileSync('./njs/test/non_utf8', 'utf8')\r\n" + {"fs.readFileSync('njs/test/fs/non_utf8', 'utf8')\r\n" "Error: Non-UTF8 file, convertion is not implemented"} } diff -r acc5fc4be35b -r bfd57048376e njs/test/non_utf8 --- a/njs/test/non_utf8 Tue Mar 05 19:54:23 2019 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -?? \ No newline at end of file From sstevenson72 at gmail.com Wed Mar 6 20:01:57 2019 From: sstevenson72 at gmail.com (Steve Stevenson) Date: Wed, 6 Mar 2019 14:01:57 -0600 Subject: Patch to fix compile errors for Windows CL compiler Message-ID: We are seeing build issues due to the flag -WX Warnings as Errors. Doing the analysis we see redundant declarations of *pkey in `src\event\ngx_event_openssl.c` . I have made the changes and validated the compile finishes properly. See the below changeset patch. # HG changeset patch # User Steve Stevenson # Date 1551891444 21600 # Wed Mar 06 10:57:24 2019 -0600 # Node ID 6f818d1f3dc795ce3b8a84d3a720a89fcba7a1e5 # Parent 49f9d2f7d8877cf7d86fc43c07ef86fc494175bc removed redundant *pkey definition leading to Compile errors (Warnings as Errors) in windows compilation diff -r 49f9d2f7d887 -r 6f818d1f3dc7 src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Tue Mar 05 16:34:19 2019 +0300 +++ b/src/event/ngx_event_openssl.c Wed Mar 06 10:57:24 2019 -0600 @@ -703,7 +703,6 @@ u_char *p, *last; ENGINE *engine; - EVP_PKEY *pkey; p = key->data + sizeof("engine:") - 1; last = (u_char *) ngx_strchr(p, ':'); -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Thu Mar 7 16:51:14 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 7 Mar 2019 19:51:14 +0300 Subject: Patch to fix compile errors for Windows CL compiler In-Reply-To: References: Message-ID: <20190307165114.GB1877@mdounin.ru> Hello! On Wed, Mar 06, 2019 at 02:01:57PM -0600, Steve Stevenson wrote: > We are seeing build issues due to the flag -WX Warnings as Errors. Doing > the analysis we see redundant declarations of *pkey in > `src\event\ngx_event_openssl.c` . I have made the changes and validated > the compile finishes properly. See the below changeset patch. > > # HG changeset patch > # User Steve Stevenson > # Date 1551891444 21600 > # Wed Mar 06 10:57:24 2019 -0600 > # Node ID 6f818d1f3dc795ce3b8a84d3a720a89fcba7a1e5 > # Parent 49f9d2f7d8877cf7d86fc43c07ef86fc494175bc > removed redundant *pkey definition leading to Compile errors (Warnings as > Errors) in windows compilation > > diff -r 49f9d2f7d887 -r 6f818d1f3dc7 src/event/ngx_event_openssl.c > --- a/src/event/ngx_event_openssl.c Tue Mar 05 16:34:19 2019 +0300 > +++ b/src/event/ngx_event_openssl.c Wed Mar 06 10:57:24 2019 -0600 > @@ -703,7 +703,6 @@ > > u_char *p, *last; > ENGINE *engine; > - EVP_PKEY *pkey; > > p = key->data + sizeof("engine:") - 1; > last = (u_char *) ngx_strchr(p, ':'); Thanks. The code compiles fine with cl 16.00.40219.01 (MSVC 2010) as used for official win32 builds, but fails with lastest cl 19.16.27027.1 from Visual Studio 2017 build tools. Looks like the warning was introduced in MSVC 2015. Here are the patch which clarifies these details, and also fixes style of the variables block: # HG changeset patch # User Maxim Dounin # Date 1551976881 -10800 # Thu Mar 07 19:41:21 2019 +0300 # Node ID 97904e5d7f844295412d15aa9bfe2f97b795f352 # Parent 49f9d2f7d8877cf7d86fc43c07ef86fc494175bc SSL: removed redundant "pkey" variable. It was accidentally introduced in 77436d9951a1 (1.15.10). In MSVC 2015 and more recent MSVC versions it triggers warning C4456 (declaration of 'pkey' hides previous local declaration), seen with cl 19.16.27027.1 from Visual Studio 2017 build tools. Reported by Steve Stevenson. 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 @@ -701,9 +701,8 @@ ngx_ssl_load_certificate_key(ngx_pool_t #ifndef OPENSSL_NO_ENGINE - u_char *p, *last; - ENGINE *engine; - EVP_PKEY *pkey; + u_char *p, *last; + ENGINE *engine; p = key->data + sizeof("engine:") - 1; last = (u_char *) ngx_strchr(p, ':'); -- Maxim Dounin http://mdounin.ru/ From mdounin at mdounin.ru Thu Mar 7 17:38:01 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 7 Mar 2019 20:38:01 +0300 Subject: Proposed patch to enforce STARTTLS before MAIL FROM In-Reply-To: <9deabc11-ae8a-32db-44eb-9ba5fd17a4be@packetmail.net> References: <20190305182303.GW1877@mdounin.ru> <9deabc11-ae8a-32db-44eb-9ba5fd17a4be@packetmail.net> Message-ID: <20190307173801.GC1877@mdounin.ru> Hello! On Tue, Mar 05, 2019 at 01:48:06PM -0600, lists--- via nginx-devel wrote: > On 3/5/19 12:23 PM, Maxim Dounin wrote: > > Not sure it is a good change. > > Thank you for your detailed reply and explanation.? I agree with you on > all facets with respect to RFC compliance.? I believe the core issue at > hand is the antiquated language in the current RFC conflicting with > common practice -- several final destination MTAs on the public > Internet, depending on their role/use, do require and enforce TLS > communication only either on a per-sender, per-recipient, or per-server > basis. AFAIK, no public MTAs as of now require TLS for all SMTP connections. And if you want to enforce TLS selectively, you can do so via the auth_http script as previously suggested. >?That said your rationale for rejecting the patch is accurate and > mirrors similar expressed in Postfix at > www.postfix.org/postconf.5.html#smtpd_tls_security_level regarding 'encypt'. > > If you find the proposed patch satisfactory from a technical aspect I > will commit the patch locally for a specific use case which would fall > under the category of 'dedicated servers'. >From technical point of view I would recommend moving the check into ngx_mail_smtp_mail() function. Or, as already suggested, you may want to avoid the patch altogether and use auth_http restrictions instead. > For your consideration, perhaps a configuration option of: > > starttls dedicated; > > With the proposed patch would meet both a use case and RFC requirement aspect. This sounds confusing. If we really want all connections to be restricted to TLS only, I would rather change "starttls only" as in your initial suggestion. -- Maxim Dounin http://mdounin.ru/ From xeioex at nginx.com Thu Mar 7 17:49:09 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 07 Mar 2019 17:49:09 +0000 Subject: [njs] Introduced njs_lexer_token_t. Message-ID: details: https://hg.nginx.org/njs/rev/8e2cb4da5e46 branches: changeset: 819:8e2cb4da5e46 user: hongzhidao date: Fri Mar 08 00:11:23 2019 +0800 description: Introduced njs_lexer_token_t. diffstat: njs/njs.c | 11 +- njs/njs_core.h | 1 + njs/njs_lexer.c | 140 ++++++++++++++----------- njs/njs_lexer.h | 256 ++++++++++++++++++++++++++++++++++++++++++++++++ njs/njs_lexer_keyword.c | 15 +- njs/njs_parser.c | 108 +++++++++++-------- njs/njs_parser.h | 237 -------------------------------------------- njs/njs_regexp.c | 9 +- 8 files changed, 414 insertions(+), 363 deletions(-) diffs (truncated from 1286 to 1000 lines): diff -r bfd57048376e -r 8e2cb4da5e46 njs/njs.c --- a/njs/njs.c Wed Mar 06 19:39:21 2019 +0300 +++ b/njs/njs.c Fri Mar 08 00:11:23 2019 +0800 @@ -234,13 +234,10 @@ njs_vm_compile(njs_vm_t *vm, u_char **st prev = vm->parser; vm->parser = parser; - nxt_memzero(&lexer, sizeof(njs_lexer_t)); - - lexer.start = *start; - lexer.end = end; - lexer.line = 1; - lexer.file = vm->options.file; - lexer.keywords_hash = vm->shared->keywords_hash; + ret = njs_lexer_init(vm, &lexer, &vm->options.file, *start, end); + if (nxt_slow_path(ret != NXT_OK)) { + return NJS_ERROR; + } parser->lexer = &lexer; diff -r bfd57048376e -r 8e2cb4da5e46 njs/njs_core.h --- a/njs/njs_core.h Wed Mar 06 19:39:21 2019 +0300 +++ b/njs/njs_core.h Fri Mar 08 00:11:23 2019 +0800 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include diff -r bfd57048376e -r 8e2cb4da5e46 njs/njs_lexer.c --- a/njs/njs_lexer.c Wed Mar 06 19:39:21 2019 +0300 +++ b/njs/njs_lexer.c Fri Mar 08 00:11:23 2019 +0800 @@ -18,11 +18,15 @@ struct njs_lexer_multi_s { }; -static njs_token_t njs_lexer_next_token(njs_lexer_t *lexer); -static njs_token_t njs_lexer_word(njs_lexer_t *lexer, u_char c); -static njs_token_t njs_lexer_string(njs_lexer_t *lexer, u_char quote); -static njs_token_t njs_lexer_number(njs_lexer_t *lexer, u_char c); -static njs_token_t njs_lexer_multi(njs_lexer_t *lexer, +static njs_token_t njs_lexer_next_token(njs_lexer_t *lexer, + njs_lexer_token_t *lt); +static njs_token_t njs_lexer_word(njs_lexer_t *lexer, njs_lexer_token_t *lt, + u_char c); +static njs_token_t njs_lexer_string(njs_lexer_t *lexer, njs_lexer_token_t *lt, + u_char quote); +static njs_token_t njs_lexer_number(njs_lexer_t *lexer, njs_lexer_token_t *lt, + u_char c); +static njs_token_t njs_lexer_multi(njs_lexer_t *lexer, njs_lexer_token_t *lt, njs_token_t token, nxt_uint_t n, const njs_lexer_multi_t *multi); static njs_token_t njs_lexer_division(njs_lexer_t *lexer, njs_token_t token); @@ -272,27 +276,49 @@ static const njs_lexer_multi_t njs_assi }; +nxt_int_t +njs_lexer_init(njs_vm_t *vm, njs_lexer_t *lexer, nxt_str_t *file, + u_char *start, u_char *end) +{ + nxt_memzero(lexer, sizeof(njs_lexer_t)); + + lexer->file = *file; + lexer->start = start; + lexer->end = end; + lexer->line = 1; + lexer->keywords_hash = vm->shared->keywords_hash; + + lexer->lexer_token = nxt_mp_alloc(vm->mem_pool, sizeof(njs_lexer_token_t)); + if (nxt_slow_path(lexer->lexer_token == NULL)) { + return NXT_ERROR; + } + + return NXT_OK; +} + + njs_token_t njs_lexer_token(njs_lexer_t *lexer) { - njs_token_t token; + njs_lexer_token_t *lt; + + lt = lexer->lexer_token; lexer->prev_start = lexer->start; - lexer->prev_token = lexer->token; + lexer->prev_token = lt->token; - token = njs_lexer_next_token(lexer); + lt->token = njs_lexer_next_token(lexer, lt); - lexer->token = token; + if (lt->token == NJS_TOKEN_NAME) { + njs_lexer_keyword(lexer, lt); - return token; -} - + if (lexer->property) { + lexer->property_token = lt->token; + return NJS_TOKEN_NAME; + } + } -void -njs_lexer_rollback(njs_lexer_t *lexer) -{ - lexer->start = lexer->prev_start; - lexer->token = lexer->prev_token; + return lt->token; } @@ -322,14 +348,14 @@ njs_lexer_peek_token(njs_lexer_t *lexer) static njs_token_t -njs_lexer_next_token(njs_lexer_t *lexer) +njs_lexer_next_token(njs_lexer_t *lexer, njs_lexer_token_t *lt) { u_char c, *p; nxt_uint_t n; njs_token_t token; const njs_lexer_multi_t *multi; - lexer->text.start = lexer->start; + lt->text.start = lexer->start; while (lexer->start < lexer->end) { c = *lexer->start++; @@ -339,15 +365,15 @@ njs_lexer_next_token(njs_lexer_t *lexer) switch (token) { case NJS_TOKEN_SPACE: - lexer->text.start = lexer->start; + lt->text.start = lexer->start; continue; case NJS_TOKEN_LETTER: - return njs_lexer_word(lexer, c); + return njs_lexer_word(lexer, lt, c); case NJS_TOKEN_DOUBLE_QUOTE: case NJS_TOKEN_SINGLE_QUOTE: - return njs_lexer_string(lexer, c); + return njs_lexer_string(lexer, lt, c); case NJS_TOKEN_DOT: p = lexer->start; @@ -356,20 +382,20 @@ njs_lexer_next_token(njs_lexer_t *lexer) && njs_tokens[p[0]] == NJS_TOKEN_DOT && njs_tokens[p[1]] == NJS_TOKEN_DOT) { - lexer->text.length = (p - lexer->text.start) + 2; + lt->text.length = (p - lt->text.start) + 2; lexer->start += 2; return NJS_TOKEN_ELLIPSIS; } if (p == lexer->end || njs_tokens[*p] != NJS_TOKEN_DIGIT) { - lexer->text.length = p - lexer->text.start; + lt->text.length = p - lt->text.start; return NJS_TOKEN_DOT; } /* Fall through. */ case NJS_TOKEN_DIGIT: - return njs_lexer_number(lexer, c); + return njs_lexer_number(lexer, lt, c); case NJS_TOKEN_ASSIGNMENT: n = nxt_nitems(njs_assignment_token), @@ -462,7 +488,7 @@ njs_lexer_next_token(njs_lexer_t *lexer) case NJS_TOKEN_COLON: case NJS_TOKEN_SEMICOLON: case NJS_TOKEN_CONDITIONAL: - lexer->text.length = lexer->start - lexer->text.start; + lt->text.length = lexer->start - lt->text.start; return token; case NJS_TOKEN_ILLEGAL: @@ -473,20 +499,19 @@ njs_lexer_next_token(njs_lexer_t *lexer) multi: - return njs_lexer_multi(lexer, token, n, multi); + return njs_lexer_multi(lexer, lt, token, n, multi); } - lexer->text.length = lexer->start - lexer->text.start; + lt->text.length = lexer->start - lt->text.start; return NJS_TOKEN_END; } static njs_token_t -njs_lexer_word(njs_lexer_t *lexer, u_char c) +njs_lexer_word(njs_lexer_t *lexer, njs_lexer_token_t *lt, u_char c) { - u_char *p; - njs_token_t token; + u_char *p; /* TODO: UTF-8 */ @@ -508,9 +533,9 @@ njs_lexer_word(njs_lexer_t *lexer, u_cha 0x00, 0x00, 0x00, 0x00, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ }; - lexer->token_line = lexer->line; - lexer->key_hash = nxt_djb_hash_add(NXT_DJB_HASH_INIT, c); - lexer->text.start = lexer->start - 1; + lt->token_line = lexer->line; + lt->key_hash = nxt_djb_hash_add(NXT_DJB_HASH_INIT, c); + lt->text.start = lexer->start - 1; for (p = lexer->start; p < lexer->end; p++) { c = *p; @@ -519,31 +544,24 @@ njs_lexer_word(njs_lexer_t *lexer, u_cha break; } - lexer->key_hash = nxt_djb_hash_add(lexer->key_hash, c); + lt->key_hash = nxt_djb_hash_add(lt->key_hash, c); } lexer->start = p; - lexer->text.length = p - lexer->text.start; - - token = njs_lexer_keyword(lexer); + lt->text.length = p - lt->text.start; - if (lexer->property) { - lexer->property_token = token; - return NJS_TOKEN_NAME; - } - - return token; + return NJS_TOKEN_NAME; } static njs_token_t -njs_lexer_string(njs_lexer_t *lexer, u_char quote) +njs_lexer_string(njs_lexer_t *lexer, njs_lexer_token_t *lt, u_char quote) { u_char *p, c; nxt_bool_t escape; escape = 0; - lexer->text.start = lexer->start; + lt->text.start = lexer->start; p = lexer->start; while (p < lexer->end) { @@ -574,7 +592,7 @@ njs_lexer_string(njs_lexer_t *lexer, u_c if (c == quote) { lexer->start = p; - lexer->text.length = (p - 1) - lexer->text.start; + lt->text.length = (p - 1) - lt->text.start; if (escape == 0) { return NJS_TOKEN_STRING; @@ -584,19 +602,19 @@ njs_lexer_string(njs_lexer_t *lexer, u_c } } - lexer->text.start--; - lexer->text.length = p - lexer->text.start; + lt->text.start--; + lt->text.length = p - lt->text.start; return NJS_TOKEN_UNTERMINATED_STRING; } static njs_token_t -njs_lexer_number(njs_lexer_t *lexer, u_char c) +njs_lexer_number(njs_lexer_t *lexer, njs_lexer_token_t *lt, u_char c) { const u_char *p; - lexer->text.start = lexer->start - 1; + lt->text.start = lexer->start - 1; p = lexer->start; @@ -611,7 +629,7 @@ njs_lexer_number(njs_lexer_t *lexer, u_c goto illegal_token; } - lexer->number = njs_number_hex_parse(&p, lexer->end); + lt->number = njs_number_hex_parse(&p, lexer->end); goto done; } @@ -625,7 +643,7 @@ njs_lexer_number(njs_lexer_t *lexer, u_c goto illegal_token; } - lexer->number = njs_number_oct_parse(&p, lexer->end); + lt->number = njs_number_oct_parse(&p, lexer->end); if (p < lexer->end && (*p == '8' || *p == '9')) { goto illegal_trailer; @@ -643,7 +661,7 @@ njs_lexer_number(njs_lexer_t *lexer, u_c goto illegal_token; } - lexer->number = njs_number_bin_parse(&p, lexer->end); + lt->number = njs_number_bin_parse(&p, lexer->end); if (p < lexer->end && (*p >= '2' && *p <= '9')) { goto illegal_trailer; @@ -660,12 +678,12 @@ njs_lexer_number(njs_lexer_t *lexer, u_c } p--; - lexer->number = njs_number_dec_parse(&p, lexer->end); + lt->number = njs_number_dec_parse(&p, lexer->end); done: lexer->start = (u_char *) p; - lexer->text.length = p - lexer->text.start; + lt->text.length = p - lt->text.start; return NJS_TOKEN_NUMBER; @@ -675,15 +693,15 @@ illegal_trailer: illegal_token: - lexer->text.length = p - lexer->text.start; + lt->text.length = p - lt->text.start; return NJS_TOKEN_ILLEGAL; } static njs_token_t -njs_lexer_multi(njs_lexer_t *lexer, njs_token_t token, nxt_uint_t n, - const njs_lexer_multi_t *multi) +njs_lexer_multi(njs_lexer_t *lexer, njs_lexer_token_t *lt, njs_token_t token, + nxt_uint_t n, const njs_lexer_multi_t *multi) { u_char c; @@ -699,7 +717,7 @@ njs_lexer_multi(njs_lexer_t *lexer, njs_ break; } - return njs_lexer_multi(lexer, multi->token, multi->count, + return njs_lexer_multi(lexer, lt, multi->token, multi->count, multi->next); } @@ -709,7 +727,7 @@ njs_lexer_multi(njs_lexer_t *lexer, njs_ } while (n != 0); } - lexer->text.length = lexer->start - lexer->text.start; + lt->text.length = lexer->start - lt->text.start; return token; } diff -r bfd57048376e -r 8e2cb4da5e46 njs/njs_lexer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/njs/njs_lexer.h Fri Mar 08 00:11:23 2019 +0800 @@ -0,0 +1,256 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) NGINX, Inc. + */ + +#ifndef _NJS_LEXER_H_INCLUDED_ +#define _NJS_LEXER_H_INCLUDED_ + + +typedef enum { + NJS_TOKEN_AGAIN = -2, + NJS_TOKEN_ERROR = -1, + NJS_TOKEN_ILLEGAL = 0, + + NJS_TOKEN_END, + NJS_TOKEN_SPACE, + NJS_TOKEN_LINE_END, + + NJS_TOKEN_DOUBLE_QUOTE, + NJS_TOKEN_SINGLE_QUOTE, + + NJS_TOKEN_OPEN_PARENTHESIS, + NJS_TOKEN_CLOSE_PARENTHESIS, + NJS_TOKEN_OPEN_BRACKET, + NJS_TOKEN_CLOSE_BRACKET, + NJS_TOKEN_OPEN_BRACE, + NJS_TOKEN_CLOSE_BRACE, + + NJS_TOKEN_COMMA, + NJS_TOKEN_DOT, + NJS_TOKEN_ELLIPSIS, + NJS_TOKEN_SEMICOLON, + + NJS_TOKEN_COLON, + NJS_TOKEN_CONDITIONAL, + + NJS_TOKEN_ASSIGNMENT, + NJS_TOKEN_ADDITION_ASSIGNMENT, + NJS_TOKEN_SUBSTRACTION_ASSIGNMENT, + NJS_TOKEN_MULTIPLICATION_ASSIGNMENT, + NJS_TOKEN_EXPONENTIATION_ASSIGNMENT, + NJS_TOKEN_DIVISION_ASSIGNMENT, + NJS_TOKEN_REMAINDER_ASSIGNMENT, + NJS_TOKEN_LEFT_SHIFT_ASSIGNMENT, + NJS_TOKEN_RIGHT_SHIFT_ASSIGNMENT, + NJS_TOKEN_UNSIGNED_RIGHT_SHIFT_ASSIGNMENT, + NJS_TOKEN_BITWISE_OR_ASSIGNMENT, + NJS_TOKEN_BITWISE_XOR_ASSIGNMENT, + NJS_TOKEN_BITWISE_AND_ASSIGNMENT, + +#define NJS_TOKEN_LAST_ASSIGNMENT NJS_TOKEN_BITWISE_AND_ASSIGNMENT + + NJS_TOKEN_EQUAL, + NJS_TOKEN_STRICT_EQUAL, + NJS_TOKEN_NOT_EQUAL, + NJS_TOKEN_STRICT_NOT_EQUAL, + + NJS_TOKEN_ADDITION, + NJS_TOKEN_UNARY_PLUS, + NJS_TOKEN_INCREMENT, + NJS_TOKEN_POST_INCREMENT, + + NJS_TOKEN_SUBSTRACTION, + NJS_TOKEN_UNARY_NEGATION, + NJS_TOKEN_DECREMENT, + NJS_TOKEN_POST_DECREMENT, + + NJS_TOKEN_MULTIPLICATION, + + NJS_TOKEN_EXPONENTIATION, + + NJS_TOKEN_DIVISION, + + NJS_TOKEN_REMAINDER, + + NJS_TOKEN_LESS, + NJS_TOKEN_LESS_OR_EQUAL, + NJS_TOKEN_LEFT_SHIFT, + + NJS_TOKEN_GREATER, + NJS_TOKEN_GREATER_OR_EQUAL, + NJS_TOKEN_RIGHT_SHIFT, + NJS_TOKEN_UNSIGNED_RIGHT_SHIFT, + + NJS_TOKEN_BITWISE_OR, + NJS_TOKEN_LOGICAL_OR, + + NJS_TOKEN_BITWISE_XOR, + + NJS_TOKEN_BITWISE_AND, + NJS_TOKEN_LOGICAL_AND, + + NJS_TOKEN_BITWISE_NOT, + NJS_TOKEN_LOGICAL_NOT, + + NJS_TOKEN_IN, + NJS_TOKEN_INSTANCEOF, + NJS_TOKEN_TYPEOF, + NJS_TOKEN_VOID, + NJS_TOKEN_NEW, + NJS_TOKEN_DELETE, + NJS_TOKEN_YIELD, + + NJS_TOKEN_DIGIT, + NJS_TOKEN_LETTER, + +#define NJS_TOKEN_FIRST_CONST NJS_TOKEN_UNDEFINED + + NJS_TOKEN_UNDEFINED, + NJS_TOKEN_NULL, + NJS_TOKEN_NUMBER, + NJS_TOKEN_BOOLEAN, + NJS_TOKEN_STRING, + +#define NJS_TOKEN_LAST_CONST NJS_TOKEN_STRING + + NJS_TOKEN_ESCAPE_STRING, + NJS_TOKEN_UNTERMINATED_STRING, + NJS_TOKEN_NAME, + + NJS_TOKEN_OBJECT, + NJS_TOKEN_OBJECT_VALUE, + NJS_TOKEN_PROPERTY, + NJS_TOKEN_PROPERTY_DELETE, + + NJS_TOKEN_ARRAY, + + NJS_TOKEN_FUNCTION, + NJS_TOKEN_FUNCTION_EXPRESSION, + NJS_TOKEN_FUNCTION_CALL, + NJS_TOKEN_METHOD_CALL, + NJS_TOKEN_ARGUMENT, + NJS_TOKEN_RETURN, + + NJS_TOKEN_REGEXP, + + NJS_TOKEN_EXTERNAL, + + NJS_TOKEN_STATEMENT, + NJS_TOKEN_BLOCK, + NJS_TOKEN_VAR, + NJS_TOKEN_IF, + NJS_TOKEN_ELSE, + NJS_TOKEN_BRANCHING, + NJS_TOKEN_WHILE, + NJS_TOKEN_DO, + NJS_TOKEN_FOR, + NJS_TOKEN_FOR_IN, + NJS_TOKEN_BREAK, + NJS_TOKEN_CONTINUE, + NJS_TOKEN_SWITCH, + NJS_TOKEN_CASE, + NJS_TOKEN_DEFAULT, + NJS_TOKEN_WITH, + NJS_TOKEN_TRY, + NJS_TOKEN_CATCH, + NJS_TOKEN_FINALLY, + NJS_TOKEN_THROW, + + NJS_TOKEN_THIS, + NJS_TOKEN_ARGUMENTS, + +#define NJS_TOKEN_FIRST_OBJECT NJS_TOKEN_GLOBAL_THIS + + NJS_TOKEN_GLOBAL_THIS, + NJS_TOKEN_NJS, + NJS_TOKEN_MATH, + NJS_TOKEN_JSON, + + NJS_TOKEN_OBJECT_CONSTRUCTOR, + NJS_TOKEN_ARRAY_CONSTRUCTOR, + NJS_TOKEN_BOOLEAN_CONSTRUCTOR, + NJS_TOKEN_NUMBER_CONSTRUCTOR, + NJS_TOKEN_STRING_CONSTRUCTOR, + NJS_TOKEN_FUNCTION_CONSTRUCTOR, + NJS_TOKEN_REGEXP_CONSTRUCTOR, + NJS_TOKEN_DATE_CONSTRUCTOR, + NJS_TOKEN_ERROR_CONSTRUCTOR, + NJS_TOKEN_EVAL_ERROR_CONSTRUCTOR, + NJS_TOKEN_INTERNAL_ERROR_CONSTRUCTOR, + NJS_TOKEN_RANGE_ERROR_CONSTRUCTOR, + NJS_TOKEN_REF_ERROR_CONSTRUCTOR, + NJS_TOKEN_SYNTAX_ERROR_CONSTRUCTOR, + NJS_TOKEN_TYPE_ERROR_CONSTRUCTOR, + NJS_TOKEN_URI_ERROR_CONSTRUCTOR, + NJS_TOKEN_MEMORY_ERROR_CONSTRUCTOR, + +#define NJS_TOKEN_FIRST_FUNCTION NJS_TOKEN_EVAL + + NJS_TOKEN_EVAL, + NJS_TOKEN_TO_STRING, + NJS_TOKEN_IS_NAN, + NJS_TOKEN_IS_FINITE, + NJS_TOKEN_PARSE_INT, + NJS_TOKEN_PARSE_FLOAT, + NJS_TOKEN_ENCODE_URI, + NJS_TOKEN_ENCODE_URI_COMPONENT, + NJS_TOKEN_DECODE_URI, + NJS_TOKEN_DECODE_URI_COMPONENT, + NJS_TOKEN_REQUIRE, + NJS_TOKEN_SET_TIMEOUT, + NJS_TOKEN_SET_IMMEDIATE, + NJS_TOKEN_CLEAR_TIMEOUT, + + NJS_TOKEN_RESERVED, +} njs_token_t; + + +typedef struct { + njs_token_t token:16; + uint32_t token_line; + uint32_t key_hash; + nxt_str_t text; + double number; +} njs_lexer_token_t; + + +typedef struct { + njs_lexer_token_t *lexer_token; + + u_char *prev_start; + njs_token_t prev_token:16; + + uint8_t property; /* 1 bit */ + njs_token_t property_token:16; + + uint32_t line; + nxt_str_t file; + + nxt_lvlhsh_t keywords_hash; + + u_char *start; + u_char *end; +} njs_lexer_t; + + +typedef struct { + nxt_str_t name; + njs_token_t token; + double number; +} njs_keyword_t; + + +nxt_int_t njs_lexer_init(njs_vm_t *vm, njs_lexer_t *lexer, nxt_str_t *file, + u_char *start, u_char *end); +njs_token_t njs_lexer_token(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 *mp, nxt_lvlhsh_t *hash); +void njs_lexer_keyword(njs_lexer_t *lexer, njs_lexer_token_t *lt); + +#define njs_lexer_rollback(lexer) \ + (lexer)->start = (lexer)->prev_start + + +#endif /* _NJS_LEXER_H_INCLUDED_ */ diff -r bfd57048376e -r 8e2cb4da5e46 njs/njs_lexer_keyword.c --- a/njs/njs_lexer_keyword.c Wed Mar 06 19:39:21 2019 +0300 +++ b/njs/njs_lexer_keyword.c Fri Mar 08 00:11:23 2019 +0800 @@ -173,22 +173,19 @@ njs_lexer_keywords_init(nxt_mp_t *mp, nx } -njs_token_t -njs_lexer_keyword(njs_lexer_t *lexer) +void +njs_lexer_keyword(njs_lexer_t *lexer, njs_lexer_token_t *lt) { njs_keyword_t *keyword; nxt_lvlhsh_query_t lhq; - lhq.key_hash = lexer->key_hash; - lhq.key = lexer->text; + lhq.key_hash = lt->key_hash; + lhq.key = lt->text; lhq.proto = &njs_keyword_hash_proto; if (nxt_lvlhsh_find(&lexer->keywords_hash, &lhq) == NXT_OK) { keyword = lhq.value; - lexer->number = keyword->number; - - return keyword->token; + lt->token = keyword->token; + lt->number = keyword->number; } - - return NJS_TOKEN_NAME; } diff -r bfd57048376e -r 8e2cb4da5e46 njs/njs_parser.c --- a/njs/njs_parser.c Wed Mar 06 19:39:21 2019 +0300 +++ b/njs/njs_parser.c Fri Mar 08 00:11:23 2019 +0800 @@ -77,6 +77,18 @@ static njs_token_t njs_parser_unexpected #define njs_parser_chain_top_set(parser, node) \ (parser)->scope->top = node +#define njs_parser_text(parser) \ + &(parser)->lexer->lexer_token->text + +#define njs_parser_key_hash(parser) \ + (parser)->lexer->lexer_token->key_hash + +#define njs_parser_number(parser) \ + (parser)->lexer->lexer_token->number + +#define njs_parser_token_line(parser) \ + (parser)->lexer->lexer_token->token_line + nxt_int_t njs_parser(njs_vm_t *vm, njs_parser_t *parser, njs_parser_t *prev) @@ -493,16 +505,17 @@ nxt_inline njs_variable_t * njs_parser_variable_add(njs_vm_t *vm, njs_parser_t *parser, njs_variable_type_t type) { - return njs_variable_add(vm, parser->scope, &parser->lexer->text, - parser->lexer->key_hash, type); + return njs_variable_add(vm, parser->scope, njs_parser_text(parser), + njs_parser_key_hash(parser), type); } nxt_inline njs_ret_t njs_parser_variable_reference(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *node, njs_reference_type_t type) { - return njs_variable_reference(vm, parser->scope, node, &parser->lexer->text, - parser->lexer->key_hash, type); + return njs_variable_reference(vm, parser->scope, node, + njs_parser_text(parser), + njs_parser_key_hash(parser), type); } @@ -515,8 +528,8 @@ njs_parser_labelled_statement(njs_vm_t * njs_token_t token; njs_variable_t *label; - name = parser->lexer->text; - hash = parser->lexer->key_hash; + name = *njs_parser_text(parser); + hash = njs_parser_key_hash(parser); label = njs_label_find(vm, parser->scope, &name, hash); if (nxt_slow_path(label != NULL)) { @@ -604,7 +617,7 @@ njs_parser_function_declaration(njs_vm_t return NJS_TOKEN_ERROR; } - node->token_line = parser->lexer->token_line; + node->token_line = njs_parser_token_line(parser); token = njs_parser_token(parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { @@ -615,7 +628,7 @@ njs_parser_function_declaration(njs_vm_t if (token == NJS_TOKEN_ARGUMENTS || token == NJS_TOKEN_EVAL) { njs_parser_syntax_error(vm, parser, "Identifier \"%V\" " "is forbidden in function declaration", - &parser->lexer->text); + njs_parser_text(parser)); } return NJS_TOKEN_ILLEGAL; @@ -664,7 +677,7 @@ njs_parser_function_expression(njs_vm_t return NJS_TOKEN_ERROR; } - node->token_line = parser->lexer->token_line; + node->token_line = njs_parser_token_line(parser); parser->node = node; token = njs_parser_token(parser); @@ -768,7 +781,7 @@ njs_parser_function_lambda(njs_vm_t *vm, arg->index = index; index += sizeof(njs_value_t); - ret = njs_name_copy(vm, &arg->name, &parser->lexer->text); + ret = njs_name_copy(vm, &arg->name, njs_parser_text(parser)); if (nxt_slow_path(ret != NXT_OK)) { return NJS_TOKEN_ERROR; } @@ -946,7 +959,7 @@ njs_parser_var_statement(njs_vm_t *vm, n if (token == NJS_TOKEN_ARGUMENTS || token == NJS_TOKEN_EVAL) { njs_parser_syntax_error(vm, parser, "Identifier \"%V\" " "is forbidden in var declaration", - &parser->lexer->text); + njs_parser_text(parser)); } return NJS_TOKEN_ILLEGAL; @@ -1292,7 +1305,7 @@ njs_parser_for_statement(njs_vm_t *vm, n } else { - name = parser->lexer->text; + name = *njs_parser_text(parser); token = njs_parser_expression(vm, parser, token); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { @@ -1398,7 +1411,7 @@ njs_parser_for_var_statement(njs_vm_t *v if (token == NJS_TOKEN_ARGUMENTS || token == NJS_TOKEN_EVAL) { njs_parser_syntax_error(vm, parser, "Identifier \"%V\" " "is forbidden in for-in var declaration", - &parser->lexer->text); + njs_parser_text(parser)); } return NJS_TOKEN_ILLEGAL; @@ -1573,7 +1586,7 @@ njs_parser_brk_statement(njs_vm_t *vm, n return NJS_TOKEN_ERROR; } - node->token_line = parser->lexer->token_line; + node->token_line = njs_parser_token_line(parser); parser->node = node; token = njs_lexer_token(parser->lexer); @@ -1584,8 +1597,8 @@ njs_parser_brk_statement(njs_vm_t *vm, n return njs_parser_token(parser); case NJS_TOKEN_NAME: - name = parser->lexer->text; - hash = parser->lexer->key_hash; + name = *njs_parser_text(parser); + hash = njs_parser_key_hash(parser); if (njs_label_find(vm, parser->scope, &name, hash) == NULL) { njs_parser_syntax_error(vm, parser, "Undefined label \"%V\"", @@ -1593,7 +1606,7 @@ njs_parser_brk_statement(njs_vm_t *vm, n return NJS_TOKEN_ILLEGAL; } - ret = njs_name_copy(vm, &parser->node->label, &parser->lexer->text); + ret = njs_name_copy(vm, &parser->node->label, &name); if (nxt_slow_path(ret != NXT_OK)) { return NJS_TOKEN_ERROR; } @@ -1875,11 +1888,8 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa { double num; njs_ret_t ret; - njs_lexer_t *lexer; njs_parser_node_t *node; - lexer = parser->lexer; - if (token == NJS_TOKEN_OPEN_PARENTHESIS) { token = njs_parser_token(parser); @@ -1952,12 +1962,12 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa return token; } - nxt_thread_log_debug("REGEX: '%V'", &lexer->text); + nxt_thread_log_debug("REGEX: '%V'", njs_parser_text(parser)); break; case NJS_TOKEN_STRING: - nxt_thread_log_debug("JS: '%V'", &lexer->text); + nxt_thread_log_debug("JS: '%V'", njs_parser_text(parser)); node = njs_parser_node_new(vm, parser, NJS_TOKEN_STRING); if (nxt_slow_path(node == NULL)) { @@ -1972,7 +1982,7 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa break; case NJS_TOKEN_ESCAPE_STRING: - nxt_thread_log_debug("JS: '%V'", &lexer->text); + nxt_thread_log_debug("JS: '%V'", njs_parser_text(parser)); node = njs_parser_node_new(vm, parser, NJS_TOKEN_STRING); if (nxt_slow_path(node == NULL)) { @@ -1988,12 +1998,12 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa case NJS_TOKEN_UNTERMINATED_STRING: njs_parser_syntax_error(vm, parser, "Unterminated string \"%V\"", - &lexer->text); + njs_parser_text(parser)); return NJS_TOKEN_ILLEGAL; case NJS_TOKEN_NUMBER: - num = lexer->number; + num = njs_parser_number(parser); nxt_thread_log_debug("JS: %f", num); node = njs_parser_node_new(vm, parser, NJS_TOKEN_NUMBER); @@ -2008,14 +2018,15 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa break; case NJS_TOKEN_BOOLEAN: - nxt_thread_log_debug("JS: boolean: %V", &lexer->text); + num = njs_parser_number(parser); + nxt_thread_log_debug("JS: boolean: %V", njs_parser_text(parser)); node = njs_parser_node_new(vm, parser, NJS_TOKEN_BOOLEAN); if (nxt_slow_path(node == NULL)) { return NJS_TOKEN_ERROR; } - if (lexer->number == 0) { + if (num == 0) { node->u.value = njs_value_false; } else { @@ -2025,8 +2036,9 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa break; default: - node = njs_parser_reference(vm, parser, token, &lexer->text, - lexer->key_hash); + node = njs_parser_reference(vm, parser, token, + njs_parser_text(parser), + njs_parser_key_hash(parser)); if (nxt_slow_path(node == NULL)) { return NJS_TOKEN_ERROR; @@ -2205,7 +2217,7 @@ 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; + node->token_line = njs_parser_token_line(parser); ext = njs_external_lookup(vm, name, hash); @@ -2319,8 +2331,8 @@ njs_parser_object(njs_vm_t *vm, njs_pars return njs_parser_token(parser); case NJS_TOKEN_NAME: - name = lexer->text; - hash = lexer->key_hash; + name = *njs_parser_text(parser); + hash = njs_parser_key_hash(parser); token = njs_parser_token(parser); break; @@ -2504,7 +2516,7 @@ njs_parser_string_create(njs_vm_t *vm, n ssize_t length; nxt_str_t *src; - src = &vm->parser->lexer->text; + src = njs_parser_text(vm->parser); length = nxt_utf8_length(src->start, src->length); @@ -2535,6 +2547,7 @@ njs_parser_escape_string_create(njs_vm_t u_char c, *start, *dst; size_t size,length, hex_length; uint64_t u; + nxt_str_t *string; const u_char *p, *src, *end, *hex_end; start = NULL; @@ -2549,8 +2562,9 @@ njs_parser_escape_string_create(njs_vm_t size = 0; length = 0; - src = parser->lexer->text.start; - end = src + parser->lexer->text.length; + string = njs_parser_text(parser); + src = string->start; + end = src + string->length; while (src < end) { c = *src++; @@ -2700,7 +2714,7 @@ njs_parser_escape_string_create(njs_vm_t invalid: njs_parser_syntax_error(vm, parser, "Invalid Unicode code point \"%V\"", - &parser->lexer->text); + njs_parser_text(parser)); return NJS_TOKEN_ILLEGAL; } @@ -2743,7 +2757,7 @@ njs_parser_unexpected_token(njs_vm_t *vm { if (token != NJS_TOKEN_END) { njs_parser_syntax_error(vm, parser, "Unexpected token \"%V\"", - &parser->lexer->text); + njs_parser_text(parser)); } else { njs_parser_syntax_error(vm, parser, "Unexpected end of input"); @@ -2757,10 +2771,11 @@ 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; - njs_lexer_t *lexer; + u_char *p; + size_t size; + njs_vm_t *vm; + njs_lexer_t *lexer; + njs_parser_t *parser; size = nxt_length("InternalError: "); memcpy(start, "InternalError: ", size); @@ -2771,14 +2786,17 @@ njs_parser_trace_handler(nxt_trace_t *tr trace = trace->next; p = trace->handler(trace, td, p); - if (vm->parser != NULL && vm->parser->lexer != NULL) { - lexer = vm->parser->lexer; + parser = vm->parser; + + if (parser != NULL && parser->lexer != NULL) { + lexer = parser->lexer; if (lexer->file.length != 0) { njs_internal_error(vm, "%s in %V:%uD", start, &lexer->file, - lexer->line); + njs_parser_token_line(parser)); } else { - njs_internal_error(vm, "%s in %uD", start, lexer->line); + njs_internal_error(vm, "%s in %uD", start, + njs_parser_token_line(parser)); } } else { diff -r bfd57048376e -r 8e2cb4da5e46 njs/njs_parser.h From mdounin at mdounin.ru Sat Mar 9 00:01:27 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 09 Mar 2019 00:01:27 +0000 Subject: [nginx] SSL: removed redundant "pkey" variable. Message-ID: details: https://hg.nginx.org/nginx/rev/b6dc8a12c07a branches: changeset: 7476:b6dc8a12c07a user: Maxim Dounin date: Sat Mar 09 02:55:43 2019 +0300 description: SSL: removed redundant "pkey" variable. It was accidentally introduced in 77436d9951a1 (1.15.9). In MSVC 2015 and more recent MSVC versions it triggers warning C4456 (declaration of 'pkey' hides previous local declaration). Previously, all such warnings were resolved in 2a621245f4cf. Reported by Steve Stevenson. diffstat: src/event/ngx_event_openssl.c | 5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-) diffs (15 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 @@ -701,9 +701,8 @@ ngx_ssl_load_certificate_key(ngx_pool_t #ifndef OPENSSL_NO_ENGINE - u_char *p, *last; - ENGINE *engine; - EVP_PKEY *pkey; + u_char *p, *last; + ENGINE *engine; p = key->data + sizeof("engine:") - 1; last = (u_char *) ngx_strchr(p, ':'); From mdounin at mdounin.ru Sat Mar 9 00:05:19 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 09 Mar 2019 00:05:19 +0000 Subject: [nginx] SSL: support for parsing PEM certificates from memory. Message-ID: details: https://hg.nginx.org/nginx/rev/c74904a17021 branches: changeset: 7477:c74904a17021 user: Maxim Dounin date: Sat Mar 09 03:03:56 2019 +0300 description: SSL: support for parsing PEM certificates from memory. This makes it possible to provide certificates directly via variables in ssl_certificate / ssl_certificate_key directives, without using intermediate files. diffstat: src/event/ngx_event_openssl.c | 74 ++++++++++++++++++++++++++---------------- 1 files changed, 46 insertions(+), 28 deletions(-) diffs (91 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 @@ -611,23 +611,29 @@ ngx_ssl_load_certificate(ngx_pool_t *poo 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 - */ - - bio = BIO_new_file((char *) cert->data, "r"); - if (bio == NULL) { - *err = "BIO_new_file() failed"; - return NULL; + if (ngx_strncmp(cert->data, "data:", sizeof("data:") - 1) == 0) { + + bio = BIO_new_mem_buf(cert->data + sizeof("data:") - 1, + cert->len - (sizeof("data:") - 1)); + if (bio == NULL) { + *err = "BIO_new_mem_buf() failed"; + return NULL; + } + + } else { + + if (ngx_get_full_name(pool, (ngx_str_t *) &ngx_cycle->conf_prefix, cert) + != NGX_OK) + { + *err = NULL; + return NULL; + } + + bio = BIO_new_file((char *) cert->data, "r"); + if (bio == NULL) { + *err = "BIO_new_file() failed"; + return NULL; + } } /* certificate itself */ @@ -743,17 +749,29 @@ ngx_ssl_load_certificate_key(ngx_pool_t #endif } - 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 (ngx_strncmp(key->data, "data:", sizeof("data:") - 1) == 0) { + + bio = BIO_new_mem_buf(key->data + sizeof("data:") - 1, + key->len - (sizeof("data:") - 1)); + if (bio == NULL) { + *err = "BIO_new_mem_buf() failed"; + return NULL; + } + + } else { + + 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) { From xeioex at nginx.com Sun Mar 10 13:41:46 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Sun, 10 Mar 2019 13:41:46 +0000 Subject: [njs] Refactored njs_parser_function_lambda(). Message-ID: details: https://hg.nginx.org/njs/rev/76a2f641e972 branches: changeset: 821:76a2f641e972 user: hongzhidao date: Sun Mar 10 17:44:16 2019 +0800 description: Refactored njs_parser_function_lambda(). The function is split into reusable components. diffstat: njs/njs_parser.c | 186 ++++++++++++++++++++++++++++++++++++------------------ njs/njs_parser.h | 3 + 2 files changed, 127 insertions(+), 62 deletions(-) diffs (267 lines): diff -r 79e9f062beae -r 76a2f641e972 njs/njs_parser.c --- a/njs/njs_parser.c Sun Mar 10 16:14:37 2019 +0300 +++ b/njs/njs_parser.c Sun Mar 10 17:44:16 2019 +0800 @@ -27,6 +27,15 @@ static njs_token_t njs_parser_function_d njs_parser_t *parser); static njs_token_t njs_parser_function_lambda(njs_vm_t *vm, njs_parser_t *parser, njs_function_lambda_t *lambda, njs_token_t token); +static njs_token_t njs_parser_lambda_arguments(njs_vm_t *vm, + njs_parser_t *parser, njs_function_lambda_t *lambda, njs_index_t index, + njs_token_t token); +static njs_token_t njs_parser_lambda_argument(njs_vm_t *vm, + njs_parser_t *parser, njs_index_t index); +static njs_token_t njs_parser_lambda_body(njs_vm_t *vm, njs_parser_t *parser, + njs_token_t token); +static njs_parser_node_t *njs_parser_return_set(njs_vm_t *vm, + njs_parser_t *parser, njs_parser_node_t *expr); static njs_token_t njs_parser_return_statement(njs_vm_t *vm, njs_parser_t *parser); static njs_token_t njs_parser_var_statement(njs_vm_t *vm, njs_parser_t *parser); @@ -735,26 +744,46 @@ static njs_token_t njs_parser_function_lambda(njs_vm_t *vm, njs_parser_t *parser, njs_function_lambda_t *lambda, njs_token_t token) { - njs_ret_t ret; - njs_index_t index; - njs_variable_t *arg; - njs_parser_node_t *node, *body, *last, *parent, *return_node; + njs_ret_t ret; + njs_index_t index; ret = njs_parser_scope_begin(vm, parser, NJS_SCOPE_FUNCTION); if (nxt_slow_path(ret != NXT_OK)) { return NJS_TOKEN_ERROR; } - token = njs_parser_match(vm, parser, token, NJS_TOKEN_OPEN_PARENTHESIS); - if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { - return token; - } - index = NJS_SCOPE_ARGUMENTS; /* A "this" reservation. */ index += sizeof(njs_value_t); + token = njs_parser_lambda_arguments(vm, parser, lambda, index, token); + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return token; + } + + token = njs_parser_lambda_body(vm, parser, token); + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return token; + } + + njs_parser_scope_end(vm, parser); + + return token; +} + + +static njs_token_t +njs_parser_lambda_arguments(njs_vm_t *vm, njs_parser_t *parser, + njs_function_lambda_t *lambda, njs_index_t index, njs_token_t token) +{ + token = njs_parser_match(vm, parser, token, NJS_TOKEN_OPEN_PARENTHESIS); + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return token; + } + + lambda->nargs = 0; + while (token != NJS_TOKEN_CLOSE_PARENTHESIS) { if (nxt_slow_path(lambda->rest_parameters)) { @@ -774,20 +803,7 @@ njs_parser_function_lambda(njs_vm_t *vm, return NJS_TOKEN_ILLEGAL; } - arg = njs_parser_variable_add(vm, parser, NJS_VARIABLE_VAR); - if (nxt_slow_path(arg == NULL)) { - return NJS_TOKEN_ERROR; - } - - arg->index = index; - index += sizeof(njs_value_t); - - ret = njs_name_copy(vm, &arg->name, njs_parser_text(parser)); - if (nxt_slow_path(ret != NXT_OK)) { - return NJS_TOKEN_ERROR; - } - - token = njs_parser_token(parser); + token = njs_parser_lambda_argument(vm, parser, index); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -798,36 +814,46 @@ njs_parser_function_lambda(njs_vm_t *vm, return token; } } - } - - lambda->nargs = njs_scope_offset(index) / sizeof(njs_value_t) - 1; - - token = njs_parser_token(parser); - if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { - return token; + + lambda->nargs++; + index += sizeof(njs_value_t); } - if (nxt_slow_path(token != NJS_TOKEN_OPEN_BRACE)) { - return NJS_TOKEN_ILLEGAL; + return njs_parser_token(parser); +} + + +static njs_token_t +njs_parser_lambda_argument(njs_vm_t *vm, njs_parser_t *parser, + njs_index_t index) +{ + njs_ret_t ret; + njs_variable_t *arg; + + arg = njs_parser_variable_add(vm, parser, NJS_VARIABLE_VAR); + if (nxt_slow_path(arg == NULL)) { + return NJS_TOKEN_ERROR; } - token = njs_parser_token(parser); - if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { - return token; + arg->index = index; + + ret = njs_name_copy(vm, &arg->name, njs_parser_text(parser)); + if (nxt_slow_path(ret != NXT_OK)) { + return NJS_TOKEN_ERROR; } + return njs_parser_token(parser); +} + + +static njs_token_t +njs_parser_lambda_body(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) +{ + njs_parser_node_t *body, *last, *parent; + parent = parser->node; - parser->node = NULL; - - while (token != NJS_TOKEN_CLOSE_BRACE) { - token = njs_parser_statement_chain(vm, parser, token, - &njs_parser_chain_top(parser)); - if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { - return token; - } - } - - token = njs_parser_token(parser); + + token = njs_parser_lambda_statements(vm, parser, token); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -853,34 +879,70 @@ 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)) { + body = njs_parser_return_set(vm, parser, NULL); + if (nxt_slow_path(body == 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 = body; - node->right = return_node; - - njs_parser_chain_top_set(parser, node); - - body = node; } parent->right = body; parser->node = parent; - njs_parser_scope_end(vm, parser); - return token; } +static njs_parser_node_t * +njs_parser_return_set(njs_vm_t *vm, njs_parser_t *parser, + njs_parser_node_t *expr) +{ + njs_parser_node_t *stmt, *node; + + node = njs_parser_node_new(vm, parser, NJS_TOKEN_RETURN); + if (nxt_slow_path(node == NULL)) { + return NULL; + } + + node->right = expr; + + stmt = njs_parser_node_new(vm, parser, NJS_TOKEN_STATEMENT); + if (nxt_slow_path(stmt == NULL)) { + return NULL; + } + + stmt->left = njs_parser_chain_top(parser); + stmt->right = node; + + njs_parser_chain_top_set(parser, stmt); + + return stmt; +} + + +njs_token_t +njs_parser_lambda_statements(njs_vm_t *vm, njs_parser_t *parser, + njs_token_t token) +{ + token = njs_parser_match(vm, parser, token, NJS_TOKEN_OPEN_BRACE); + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return token; + } + + parser->node = NULL; + + while (token != NJS_TOKEN_CLOSE_BRACE) { + token = njs_parser_statement_chain(vm, parser, token, + &njs_parser_chain_top(parser)); + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return token; + } + } + + return njs_parser_token(parser); +} + + static njs_token_t njs_parser_return_statement(njs_vm_t *vm, njs_parser_t *parser) { diff -r 79e9f062beae -r 76a2f641e972 njs/njs_parser.h --- a/njs/njs_parser.h Sun Mar 10 16:14:37 2019 +0300 +++ b/njs/njs_parser.h Sun Mar 10 17:44:16 2019 +0800 @@ -90,6 +90,9 @@ njs_token_t njs_parser_terminal(njs_vm_t njs_token_t token); 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); +njs_token_t njs_parser_lambda_statements(njs_vm_t *vm, njs_parser_t *parser, + njs_token_t token); + 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); From xeioex at nginx.com Sun Mar 10 13:41:45 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Sun, 10 Mar 2019 13:41:45 +0000 Subject: [njs] Improved njs_parser_reference(). Message-ID: details: https://hg.nginx.org/njs/rev/79e9f062beae branches: changeset: 820:79e9f062beae user: Dmitry Volyntsev date: Sun Mar 10 16:14:37 2019 +0300 description: Improved njs_parser_reference(). diffstat: njs/njs_parser.c | 17 +++++++++++------ 1 files changed, 11 insertions(+), 6 deletions(-) diffs (77 lines): diff -r 8e2cb4da5e46 -r 79e9f062beae njs/njs_parser.c --- a/njs/njs_parser.c Fri Mar 08 00:11:23 2019 +0800 +++ b/njs/njs_parser.c Sun Mar 10 16:14:37 2019 +0300 @@ -53,7 +53,8 @@ static njs_token_t njs_parser_throw_stat static njs_token_t njs_parser_grouping_expression(njs_vm_t *vm, njs_parser_t *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_parser_t *parser, njs_token_t token, nxt_str_t *name, uint32_t hash, + uint32_t token_line); 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); @@ -2038,7 +2039,8 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa default: node = njs_parser_reference(vm, parser, token, njs_parser_text(parser), - njs_parser_key_hash(parser)); + njs_parser_key_hash(parser), + njs_parser_token_line(parser)); if (nxt_slow_path(node == NULL)) { return NJS_TOKEN_ERROR; @@ -2055,7 +2057,7 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa 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) + nxt_str_t *name, uint32_t hash, uint32_t token_line) { njs_ret_t ret; njs_value_t *ext; @@ -2217,7 +2219,7 @@ njs_parser_reference(njs_vm_t *vm, njs_p case NJS_TOKEN_NAME: nxt_thread_log_debug("JS: %V", name); - node->token_line = njs_parser_token_line(parser); + node->token_line = token_line; ext = njs_external_lookup(vm, name, hash); @@ -2301,7 +2303,7 @@ njs_parser_builtin(njs_vm_t *vm, njs_par static njs_token_t njs_parser_object(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *obj) { - uint32_t hash; + uint32_t hash, token_line; nxt_str_t name; njs_token_t token; njs_lexer_t *lexer; @@ -2312,6 +2314,7 @@ njs_parser_object(njs_vm_t *vm, njs_pars /* GCC and Clang complain about uninitialized hash. */ hash = 0; + token_line = 0; object = njs_parser_node_new(vm, parser, NJS_TOKEN_OBJECT_VALUE); if (nxt_slow_path(object == NULL)) { @@ -2332,7 +2335,9 @@ njs_parser_object(njs_vm_t *vm, njs_pars case NJS_TOKEN_NAME: name = *njs_parser_text(parser); + hash = njs_parser_key_hash(parser); + token_line = njs_parser_token_line(parser); token = njs_parser_token(parser); break; @@ -2365,7 +2370,7 @@ njs_parser_object(njs_vm_t *vm, njs_pars && lexer->property_token != NJS_TOKEN_GLOBAL_THIS) { expression = njs_parser_reference(vm, parser, lexer->property_token, - &name, hash); + &name, hash, token_line); if (nxt_slow_path(expression == NULL)) { return NJS_TOKEN_ERROR; } From xeioex at nginx.com Sun Mar 10 15:47:13 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Sun, 10 Mar 2019 15:47:13 +0000 Subject: [njs] Added support for arbitrary number of peek tokens in lexer. Message-ID: details: https://hg.nginx.org/njs/rev/4e82cb630c69 branches: changeset: 822:4e82cb630c69 user: hongzhidao date: Sun Mar 10 22:25:59 2019 +0800 description: Added support for arbitrary number of peek tokens in lexer. diffstat: njs/njs_lexer.c | 131 ++++++++++++++++++++++++++++++++----------- njs/njs_lexer.h | 6 +- njs/njs_parser.c | 102 +++++++++++++++++----------------- njs/njs_parser.h | 2 +- njs/njs_parser_expression.c | 32 +++++----- 5 files changed, 170 insertions(+), 103 deletions(-) diffs (806 lines): diff -r 76a2f641e972 -r 4e82cb630c69 njs/njs_lexer.c --- a/njs/njs_lexer.c Sun Mar 10 17:44:16 2019 +0800 +++ b/njs/njs_lexer.c Sun Mar 10 22:25:59 2019 +0800 @@ -18,6 +18,11 @@ struct njs_lexer_multi_s { }; +static njs_lexer_token_t *njs_lexer_token_push(njs_vm_t *vm, + njs_lexer_t *lexer); +static njs_lexer_token_t *njs_lexer_token_pop(njs_lexer_t *lexer); +static njs_token_t njs_lexer_token_name_resolve(njs_lexer_t *lexer, + njs_lexer_token_t *lt); static njs_token_t njs_lexer_next_token(njs_lexer_t *lexer, njs_lexer_token_t *lt); static njs_token_t njs_lexer_word(njs_lexer_t *lexer, njs_lexer_token_t *lt, @@ -288,27 +293,112 @@ njs_lexer_init(njs_vm_t *vm, njs_lexer_t lexer->line = 1; lexer->keywords_hash = vm->shared->keywords_hash; - lexer->lexer_token = nxt_mp_alloc(vm->mem_pool, sizeof(njs_lexer_token_t)); - if (nxt_slow_path(lexer->lexer_token == NULL)) { - return NXT_ERROR; - } + nxt_queue_init(&lexer->preread); return NXT_OK; } njs_token_t -njs_lexer_token(njs_lexer_t *lexer) +njs_lexer_token(njs_vm_t *vm, njs_lexer_t *lexer) { njs_lexer_token_t *lt; - lt = lexer->lexer_token; + lexer->prev_start = lexer->start; + + if (lexer->lexer_token != NULL) { + lexer->prev_token = lexer->lexer_token->token; + nxt_mp_free(vm->mem_pool, lexer->lexer_token); + } + + if (nxt_queue_is_empty(&lexer->preread)) { + lt = njs_lexer_token_push(vm, lexer); + if (nxt_slow_path(lt == NULL)) { + return NJS_TOKEN_ERROR; + } + } + + lexer->lexer_token = njs_lexer_token_pop(lexer); + + return njs_lexer_token_name_resolve(lexer, lexer->lexer_token); +} + + +njs_token_t +njs_lexer_peek_token(njs_vm_t *vm, njs_lexer_t *lexer, size_t offset) +{ + size_t i; + nxt_queue_link_t *link; + njs_lexer_token_t *lt; + + /* GCC and Clang complain about uninitialized lt. */ + lt = NULL; + + link = nxt_queue_first(&lexer->preread); + + for (i = 0; i <= offset; i++) { + + if (link != nxt_queue_tail(&lexer->preread)) { - lexer->prev_start = lexer->start; - lexer->prev_token = lt->token; + lt = nxt_queue_link_data(link, njs_lexer_token_t, link); + + /* NJS_TOKEN_DIVISION stands for regexp literal. */ + + if (lt->token == NJS_TOKEN_DIVISION + || lt->token == NJS_TOKEN_END) + { + break; + } + + link = nxt_queue_next(link); + + } else { + + lt = njs_lexer_token_push(vm, lexer); + + if (nxt_slow_path(lt == NULL)) { + return NJS_TOKEN_ERROR; + } + } + } + + return njs_lexer_token_name_resolve(lexer, lt); +} + + +static njs_lexer_token_t * +njs_lexer_token_push(njs_vm_t *vm, njs_lexer_t *lexer) +{ + njs_lexer_token_t *lt; + + lt = nxt_mp_alloc(vm->mem_pool, sizeof(njs_lexer_token_t)); + if (nxt_slow_path(lt == NULL)) { + return NULL; + } lt->token = njs_lexer_next_token(lexer, lt); + nxt_queue_insert_tail(&lexer->preread, <->link); + + return lt; +} + + +static njs_lexer_token_t * +njs_lexer_token_pop(njs_lexer_t *lexer) +{ + nxt_queue_link_t *lnk; + + lnk = nxt_queue_first(&lexer->preread); + nxt_queue_remove(lnk); + + return nxt_queue_link_data(lnk, njs_lexer_token_t, link); +} + + +static njs_token_t +njs_lexer_token_name_resolve(njs_lexer_t *lexer, njs_lexer_token_t *lt) +{ if (lt->token == NJS_TOKEN_NAME) { njs_lexer_keyword(lexer, lt); @@ -322,31 +412,6 @@ njs_lexer_token(njs_lexer_t *lexer) } -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; -} - - static njs_token_t njs_lexer_next_token(njs_lexer_t *lexer, njs_lexer_token_t *lt) { diff -r 76a2f641e972 -r 4e82cb630c69 njs/njs_lexer.h --- a/njs/njs_lexer.h Sun Mar 10 17:44:16 2019 +0800 +++ b/njs/njs_lexer.h Sun Mar 10 22:25:59 2019 +0800 @@ -213,11 +213,13 @@ typedef struct { uint32_t key_hash; nxt_str_t text; double number; + nxt_queue_link_t link; } njs_lexer_token_t; typedef struct { njs_lexer_token_t *lexer_token; + nxt_queue_t preread; /* of njs_lexer_token_t */ u_char *prev_start; njs_token_t prev_token:16; @@ -244,8 +246,8 @@ typedef struct { nxt_int_t njs_lexer_init(njs_vm_t *vm, njs_lexer_t *lexer, nxt_str_t *file, u_char *start, u_char *end); -njs_token_t njs_lexer_token(njs_lexer_t *lexer); -njs_token_t njs_lexer_peek_token(njs_lexer_t *lexer); +njs_token_t njs_lexer_token(njs_vm_t *vm, njs_lexer_t *lexer); +njs_token_t njs_lexer_peek_token(njs_vm_t *vm, njs_lexer_t *lexer, size_t offset); nxt_int_t njs_lexer_keywords_init(nxt_mp_t *mp, nxt_lvlhsh_t *hash); void njs_lexer_keyword(njs_lexer_t *lexer, njs_lexer_token_t *lt); diff -r 76a2f641e972 -r 4e82cb630c69 njs/njs_parser.c --- a/njs/njs_parser.c Sun Mar 10 17:44:16 2019 +0800 +++ b/njs/njs_parser.c Sun Mar 10 22:25:59 2019 +0800 @@ -148,7 +148,7 @@ njs_parser(njs_vm_t *vm, njs_parser_t *p } } - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); while (token != NJS_TOKEN_END) { @@ -317,7 +317,7 @@ njs_parser_statement_chain(njs_vm_t *vm, *dest = node; while (token == NJS_TOKEN_SEMICOLON) { - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { break; } @@ -358,7 +358,7 @@ njs_parser_statement(njs_vm_t *vm, njs_p return njs_parser_try_statement(vm, parser); case NJS_TOKEN_SEMICOLON: - return njs_parser_token(parser); + return njs_parser_token(vm, parser); case NJS_TOKEN_OPEN_BRACE: return njs_parser_block_statement(vm, parser); @@ -375,7 +375,7 @@ njs_parser_statement(njs_vm_t *vm, njs_p default: if (token == NJS_TOKEN_NAME - && njs_lexer_peek_token(parser->lexer) == NJS_TOKEN_COLON) + && njs_lexer_peek_token(vm, parser->lexer, 0) == NJS_TOKEN_COLON) { return njs_parser_labelled_statement(vm, parser); } @@ -414,7 +414,7 @@ njs_parser_statement(njs_vm_t *vm, njs_p switch (token) { case NJS_TOKEN_SEMICOLON: - return njs_parser_token(parser); + return njs_parser_token(vm, parser); case NJS_TOKEN_CLOSE_BRACE: case NJS_TOKEN_END: @@ -438,7 +438,7 @@ njs_parser_block_statement(njs_vm_t *vm, njs_token_t token; njs_parser_node_t *node; - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -473,7 +473,7 @@ njs_parser_block_statement(njs_vm_t *vm, njs_parser_scope_end(vm, parser); - return njs_parser_token(parser); + return njs_parser_token(vm, parser); } @@ -504,7 +504,7 @@ njs_parser_match(njs_vm_t *vm, njs_parse njs_token_t match) { if (nxt_fast_path(token == match)) { - return njs_parser_token(parser); + return njs_parser_token(vm, parser); } return njs_parser_unexpected_token(vm, parser, token); @@ -553,7 +553,7 @@ njs_parser_labelled_statement(njs_vm_t * return NJS_TOKEN_ERROR; } - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -629,7 +629,7 @@ njs_parser_function_declaration(njs_vm_t node->token_line = njs_parser_token_line(parser); - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -654,7 +654,7 @@ njs_parser_function_declaration(njs_vm_t return NJS_TOKEN_ERROR; } - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -690,7 +690,7 @@ njs_parser_function_expression(njs_vm_t node->token_line = njs_parser_token_line(parser); parser->node = node; - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -710,7 +710,7 @@ njs_parser_function_expression(njs_vm_t return NJS_TOKEN_ERROR; } - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -793,7 +793,7 @@ njs_parser_lambda_arguments(njs_vm_t *vm if (nxt_slow_path(token == NJS_TOKEN_ELLIPSIS)) { lambda->rest_parameters = 1; - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return NJS_TOKEN_ILLEGAL; } @@ -809,7 +809,7 @@ njs_parser_lambda_arguments(njs_vm_t *vm } if (token == NJS_TOKEN_COMMA) { - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -819,7 +819,7 @@ njs_parser_lambda_arguments(njs_vm_t *vm index += sizeof(njs_value_t); } - return njs_parser_token(parser); + return njs_parser_token(vm, parser); } @@ -842,7 +842,7 @@ njs_parser_lambda_argument(njs_vm_t *vm, return NJS_TOKEN_ERROR; } - return njs_parser_token(parser); + return njs_parser_token(vm, parser); } @@ -939,7 +939,7 @@ njs_parser_lambda_statements(njs_vm_t *v } } - return njs_parser_token(parser); + return njs_parser_token(vm, parser); } @@ -968,7 +968,7 @@ njs_parser_return_statement(njs_vm_t *vm parser->node = node; - token = njs_lexer_token(parser->lexer); + token = njs_lexer_token(vm, parser->lexer); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -976,7 +976,7 @@ njs_parser_return_statement(njs_vm_t *vm switch (token) { case NJS_TOKEN_LINE_END: - return njs_parser_token(parser); + return njs_parser_token(vm, parser); case NJS_TOKEN_SEMICOLON: case NJS_TOKEN_CLOSE_BRACE: @@ -1013,7 +1013,7 @@ njs_parser_var_statement(njs_vm_t *vm, n left = NULL; do { - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -1043,7 +1043,7 @@ njs_parser_var_statement(njs_vm_t *vm, n return NJS_TOKEN_ERROR; } - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -1052,7 +1052,7 @@ njs_parser_var_statement(njs_vm_t *vm, n if (token == NJS_TOKEN_ASSIGNMENT) { - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -1113,7 +1113,7 @@ njs_parser_if_statement(njs_vm_t *vm, nj stmt = parser->node; - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -1185,7 +1185,7 @@ njs_parser_switch_statement(njs_vm_t *vm } if (token == NJS_TOKEN_CASE) { - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -1217,7 +1217,7 @@ njs_parser_switch_statement(njs_vm_t *vm branch->token = NJS_TOKEN_DEFAULT; dflt = branch; - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -1255,7 +1255,7 @@ njs_parser_switch_statement(njs_vm_t *vm parser->node = swtch; - return njs_parser_token(parser); + return njs_parser_token(vm, parser); } @@ -1296,7 +1296,7 @@ njs_parser_do_while_statement(njs_vm_t * njs_token_t token; njs_parser_node_t *node, *stmt; - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -1341,7 +1341,7 @@ njs_parser_for_statement(njs_vm_t *vm, n condition = NULL; update = NULL; - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -1465,7 +1465,7 @@ njs_parser_for_var_statement(njs_vm_t *v left = NULL; do { - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -1495,7 +1495,7 @@ njs_parser_for_var_statement(njs_vm_t *v return NJS_TOKEN_ERROR; } - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -1508,7 +1508,7 @@ njs_parser_for_var_statement(njs_vm_t *v if (token == NJS_TOKEN_ASSIGNMENT) { - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -1554,7 +1554,7 @@ njs_parser_for_var_in_statement(njs_vm_t njs_token_t token; njs_parser_node_t *node, *foreach; - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -1652,12 +1652,12 @@ njs_parser_brk_statement(njs_vm_t *vm, n node->token_line = njs_parser_token_line(parser); parser->node = node; - token = njs_lexer_token(parser->lexer); + token = njs_lexer_token(vm, parser->lexer); switch (token) { case NJS_TOKEN_LINE_END: - return njs_parser_token(parser); + return njs_parser_token(vm, parser); case NJS_TOKEN_NAME: name = *njs_parser_text(parser); @@ -1674,7 +1674,7 @@ njs_parser_brk_statement(njs_vm_t *vm, n return NJS_TOKEN_ERROR; } - return njs_parser_token(parser); + return njs_parser_token(vm, parser); case NJS_TOKEN_SEMICOLON: case NJS_TOKEN_CLOSE_BRACE: @@ -1709,7 +1709,7 @@ njs_parser_try_statement(njs_vm_t *vm, n try->left = parser->node; if (token == NJS_TOKEN_CATCH) { - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -1756,7 +1756,7 @@ njs_parser_try_statement(njs_vm_t *vm, n catch->left = node; - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -1815,7 +1815,7 @@ njs_parser_try_block(njs_vm_t *vm, njs_p njs_token_t token; njs_parser_node_t *node; - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token != NJS_TOKEN_OPEN_BRACE)) { return NJS_TOKEN_ILLEGAL; } @@ -1848,7 +1848,7 @@ njs_parser_throw_statement(njs_vm_t *vm, return NJS_TOKEN_ERROR; } - token = njs_lexer_token(parser->lexer); + token = njs_lexer_token(vm, parser->lexer); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -1878,7 +1878,7 @@ njs_parser_grouping_expression(njs_vm_t { njs_token_t token; - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -1906,7 +1906,7 @@ njs_parser_property_token(njs_vm_t *vm, parser->lexer->property = 1; - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); parser->lexer->property = 0; @@ -1929,12 +1929,12 @@ njs_parser_property_token(njs_vm_t *vm, njs_token_t -njs_parser_token(njs_parser_t *parser) +njs_parser_token(njs_vm_t *vm, njs_parser_t *parser) { njs_token_t token; do { - token = njs_lexer_token(parser->lexer); + token = njs_lexer_token(vm, parser->lexer); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; @@ -1955,7 +1955,7 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa if (token == NJS_TOKEN_OPEN_PARENTHESIS) { - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -2113,7 +2113,7 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa parser->node = node; - return njs_parser_token(parser); + return njs_parser_token(vm, parser); } @@ -2393,7 +2393,7 @@ njs_parser_object(njs_vm_t *vm, njs_pars switch (token) { case NJS_TOKEN_CLOSE_BRACE: - return njs_parser_token(parser); + return njs_parser_token(vm, parser); case NJS_TOKEN_NAME: name = *njs_parser_text(parser); @@ -2401,7 +2401,7 @@ njs_parser_object(njs_vm_t *vm, njs_pars hash = njs_parser_key_hash(parser); token_line = njs_parser_token_line(parser); - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); break; case NJS_TOKEN_NUMBER: @@ -2473,7 +2473,7 @@ njs_parser_object(njs_vm_t *vm, njs_pars left = stmt; if (token == NJS_TOKEN_CLOSE_BRACE) { - return njs_parser_token(parser); + return njs_parser_token(vm, parser); } if (nxt_slow_path(token != NJS_TOKEN_COMMA)) { @@ -2494,7 +2494,7 @@ njs_parser_array(njs_vm_t *vm, njs_parse left = NULL; for ( ;; ) { - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -2572,7 +2572,7 @@ njs_parser_array(njs_vm_t *vm, njs_parse obj->u.length = index; - return njs_parser_token(parser); + return njs_parser_token(vm, parser); } diff -r 76a2f641e972 -r 4e82cb630c69 njs/njs_parser.h --- a/njs/njs_parser.h Sun Mar 10 17:44:16 2019 +0800 +++ b/njs/njs_parser.h Sun Mar 10 22:25:59 2019 +0800 @@ -89,7 +89,7 @@ njs_token_t njs_parser_assignment_expres njs_token_t njs_parser_terminal(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token); 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); +njs_token_t njs_parser_token(njs_vm_t *vm, njs_parser_t *parser); njs_token_t njs_parser_lambda_statements(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token); diff -r 76a2f641e972 -r 4e82cb630c69 njs/njs_parser_expression.c --- a/njs/njs_parser_expression.c Sun Mar 10 17:44:16 2019 +0800 +++ b/njs/njs_parser_expression.c Sun Mar 10 22:25:59 2019 +0800 @@ -243,7 +243,7 @@ njs_parser_var_expression(njs_vm_t *vm, node->u.operation = operation; node->left = parser->node; - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -376,7 +376,7 @@ njs_parser_assignment_expression(njs_vm_ node->u.operation = operation; node->left = parser->node; - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -410,7 +410,7 @@ njs_parser_conditional_expression(njs_vm return token; } - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -441,7 +441,7 @@ njs_parser_conditional_expression(njs_vm node->left = parser->node; node->left->dest = cond; - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -499,7 +499,7 @@ njs_parser_binary_expression(njs_vm_t *v node->left = parser->node; node->left->dest = node; - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -538,7 +538,7 @@ njs_parser_exponential_expression(njs_vm node->left = parser->node; node->left->dest = node; - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -602,7 +602,7 @@ njs_parser_unary_expression(njs_vm_t *vm return njs_parser_inc_dec_expression(vm, parser, token); } - next = njs_parser_token(parser); + next = njs_parser_token(vm, parser); if (nxt_slow_path(next <= NJS_TOKEN_ILLEGAL)) { return next; } @@ -698,7 +698,7 @@ njs_parser_inc_dec_expression(njs_vm_t * return njs_parser_post_inc_dec_expression(vm, parser, token); } - next = njs_parser_token(parser); + next = njs_parser_token(vm, parser); if (nxt_slow_path(next <= NJS_TOKEN_ILLEGAL)) { return next; } @@ -777,7 +777,7 @@ njs_parser_post_inc_dec_expression(njs_v node->left = parser->node; parser->node = node; - return njs_parser_token(parser); + return njs_parser_token(vm, parser); } @@ -863,7 +863,7 @@ njs_parser_call_expression(njs_vm_t *vm, parser->node = func; - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -877,7 +877,7 @@ njs_parser_new_expression(njs_vm_t *vm, { njs_parser_node_t *func, *node; - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -957,7 +957,7 @@ njs_parser_new_expression(njs_vm_t *vm, parser->node = func; - return njs_parser_token(parser); + return njs_parser_token(vm, parser); } @@ -993,10 +993,10 @@ njs_parser_property_expression(njs_vm_t return NJS_TOKEN_ILLEGAL; } - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); } else { - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -1027,7 +1027,7 @@ njs_parser_property_brackets(njs_vm_t *v return NJS_TOKEN_ERROR; } - return njs_parser_token(parser); + return njs_parser_token(vm, parser); } @@ -1042,7 +1042,7 @@ njs_parser_arguments(njs_vm_t *vm, njs_p index = NJS_SCOPE_CALLEE_ARGUMENTS; do { - token = njs_parser_token(parser); + token = njs_parser_token(vm, parser); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } From xeioex at nginx.com Sun Mar 10 18:20:54 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Sun, 10 Mar 2019 18:20:54 +0000 Subject: [njs] Fixed heap-buffer-overflow in lexer. Message-ID: details: https://hg.nginx.org/njs/rev/5a27272949d8 branches: changeset: 823:5a27272949d8 user: Dmitry Volyntsev date: Sun Mar 10 21:13:26 2019 +0300 description: Fixed heap-buffer-overflow in lexer. The issue was introduced in 8e2cb4da5e46. diffstat: njs/njs_lexer.c | 19 ++----------------- njs/test/njs_unit_test.c | 3 +++ 2 files changed, 5 insertions(+), 17 deletions(-) diffs (51 lines): diff -r 4e82cb630c69 -r 5a27272949d8 njs/njs_lexer.c --- a/njs/njs_lexer.c Sun Mar 10 22:25:59 2019 +0800 +++ b/njs/njs_lexer.c Sun Mar 10 21:13:26 2019 +0300 @@ -371,7 +371,7 @@ njs_lexer_token_push(njs_vm_t *vm, njs_l { njs_lexer_token_t *lt; - lt = nxt_mp_alloc(vm->mem_pool, sizeof(njs_lexer_token_t)); + lt = nxt_mp_zalloc(vm->mem_pool, sizeof(njs_lexer_token_t)); if (nxt_slow_path(lt == NULL)) { return NULL; } @@ -542,24 +542,9 @@ njs_lexer_next_token(njs_lexer_t *lexer, /* Fall through. */ - case NJS_TOKEN_BITWISE_NOT: - case NJS_TOKEN_OPEN_PARENTHESIS: - case NJS_TOKEN_CLOSE_PARENTHESIS: - case NJS_TOKEN_OPEN_BRACKET: - case NJS_TOKEN_CLOSE_BRACKET: - case NJS_TOKEN_OPEN_BRACE: - case NJS_TOKEN_CLOSE_BRACE: - case NJS_TOKEN_COMMA: - case NJS_TOKEN_COLON: - case NJS_TOKEN_SEMICOLON: - case NJS_TOKEN_CONDITIONAL: + default: lt->text.length = lexer->start - lt->text.start; return token; - - case NJS_TOKEN_ILLEGAL: - default: - lexer->start--; - return token; } multi: diff -r 4e82cb630c69 -r 5a27272949d8 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Sun Mar 10 22:25:59 2019 +0800 +++ b/njs/test/njs_unit_test.c Sun Mar 10 21:13:26 2019 +0300 @@ -22,6 +22,9 @@ typedef struct { static njs_unit_test_t njs_test[] = { + { nxt_string("@"), + nxt_string("SyntaxError: Unexpected token \"@\" in 1") }, + { nxt_string("}"), nxt_string("SyntaxError: Unexpected token \"}\" in 1") }, From xeioex at nginx.com Sun Mar 10 19:49:38 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Sun, 10 Mar 2019 19:49:38 +0000 Subject: [njs] Introduced njs_parser_peek_token(). Message-ID: details: https://hg.nginx.org/njs/rev/0e8ab0dfd08b branches: changeset: 824:0e8ab0dfd08b user: Dmitry Volyntsev date: Sun Mar 10 22:26:25 2019 +0300 description: Introduced njs_parser_peek_token(). diffstat: njs/njs_parser.c | 20 +------------------- njs/njs_parser.h | 40 ++++++++++++++++++++++++++++++---------- 2 files changed, 31 insertions(+), 29 deletions(-) diffs (117 lines): diff -r 5a27272949d8 -r 0e8ab0dfd08b njs/njs_parser.c --- a/njs/njs_parser.c Sun Mar 10 21:13:26 2019 +0300 +++ b/njs/njs_parser.c Sun Mar 10 22:26:25 2019 +0300 @@ -375,7 +375,7 @@ njs_parser_statement(njs_vm_t *vm, njs_p default: if (token == NJS_TOKEN_NAME - && njs_lexer_peek_token(vm, parser->lexer, 0) == NJS_TOKEN_COLON) + && njs_parser_peek_token(vm, parser, 0) == NJS_TOKEN_COLON) { return njs_parser_labelled_statement(vm, parser); } @@ -1929,24 +1929,6 @@ njs_parser_property_token(njs_vm_t *vm, njs_token_t -njs_parser_token(njs_vm_t *vm, njs_parser_t *parser) -{ - njs_token_t token; - - do { - token = njs_lexer_token(vm, parser->lexer); - - if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { - return token; - } - - } while (nxt_slow_path(token == NJS_TOKEN_LINE_END)); - - return token; -} - - -njs_token_t njs_parser_terminal(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) { double num; diff -r 5a27272949d8 -r 0e8ab0dfd08b njs/njs_parser.h --- a/njs/njs_parser.h Sun Mar 10 21:13:26 2019 +0300 +++ b/njs/njs_parser.h Sun Mar 10 22:26:25 2019 +0300 @@ -8,10 +8,6 @@ #define _NJS_PARSER_H_INCLUDED_ -#define njs_parser_is_lvalue(node) \ - ((node)->token == NJS_TOKEN_NAME || (node)->token == NJS_TOKEN_PROPERTY) - - struct njs_parser_scope_s { njs_parser_node_t *top; @@ -89,10 +85,8 @@ njs_token_t njs_parser_assignment_expres njs_token_t njs_parser_terminal(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token); njs_token_t njs_parser_property_token(njs_vm_t *vm, njs_parser_t *parser); -njs_token_t njs_parser_token(njs_vm_t *vm, njs_parser_t *parser); njs_token_t njs_parser_lambda_statements(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token); - 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); @@ -105,6 +99,18 @@ void njs_parser_node_error(njs_vm_t *vm, njs_value_type_t type, const char *fmt, ...); +#define njs_parser_peek_token(vm, parser, offset) \ + njs_lexer_peek_token(vm, (parser)->lexer, offset) + + +#define njs_parser_is_lvalue(node) \ + ((node)->token == NJS_TOKEN_NAME || (node)->token == NJS_TOKEN_PROPERTY) + + +#define njs_scope_accumulative(vm, scope) \ + ((vm)->options.accumulative && (scope)->type == NJS_SCOPE_GLOBAL) + + #define njs_parser_syntax_error(vm, parser, fmt, ...) \ njs_parser_lexer_error(vm, parser, NJS_OBJECT_SYNTAX_ERROR, fmt, \ ##__VA_ARGS__) @@ -114,6 +120,24 @@ void njs_parser_node_error(njs_vm_t *vm, njs_parser_lexer_error(vm, parser, NJS_OBJECT_REF_ERROR, fmt, ##__VA_ARGS__) +nxt_inline njs_token_t +njs_parser_token(njs_vm_t *vm, njs_parser_t *parser) +{ + njs_token_t token; + + do { + token = njs_lexer_token(vm, parser->lexer); + + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return token; + } + + } while (nxt_slow_path(token == NJS_TOKEN_LINE_END)); + + return token; +} + + nxt_inline njs_parser_node_t * njs_parser_node_new(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) { @@ -145,10 +169,6 @@ 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; From xeioex at nginx.com Mon Mar 11 09:06:38 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 11 Mar 2019 09:06:38 +0000 Subject: [njs] Improved handling of arguments object. Message-ID: details: https://hg.nginx.org/njs/rev/a835619baf84 branches: changeset: 825:a835619baf84 user: Dmitry Volyntsev date: Mon Mar 11 11:15:20 2019 +0300 description: Improved handling of arguments object. diffstat: njs/njs_generator.c | 4 +--- njs/njs_generator.h | 1 - njs/njs_parser.c | 2 ++ njs/njs_parser.h | 1 + 4 files changed, 4 insertions(+), 4 deletions(-) diffs (55 lines): diff -r 0e8ab0dfd08b -r a835619baf84 njs/njs_generator.c --- a/njs/njs_generator.c Sun Mar 10 22:26:25 2019 +0300 +++ b/njs/njs_generator.c Mon Mar 11 11:15:20 2019 +0300 @@ -579,8 +579,6 @@ njs_generate_arguments_object(njs_vm_t * { njs_vmcode_arguments_t *gen; - generator->arguments_object = 1; - node->index = njs_generate_object_dest_index(vm, generator, node); if (nxt_slow_path(node->index == NJS_INDEX_ERROR)) { return NXT_ERROR; @@ -2312,7 +2310,7 @@ njs_generate_function_scope(njs_vm_t *vm lambda->closure_size = size; lambda->nesting = node->scope->nesting; - lambda->arguments_object = generator.arguments_object; + lambda->arguments_object = node->scope->arguments_object; lambda->start = generator.code_start; lambda->local_size = generator.scope_size; diff -r 0e8ab0dfd08b -r a835619baf84 njs/njs_generator.h --- a/njs/njs_generator.h Sun Mar 10 22:26:25 2019 +0300 +++ b/njs/njs_generator.h Mon Mar 11 11:15:20 2019 +0300 @@ -24,7 +24,6 @@ struct njs_generator_s { /* Parsing Function() or eval(). */ uint8_t runtime; /* 1 bit */ - uint8_t arguments_object; /* 1 bit */ }; diff -r 0e8ab0dfd08b -r a835619baf84 njs/njs_parser.c --- a/njs/njs_parser.c Sun Mar 10 22:26:25 2019 +0300 +++ b/njs/njs_parser.c Mon Mar 11 11:15:20 2019 +0300 @@ -2169,6 +2169,8 @@ njs_parser_reference(njs_vm_t *vm, njs_p return NULL; } + parser->scope->arguments_object = 1; + break; case NJS_TOKEN_OBJECT_CONSTRUCTOR: diff -r 0e8ab0dfd08b -r a835619baf84 njs/njs_parser.h --- a/njs/njs_parser.h Sun Mar 10 22:26:25 2019 +0300 +++ b/njs/njs_parser.h Mon Mar 11 11:15:20 2019 +0300 @@ -30,6 +30,7 @@ struct njs_parser_scope_s { njs_scope_t type:8; uint8_t nesting; /* 4 bits */ uint8_t argument_closures; + uint8_t arguments_object; }; From bjornar.ness at gmail.com Mon Mar 11 13:49:33 2019 From: bjornar.ness at gmail.com (=?UTF-8?Q?Bj=C3=B8rnar_Ness?=) Date: Mon, 11 Mar 2019 14:49:33 +0100 Subject: [nginx] Add abstract socket support on Linux Message-ID: # HG changeset patch # User Bjornar Ness # Date 1552311828 -3600 # Mon Mar 11 14:43:48 2019 +0100 # Node ID 9bf37762c5066b2f0ec3e6a312d97c86c4fdba18 # Parent c74904a1702135f673a275bd0d36f010a3bfb89a Add abstract socket support on Linux This patch adds abstract socket support for Linux, making it possible to both listen and connect to abstract socket: server { listen unix:@abstract-socket; } This is convenient for ephemeral sockets for i.e fastcgi/uwsgi diff -r c74904a17021 -r 9bf37762c506 src/core/ngx_connection.c --- a/src/core/ngx_connection.c Sat Mar 09 03:03:56 2019 +0300 +++ b/src/core/ngx_connection.c Mon Mar 11 14:43:48 2019 +0100 @@ -625,7 +625,12 @@ #if (NGX_HAVE_UNIX_DOMAIN) - if (ls[i].sockaddr->sa_family == AF_UNIX) { + if (ls[i].sockaddr->sa_family == AF_UNIX +#if (NGX_LINUX) + && ls[i].addr_text.data[sizeof("unix:") - 1] != '@' +#endif + ) + { mode_t mode; u_char *name; @@ -1069,6 +1074,9 @@ #if (NGX_HAVE_UNIX_DOMAIN) if (ls[i].sockaddr->sa_family == AF_UNIX +#if (NGX_LINUX) + && ls[i].addr_text.data[sizeof("unix:") - 1] != '@' +#endif && ngx_process <= NGX_PROCESS_MASTER && ngx_new_binary == 0) { diff -r c74904a17021 -r 9bf37762c506 src/core/ngx_cycle.c --- a/src/core/ngx_cycle.c Sat Mar 09 03:03:56 2019 +0300 +++ b/src/core/ngx_cycle.c Mon Mar 11 14:43:48 2019 +0100 @@ -709,7 +709,12 @@ #if (NGX_HAVE_UNIX_DOMAIN) - if (ls[i].sockaddr->sa_family == AF_UNIX) { + if (ls[i].sockaddr->sa_family == AF_UNIX +#if (NGX_LINUX) + && ls[i].addr_text.data[sizeof("unix:") - 1] != '@' +#endif + ) + { u_char *name; name = ls[i].addr_text.data + sizeof("unix:") - 1; diff -r c74904a17021 -r 9bf37762c506 src/core/ngx_inet.c --- a/src/core/ngx_inet.c Sat Mar 09 03:03:56 2019 +0300 +++ b/src/core/ngx_inet.c Mon Mar 11 14:43:48 2019 +0100 @@ -242,6 +242,9 @@ if (socklen <= (socklen_t) offsetof(struct sockaddr_un, sun_path)) { p = ngx_snprintf(text, len, "unix:%Z"); + } else if (saun->sun_path[0] == '\0') { + p = ngx_snprintf(text, len, "unix:@%s%Z", &saun->sun_path[1]); + } else { n = ngx_strnlen((u_char *) saun->sun_path, socklen - offsetof(struct sockaddr_un, sun_path)); @@ -744,6 +747,13 @@ saun->sun_family = AF_UNIX; (void) ngx_cpystrn((u_char *) saun->sun_path, path, len); +#if (NGX_LINUX) + if (path[0] == '@') { + saun->sun_path[0] = '\0'; + u->socklen = sizeof(sa_family_t) + strlen(path); + } +#endif + u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t)); if (u->addrs == NULL) { return NGX_ERROR; @@ -765,6 +775,13 @@ u->addrs[0].name.len = len + 4; u->addrs[0].name.data = u->url.data; +#if (NGX_LINUX) + if (path[0] == '@') { + saun->sun_path[0] = '\0'; + u->addrs[0].socklen = sizeof(sa_family_t) + strlen(path); + } +#endif + return NGX_OK; #else From xeioex at nginx.com Mon Mar 11 15:31:48 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 11 Mar 2019 15:31:48 +0000 Subject: [njs] Added Object.prototype.propertyIsEnumerable(). Message-ID: details: https://hg.nginx.org/njs/rev/49f4eb5afc9b branches: changeset: 826:49f4eb5afc9b user: Dmitry Volyntsev date: Mon Mar 11 18:31:40 2019 +0300 description: Added Object.prototype.propertyIsEnumerable(). diffstat: njs/njs_object.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ njs/test/njs_unit_test.c | 24 ++++++++++++++++++++++ 2 files changed, 76 insertions(+), 0 deletions(-) diffs (117 lines): diff -r a835619baf84 -r 49f4eb5afc9b njs/njs_object.c --- a/njs/njs_object.c Mon Mar 11 11:15:20 2019 +0300 +++ b/njs/njs_object.c Mon Mar 11 18:31:40 2019 +0300 @@ -2458,6 +2458,51 @@ njs_object_prototype_has_own_property(nj static njs_ret_t +njs_object_prototype_prop_is_enumerable(njs_vm_t *vm, njs_value_t *args, + nxt_uint_t nargs, njs_index_t unused) +{ + nxt_int_t ret; + const njs_value_t *value, *property, *retval; + njs_object_prop_t *prop; + njs_property_query_t pq; + + value = njs_arg(args, nargs, 0); + + if (njs_is_null_or_void(value)) { + njs_type_error(vm, "cannot convert %s argument to object", + njs_type_string(value->type)); + return NXT_ERROR; + } + + property = njs_arg(args, nargs, 1); + + njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 1); + + ret = njs_property_query(vm, &pq, (njs_value_t *) value, property); + + switch (ret) { + case NXT_OK: + prop = pq.lhq.value; + retval = prop->enumerable ? &njs_value_true : &njs_value_false; + break; + + case NXT_DECLINED: + retval = &njs_value_false; + break; + + case NJS_TRAP: + case NXT_ERROR: + default: + return ret; + } + + vm->retval = *retval; + + return NXT_OK; +} + + +static njs_ret_t njs_object_prototype_is_prototype_of(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) { @@ -2524,6 +2569,13 @@ static const njs_object_prop_t njs_obje { .type = NJS_METHOD, + .name = njs_long_string("propertyIsEnumerable"), + .value = njs_native_function(njs_object_prototype_prop_is_enumerable, 0, + NJS_OBJECT_ARG, NJS_STRING_ARG), + }, + + { + .type = NJS_METHOD, .name = njs_string("isPrototypeOf"), .value = njs_native_function(njs_object_prototype_is_prototype_of, 0, NJS_OBJECT_ARG, NJS_OBJECT_ARG), diff -r a835619baf84 -r 49f4eb5afc9b njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Mon Mar 11 11:15:20 2019 +0300 +++ b/njs/test/njs_unit_test.c Mon Mar 11 18:31:40 2019 +0300 @@ -8464,6 +8464,12 @@ static njs_unit_test_t njs_test[] = { nxt_string("[1,2].hasOwnProperty('len')"), nxt_string("false") }, + { nxt_string("[1,2].hasOwnProperty('0')"), + nxt_string("true") }, + + { nxt_string("[1,2].hasOwnProperty('2')"), + nxt_string("false") }, + { nxt_string("[].hasOwnProperty('length')"), nxt_string("true") }, @@ -8485,6 +8491,12 @@ static njs_unit_test_t njs_test[] = { nxt_string("'s'.hasOwnProperty('b')"), nxt_string("false") }, + { nxt_string("'s'.hasOwnProperty('0')"), + nxt_string("true") }, + + { nxt_string("'s'.hasOwnProperty('1')"), + nxt_string("false") }, + { nxt_string("var p = { a:5 }; var o = Object.create(p);" "Object.getPrototypeOf(o) === p"), nxt_string("true") }, @@ -8607,6 +8619,18 @@ static njs_unit_test_t njs_test[] = { nxt_string("Object.getOwnPropertyDescriptor(1, '0')"), nxt_string("undefined") }, + { nxt_string("'????'.propertyIsEnumerable('0')"), + nxt_string("true") }, + + { nxt_string("({a:1}).propertyIsEnumerable({toString:function () {return 'a';}})"), + nxt_string("true") }, + + { nxt_string("'????'.propertyIsEnumerable('a')"), + nxt_string("false") }, + + { nxt_string("'????'.propertyIsEnumerable('length')"), + nxt_string("false") }, + { nxt_string("var min = Object.getOwnPropertyDescriptor(Math, 'min').value;" "[min(1,2), min(2,1), min(-1,1)]"), nxt_string("1,1,-1") }, From xeioex at nginx.com Tue Mar 12 16:30:28 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 12 Mar 2019 16:30:28 +0000 Subject: [njs] Reporting file name and function name in disassembler output. Message-ID: details: https://hg.nginx.org/njs/rev/dcc7965410bd branches: changeset: 827:dcc7965410bd user: Dmitry Volyntsev date: Tue Mar 12 19:28:11 2019 +0300 description: Reporting file name and function name in disassembler output. diffstat: njs/njs.c | 2 +- njs/njs_disassembler.c | 2 ++ njs/njs_generator.c | 16 ++++++++++------ njs/njs_generator.h | 2 +- njs/njs_vm.c | 19 ++++++++++--------- njs/njs_vm.h | 7 +++++++ 6 files changed, 31 insertions(+), 17 deletions(-) diffs (192 lines): diff -r 49f4eb5afc9b -r dcc7965410bd njs/njs.c --- a/njs/njs.c Mon Mar 11 18:31:40 2019 +0300 +++ b/njs/njs.c Tue Mar 12 19:28:11 2019 +0300 @@ -271,7 +271,7 @@ njs_vm_compile(njs_vm_t *vm, u_char **st nxt_memzero(&generator, sizeof(njs_generator_t)); - ret = njs_generate_scope(vm, &generator, scope); + ret = njs_generate_scope(vm, &generator, scope, &njs_entry_main); if (nxt_slow_path(ret != NXT_OK)) { goto fail; } diff -r 49f4eb5afc9b -r dcc7965410bd njs/njs_disassembler.c --- a/njs/njs_disassembler.c Mon Mar 11 18:31:40 2019 +0300 +++ b/njs/njs_disassembler.c Tue Mar 12 19:28:11 2019 +0300 @@ -139,6 +139,8 @@ njs_disassembler(njs_vm_t *vm) n = vm->code->items; while (n != 0) { + printf("%.*s:%.*s\n", (int) code->file.length, code->file.start, + (int) code->name.length, code->name.start); njs_disassemble(code->start, code->end); code++; n--; diff -r 49f4eb5afc9b -r dcc7965410bd njs/njs_generator.c --- a/njs/njs_generator.c Mon Mar 11 18:31:40 2019 +0300 +++ b/njs/njs_generator.c Tue Mar 12 19:28:11 2019 +0300 @@ -138,7 +138,8 @@ static nxt_int_t njs_generate_inc_dec_op static nxt_int_t njs_generate_function_declaration(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node); static nxt_int_t njs_generate_function_scope(njs_vm_t *vm, - njs_function_lambda_t *lambda, njs_parser_node_t *node); + njs_function_lambda_t *lambda, njs_parser_node_t *node, + const nxt_str_t *name); static nxt_int_t njs_generate_argument_closures(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node); static nxt_int_t njs_generate_return_statement(njs_vm_t *vm, @@ -1913,7 +1914,7 @@ njs_generate_function(njs_vm_t *vm, njs_ lambda = node->u.value.data.u.lambda; - ret = njs_generate_function_scope(vm, lambda, node); + ret = njs_generate_function_scope(vm, lambda, node, &njs_entry_anonymous); if (nxt_slow_path(ret != NXT_OK)) { return ret; @@ -2269,7 +2270,8 @@ njs_generate_function_declaration(njs_vm lambda = var->value.data.u.function->u.lambda; - ret = njs_generate_function_scope(vm, lambda, node); + ret = njs_generate_function_scope(vm, lambda, node, + &node->u.reference.name); if (nxt_slow_path(ret != NXT_OK)) { return ret; } @@ -2284,7 +2286,7 @@ njs_generate_function_declaration(njs_vm static nxt_int_t njs_generate_function_scope(njs_vm_t *vm, njs_function_lambda_t *lambda, - njs_parser_node_t *node) + njs_parser_node_t *node, const nxt_str_t *name) { size_t size; nxt_int_t ret; @@ -2295,7 +2297,7 @@ njs_generate_function_scope(njs_vm_t *vm nxt_memzero(&generator, sizeof(njs_generator_t)); - ret = njs_generate_scope(vm, &generator, node->scope); + ret = njs_generate_scope(vm, &generator, node->scope, name); if (nxt_fast_path(ret == NXT_OK)) { size = 0; @@ -2323,7 +2325,7 @@ njs_generate_function_scope(njs_vm_t *vm nxt_int_t njs_generate_scope(njs_vm_t *vm, njs_generator_t *generator, - njs_parser_scope_t *scope) + njs_parser_scope_t *scope, const nxt_str_t *name) { u_char *p; size_t size; @@ -2393,6 +2395,8 @@ njs_generate_scope(njs_vm_t *vm, njs_gen code->start = generator->code_start; code->end = generator->code_end; + code->file = scope->file; + code->name = *name; return NXT_OK; } diff -r 49f4eb5afc9b -r dcc7965410bd njs/njs_generator.h --- a/njs/njs_generator.h Mon Mar 11 18:31:40 2019 +0300 +++ b/njs/njs_generator.h Tue Mar 12 19:28:11 2019 +0300 @@ -28,7 +28,7 @@ struct njs_generator_s { nxt_int_t njs_generate_scope(njs_vm_t *vm, njs_generator_t *generator, - njs_parser_scope_t *scope); + njs_parser_scope_t *scope, const nxt_str_t *name); #endif /* _NJS_GENERATOR_H_INCLUDED_ */ diff -r 49f4eb5afc9b -r dcc7965410bd njs/njs_vm.c --- a/njs/njs_vm.c Mon Mar 11 18:31:40 2019 +0300 +++ b/njs/njs_vm.c Tue Mar 12 19:28:11 2019 +0300 @@ -95,6 +95,12 @@ const njs_value_t njs_string_function = const njs_value_t njs_string_memory_error = njs_string("MemoryError"); +const nxt_str_t njs_entry_main = nxt_string("main"); +const nxt_str_t njs_entry_native = nxt_string("native"); +const nxt_str_t njs_entry_unknown = nxt_string("unknown"); +const nxt_str_t njs_entry_anonymous = nxt_string("anonymous"); + + /* * The nJSVM is optimized for an ABIs where the first several arguments * are passed in registers (AMD64, ARM32/64): two pointers to the operand @@ -3497,11 +3503,6 @@ njs_vm_add_backtrace_entry(njs_vm_t *vm, njs_function_lambda_t *lambda; njs_backtrace_entry_t *be; - static const nxt_str_t entry_main = nxt_string("main"); - static const nxt_str_t entry_native = nxt_string("native"); - static const nxt_str_t entry_unknown = nxt_string("unknown"); - static const nxt_str_t entry_anonymous = nxt_string("anonymous"); - native_frame = &frame->native; function = native_frame->function; @@ -3513,7 +3514,7 @@ njs_vm_add_backtrace_entry(njs_vm_t *vm, be->line = 0; if (function == NULL) { - be->name = entry_main; + be->name = njs_entry_main; return NXT_OK; } @@ -3529,7 +3530,7 @@ njs_vm_add_backtrace_entry(njs_vm_t *vm, return NXT_OK; } - be->name = entry_native; + be->name = njs_entry_native; return NXT_OK; } @@ -3543,7 +3544,7 @@ njs_vm_add_backtrace_entry(njs_vm_t *vm, be->name = debug_entry[i].name; } else { - be->name = entry_anonymous; + be->name = njs_entry_anonymous; } be->file = debug_entry[i].file; @@ -3553,7 +3554,7 @@ njs_vm_add_backtrace_entry(njs_vm_t *vm, } } - be->name = entry_unknown; + be->name = njs_entry_unknown; return NXT_OK; } diff -r 49f4eb5afc9b -r dcc7965410bd njs/njs_vm.h --- a/njs/njs_vm.h Mon Mar 11 18:31:40 2019 +0300 +++ b/njs/njs_vm.h Tue Mar 12 19:28:11 2019 +0300 @@ -1095,6 +1095,8 @@ struct njs_vm_s { typedef struct { u_char *start; u_char *end; + nxt_str_t file; + nxt_str_t name; } njs_vm_code_t; @@ -1297,6 +1299,11 @@ extern const njs_value_t njs_string_nan extern const njs_value_t njs_string_internal_error; extern const njs_value_t njs_string_memory_error; +extern const nxt_str_t njs_entry_main; +extern const nxt_str_t njs_entry_native; +extern const nxt_str_t njs_entry_unknown; +extern const nxt_str_t njs_entry_anonymous; + extern const nxt_mem_proto_t njs_array_mem_proto; extern const nxt_lvlhsh_proto_t njs_object_hash_proto; From borovcanindusan1 at gmail.com Thu Mar 14 18:10:00 2019 From: borovcanindusan1 at gmail.com (=?UTF-8?B?RHXFoWFuIEJvcm92xI1hbmlu?=) Date: Thu, 14 Mar 2019 19:10:00 +0100 Subject: MQTT TLS client certificates using NJS Message-ID: Hi, I'm working on mutual authentication feature between MQTT client and broker, and I follow these tutorials: https://www.nginx.com/blog/nginx-plus-iot-load-balancing-mqtt and https://www.nginx.com/blog/nginx-plus-iot-security-encrypt-authenticate-mqtt/#mqtt-client-certs. However, the code examples are extremely out of date and this JavaScript code does not work with recent versions of njs, so I've tried to write my own code following your example from here: https://gist.github.com/nginx-gists/0e93fe7813ec131fed8329d10ead70ea#file-mqtt-js . However, I can't figure out what is the possible replacement for the following snippet: if ( s.buffer.toString().length == 0 ) { // Initial calls may > s.log("No buffer yet"); // contain no data, so > return s.AGAIN; // ask that we get called again } else if ( client_messages == 1 ) { // CONNECT is first packet from the > client... >From version 0.2.4, s.(OK, ABORT, AGAIN, DECLINED, ERROR) are replace with s.(allow(), done(), decline()). In my case, the initial call does not contain any data. In logs, I can see that I always read only 4 bytes of data received from the client. So when I send, let say, 50 bytes of data, an event is triggered, but data passed to `upload` callback is empty. Is this a bug? Can I somehow trigger this callback again? Best regards, Du?an Borov?anin -------------- next part -------------- An HTML attachment was scrubbed... URL: From drasko.draskovic at gmail.com Thu Mar 14 18:14:01 2019 From: drasko.draskovic at gmail.com (Drasko DRASKOVIC) Date: Thu, 14 Mar 2019 19:14:01 +0100 Subject: MQTT TLS client certificates using NJS In-Reply-To: References: Message-ID: Hi all, Dusan is refering to an issue https://github.com/nginx/njs/issues/111 BR, Drasko On Thu, Mar 14, 2019 at 7:10 PM Du?an Borov?anin wrote: > > Hi, > > I'm working on mutual authentication feature between MQTT client and broker, and I follow these tutorials: https://www.nginx.com/blog/nginx-plus-iot-load-balancing-mqtt and https://www.nginx.com/blog/nginx-plus-iot-security-encrypt-authenticate-mqtt/#mqtt-client-certs. However, the code examples are extremely out of date and this JavaScript code does not work with recent versions of njs, so I've tried to write my own code following your example from here: https://gist.github.com/nginx-gists/0e93fe7813ec131fed8329d10ead70ea#file-mqtt-js. However, I can't figure out what is the possible replacement for the following snippet: > >> if ( s.buffer.toString().length == 0 ) { // Initial calls may >> s.log("No buffer yet"); // contain no data, so >> return s.AGAIN; // ask that we get called again >> >> } else if ( client_messages == 1 ) { // CONNECT is first packet from the client... > > From version 0.2.4, s.(OK, ABORT, AGAIN, DECLINED, ERROR) are replace with s.(allow(), done(), decline()). In my case, the initial call does not contain any data. In logs, I can see that I always read only 4 bytes of data received from the client. So when I send, let say, 50 bytes of data, an event is triggered, but data passed to `upload` callback is empty. Is this a bug? Can I somehow trigger this callback again? > > Best regards, > Du?an Borov?anin > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel From hidinginthebbc at gmail.com Fri Mar 15 10:23:15 2019 From: hidinginthebbc at gmail.com (Thomas Peterson) Date: Fri, 15 Mar 2019 10:23:15 +0000 Subject: [PATCH] Apply cache locking behaviour to stale cache entries. In-Reply-To: <20190117132401.GJ99070@mdounin.ru> References: <20181210190717.GV99070@mdounin.ru> <20190117132401.GJ99070@mdounin.ru> Message-ID: Hi Max, It's now been several months since you last responded to this patch - is there any particular action we can take to help move things along please? Regards On 17/01/2019 13:24, Maxim Dounin wrote: > Hello! > > On Wed, Jan 16, 2019 at 10:20:59AM +0000, Elliot Thomas wrote: > >> With regards to the cache locking on stale patch, are there any further >> improvements I should make? > Sorry, I'm a bit busy with other tasks now. Hopefully I'll > be able to look again at the patch later this month. > From xeioex at nginx.com Fri Mar 15 10:59:34 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 15 Mar 2019 10:59:34 +0000 Subject: [njs] Introducing UNIT makefile dependency scripts. Message-ID: details: https://hg.nginx.org/njs/rev/a750d6fdc54a branches: changeset: 828:a750d6fdc54a user: Dmitry Volyntsev date: Wed Mar 13 15:04:58 2019 +0800 description: Introducing UNIT makefile dependency scripts. 1) Autogenerating Makefile. 2) Correct makefile dependency tracking. 3) Makefile.conf is removed. 4) nxt/auto scripts moved to auto. In collaboration with ??? (Hong Zhi Dao). This closes #110 issue on Github. diffstat: Makefile | 576 ------------------------------------------------ auto/clang | 321 ++++++++++++++++++++++++++ auto/define | 12 + auto/deps | 29 ++ auto/echo | 12 + auto/editline | 55 ++++ auto/expect | 36 +++ auto/explicit_bzero | 40 +++ auto/feature | 112 +++++++++ auto/getrandom | 91 +++++++ auto/make | 275 ++++++++++++++++++++++ auto/memalign | 50 ++++ auto/os | 57 ++++ auto/pcre | 41 +++ auto/sources | 65 +++++ auto/time | 69 +++++ configure | 52 ++++- nginx/config | 4 +- nginx/config.make | 2 +- nxt/Makefile | 273 ---------------------- nxt/auto/clang | 321 -------------------------- nxt/auto/configure | 60 ----- nxt/auto/define | 12 - nxt/auto/echo | 12 - nxt/auto/editline | 59 ---- nxt/auto/expect | 36 --- nxt/auto/explicit_bzero | 40 --- nxt/auto/feature | 112 --------- nxt/auto/getrandom | 91 ------- nxt/auto/memalign | 50 ---- nxt/auto/os | 57 ---- nxt/auto/pcre | 47 --- nxt/auto/time | 73 ------ nxt/test/Makefile | 57 ---- 34 files changed, 1316 insertions(+), 1883 deletions(-) diffs (truncated from 3359 to 1000 lines): diff -r dcc7965410bd -r a750d6fdc54a Makefile --- a/Makefile Tue Mar 12 19:28:11 2019 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,576 +0,0 @@ - -NXT_LIB = nxt - --include $(NXT_LIB)/Makefile.conf - -NXT_BUILDDIR = build - -$(NXT_BUILDDIR)/libnjs.a: \ - $(NXT_LIB)/nxt_auto_config.h \ - $(NXT_BUILDDIR)/njs_shell.o \ - $(NXT_BUILDDIR)/njs_vm.o \ - $(NXT_BUILDDIR)/njs_boolean.o \ - $(NXT_BUILDDIR)/njs_number.o \ - $(NXT_BUILDDIR)/njs_string.o \ - $(NXT_BUILDDIR)/njs_object.o \ - $(NXT_BUILDDIR)/njs_array.o \ - $(NXT_BUILDDIR)/njs_json.o \ - $(NXT_BUILDDIR)/njs_function.o \ - $(NXT_BUILDDIR)/njs_regexp.o \ - $(NXT_BUILDDIR)/njs_date.o \ - $(NXT_BUILDDIR)/njs_error.o \ - $(NXT_BUILDDIR)/njs_math.o \ - $(NXT_BUILDDIR)/njs_time.o \ - $(NXT_BUILDDIR)/njs_module.o \ - $(NXT_BUILDDIR)/njs_event.o \ - $(NXT_BUILDDIR)/njs_fs.o \ - $(NXT_BUILDDIR)/njs_crypto.o \ - $(NXT_BUILDDIR)/njs_extern.o \ - $(NXT_BUILDDIR)/njs_variable.o \ - $(NXT_BUILDDIR)/njs_builtin.o \ - $(NXT_BUILDDIR)/njs_lexer.o \ - $(NXT_BUILDDIR)/njs_lexer_keyword.o \ - $(NXT_BUILDDIR)/njs_parser.o \ - $(NXT_BUILDDIR)/njs_parser_expression.o \ - $(NXT_BUILDDIR)/njs_generator.o \ - $(NXT_BUILDDIR)/njs_disassembler.o \ - $(NXT_BUILDDIR)/nxt_diyfp.o \ - $(NXT_BUILDDIR)/nxt_dtoa.o \ - $(NXT_BUILDDIR)/nxt_strtod.o \ - $(NXT_BUILDDIR)/nxt_djb_hash.o \ - $(NXT_BUILDDIR)/nxt_utf8.o \ - $(NXT_BUILDDIR)/nxt_array.o \ - $(NXT_BUILDDIR)/nxt_rbtree.o \ - $(NXT_BUILDDIR)/nxt_lvlhsh.o \ - $(NXT_BUILDDIR)/nxt_trace.o \ - $(NXT_BUILDDIR)/nxt_random.o \ - $(NXT_BUILDDIR)/nxt_md5.o \ - $(NXT_BUILDDIR)/nxt_sha1.o \ - $(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 \ - - ar -r -c $(NXT_BUILDDIR)/libnjs.a \ - $(NXT_BUILDDIR)/njs_shell.o \ - $(NXT_BUILDDIR)/njs_vm.o \ - $(NXT_BUILDDIR)/njs_boolean.o \ - $(NXT_BUILDDIR)/njs_number.o \ - $(NXT_BUILDDIR)/njs_string.o \ - $(NXT_BUILDDIR)/njs_object.o \ - $(NXT_BUILDDIR)/njs_array.o \ - $(NXT_BUILDDIR)/njs_json.o \ - $(NXT_BUILDDIR)/njs_function.o \ - $(NXT_BUILDDIR)/njs_regexp.o \ - $(NXT_BUILDDIR)/njs_date.o \ - $(NXT_BUILDDIR)/njs_error.o \ - $(NXT_BUILDDIR)/njs_math.o \ - $(NXT_BUILDDIR)/njs_time.o \ - $(NXT_BUILDDIR)/njs_module.o \ - $(NXT_BUILDDIR)/njs_event.o \ - $(NXT_BUILDDIR)/njs_fs.o \ - $(NXT_BUILDDIR)/njs_crypto.o \ - $(NXT_BUILDDIR)/njs_extern.o \ - $(NXT_BUILDDIR)/njs_variable.o \ - $(NXT_BUILDDIR)/njs_builtin.o \ - $(NXT_BUILDDIR)/njs_lexer.o \ - $(NXT_BUILDDIR)/njs_lexer_keyword.o \ - $(NXT_BUILDDIR)/njs_parser.o \ - $(NXT_BUILDDIR)/njs_parser_expression.o \ - $(NXT_BUILDDIR)/njs_generator.o \ - $(NXT_BUILDDIR)/njs_disassembler.o \ - $(NXT_BUILDDIR)/nxt_diyfp.o \ - $(NXT_BUILDDIR)/nxt_dtoa.o \ - $(NXT_BUILDDIR)/nxt_strtod.o \ - $(NXT_BUILDDIR)/nxt_djb_hash.o \ - $(NXT_BUILDDIR)/nxt_utf8.o \ - $(NXT_BUILDDIR)/nxt_array.o \ - $(NXT_BUILDDIR)/nxt_rbtree.o \ - $(NXT_BUILDDIR)/nxt_lvlhsh.o \ - $(NXT_BUILDDIR)/nxt_trace.o \ - $(NXT_BUILDDIR)/nxt_random.o \ - $(NXT_BUILDDIR)/nxt_md5.o \ - $(NXT_BUILDDIR)/nxt_sha1.o \ - $(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 \ - -all: test lib_test - -njs: $(NXT_BUILDDIR)/njs - -libnjs: $(NXT_BUILDDIR)/libnjs.a - -njs_interactive_test: njs_expect_test $(NXT_BUILDDIR)/njs_interactive_test - $(NXT_BUILDDIR)/njs_interactive_test - -test: lib_test \ - njs_interactive_test \ - $(NXT_BUILDDIR)/njs_unit_test \ - $(NXT_BUILDDIR)/njs_benchmark \ - - $(NXT_BUILDDIR)/njs_unit_test - -clean: - rm -rf $(NXT_BUILDDIR) - rm -f $(NXT_LIB)/Makefile.conf $(NXT_LIB)/nxt_auto_config.h - -dist: - NJS_VER=`grep NJS_VERSION njs/njs.h | sed -e 's/.*"\(.*\)".*/\1/'`; \ - rm -rf njs-$${NJS_VER} \ - && hg archive njs-$${NJS_VER}.tar.gz \ - -p njs-$${NJS_VER} \ - -X ".hg*" \ - && echo njs-$${NJS_VER}.tar.gz done - -$(NXT_LIB)/nxt_auto_config.h: - @echo - @echo " Please run ./configure before make" - @echo - @exit 1 - -$(NXT_BUILDDIR)/njs_shell.o: \ - $(NXT_BUILDDIR)/libnxt.a \ - njs/njs.h \ - njs/njs_core.h \ - njs/njs_vm.h \ - njs/njs_string.h \ - njs/njs_object.h \ - njs/njs_function.h \ - njs/njs_parser.h \ - njs/njs_generator.h \ - njs/njs.h \ - njs/njs.c \ - - $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_shell.o $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs \ - njs/njs.c - -$(NXT_BUILDDIR)/njs_vm.o: \ - $(NXT_BUILDDIR)/libnxt.a \ - njs/njs.h \ - njs/njs_core.h \ - njs/njs_vm.h \ - njs/njs_number.h \ - njs/njs_string.h \ - njs/njs_object.h \ - njs/njs_object_hash.h \ - njs/njs_array.h \ - njs/njs_function.h \ - njs/njs_regexp.h \ - njs/njs_extern.h \ - njs/njs_variable.h \ - njs/njs_parser.h \ - njs/njs_vm.c \ - - $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_vm.o $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs \ - njs/njs_vm.c - -$(NXT_BUILDDIR)/njs_boolean.o: \ - $(NXT_BUILDDIR)/libnxt.a \ - njs/njs.h \ - njs/njs_vm.h \ - njs/njs_boolean.h \ - njs/njs_object.h \ - njs/njs_function.h \ - njs/njs_boolean.c \ - - $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_boolean.o $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs \ - njs/njs_boolean.c - -$(NXT_BUILDDIR)/njs_number.o: \ - $(NXT_BUILDDIR)/libnxt.a \ - njs/njs.h \ - njs/njs_core.h \ - njs/njs_vm.h \ - njs/njs_number.h \ - njs/njs_string.h \ - njs/njs_object.h \ - njs/njs_array.h \ - njs/njs_function.h \ - njs/njs_number.c \ - - $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_number.o $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs \ - njs/njs_number.c - -$(NXT_BUILDDIR)/njs_string.o: \ - $(NXT_BUILDDIR)/libnxt.a \ - njs/njs.h \ - njs/njs_core.h \ - njs/njs_vm.h \ - njs/njs_number.h \ - njs/njs_string.h \ - njs/njs_object.h \ - njs/njs_object_hash.h \ - njs/njs_array.h \ - njs/njs_function.h \ - njs/njs_regexp.h \ - njs/njs_parser.h \ - njs/njs_string.c \ - - $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_string.o $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs $(NXT_PCRE_CFLAGS) \ - njs/njs_string.c - -$(NXT_BUILDDIR)/njs_object.o: \ - $(NXT_BUILDDIR)/libnxt.a \ - njs/njs.h \ - njs/njs_core.h \ - njs/njs_vm.h \ - njs/njs_object.h \ - njs/njs_object_hash.h \ - njs/njs_function.h \ - njs/njs_object.c \ - - $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_object.o $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs \ - njs/njs_object.c - -$(NXT_BUILDDIR)/njs_array.o: \ - $(NXT_BUILDDIR)/libnxt.a \ - njs/njs.h \ - njs/njs_core.h \ - njs/njs_vm.h \ - njs/njs_number.h \ - njs/njs_string.h \ - njs/njs_object.h \ - njs/njs_object_hash.h \ - njs/njs_array.h \ - njs/njs_function.h \ - njs/njs_array.c \ - - $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_array.o $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs \ - njs/njs_array.c - -$(NXT_BUILDDIR)/njs_json.o: \ - $(NXT_BUILDDIR)/libnxt.a \ - njs/njs.h \ - njs/njs_core.h \ - njs/njs_vm.h \ - njs/njs_object.h \ - njs/njs_json.c \ - - $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_json.o $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs \ - njs/njs_json.c - - -$(NXT_BUILDDIR)/njs_function.o: \ - $(NXT_BUILDDIR)/libnxt.a \ - njs/njs.h \ - njs/njs_core.h \ - njs/njs_vm.h \ - njs/njs_object.h \ - njs/njs_array.h \ - njs/njs_function.h \ - njs/njs_function.c \ - - $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_function.o $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs \ - njs/njs_function.c - -$(NXT_BUILDDIR)/njs_regexp.o: \ - $(NXT_BUILDDIR)/libnxt.a \ - njs/njs.h \ - njs/njs_core.h \ - njs/njs_vm.h \ - njs/njs_string.h \ - njs/njs_object.h \ - njs/njs_object_hash.h \ - njs/njs_array.h \ - njs/njs_function.h \ - njs/njs_regexp.h \ - njs/njs_regexp.c \ - - $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_regexp.o $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs $(NXT_PCRE_CFLAGS) \ - njs/njs_regexp.c - -$(NXT_BUILDDIR)/njs_date.o: \ - $(NXT_BUILDDIR)/libnxt.a \ - njs/njs.h \ - njs/njs_core.h \ - njs/njs_vm.h \ - njs/njs_string.h \ - njs/njs_object.h \ - njs/njs_function.h \ - njs/njs_date.h \ - njs/njs_date.c \ - - $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_date.o $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs $(NXT_PCRE_CFLAGS) \ - njs/njs_date.c - -$(NXT_BUILDDIR)/njs_error.o: \ - $(NXT_BUILDDIR)/libnxt.a \ - njs/njs.h \ - njs/njs_core.h \ - njs/njs_vm.h \ - njs/njs_string.h \ - njs/njs_object.h \ - njs/njs_function.h \ - njs/njs_error.h \ - njs/njs_error.c \ - - $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_error.o $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs $(NXT_PCRE_CFLAGS) \ - njs/njs_error.c - -$(NXT_BUILDDIR)/njs_math.o: \ - $(NXT_BUILDDIR)/libnxt.a \ - njs/njs.h \ - njs/njs_core.h \ - njs/njs_vm.h \ - njs/njs_object.h \ - njs/njs_math.h \ - njs/njs_math.c \ - - $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_math.o $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs \ - njs/njs_math.c - -$(NXT_BUILDDIR)/njs_time.o: \ - $(NXT_BUILDDIR)/libnxt.a \ - njs/njs.h \ - njs/njs_core.h \ - njs/njs_vm.h \ - njs/njs_object.h \ - njs/njs_time.h \ - njs/njs_time.c \ - - $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_time.o $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs \ - njs/njs_time.c - -$(NXT_BUILDDIR)/njs_module.o: \ - $(NXT_BUILDDIR)/libnxt.a \ - njs/njs.h \ - njs/njs_core.h \ - njs/njs_vm.h \ - njs/njs_module.h \ - njs/njs_module.c \ - - $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_module.o $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs \ - njs/njs_module.c - -$(NXT_BUILDDIR)/njs_event.o: \ - $(NXT_BUILDDIR)/libnxt.a \ - njs/njs.h \ - njs/njs_core.h \ - njs/njs_vm.h \ - njs/njs_event.h \ - njs/njs_event.c \ - - $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_event.o $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs \ - njs/njs_event.c - -$(NXT_BUILDDIR)/njs_fs.o: \ - $(NXT_BUILDDIR)/libnxt.a \ - njs/njs.h \ - njs/njs_vm.h \ - njs/njs_fs.h \ - njs/njs_fs.c \ - - $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_fs.o $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs \ - njs/njs_fs.c - -$(NXT_BUILDDIR)/njs_crypto.o: \ - $(NXT_BUILDDIR)/libnxt.a \ - njs/njs.h \ - njs/njs_core.h \ - njs/njs_vm.h \ - njs/njs_crypto.h \ - njs/njs_crypto.c \ - - $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_crypto.o $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs \ - njs/njs_crypto.c - -$(NXT_BUILDDIR)/njs_extern.o: \ - $(NXT_BUILDDIR)/libnxt.a \ - njs/njs.h \ - njs/njs_core.h \ - njs/njs_vm.h \ - njs/njs_parser.h \ - njs/njs_extern.h \ - njs/njs_extern.c \ - - $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_extern.o $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs \ - njs/njs_extern.c - -$(NXT_BUILDDIR)/njs_variable.o: \ - $(NXT_BUILDDIR)/libnxt.a \ - njs/njs.h \ - njs/njs_core.h \ - njs/njs_vm.h \ - njs/njs_parser.h \ - njs/njs_variable.h \ - njs/njs_variable.c \ - - $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_variable.o $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs \ - njs/njs_variable.c - -$(NXT_BUILDDIR)/njs_builtin.o: \ - $(NXT_BUILDDIR)/libnxt.a \ - njs/njs.h \ - njs/njs_core.h \ - njs/njs_vm.h \ - njs/njs_boolean.h \ - njs/njs_number.h \ - njs/njs_string.h \ - njs/njs_object.h \ - njs/njs_array.h \ - njs/njs_module.h \ - njs/njs_function.h \ - njs/njs_regexp.h \ - njs/njs_parser.h \ - njs/njs_builtin.c \ - - $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_builtin.o $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs \ - njs/njs_builtin.c - -$(NXT_BUILDDIR)/njs_lexer.o: \ - $(NXT_BUILDDIR)/libnxt.a \ - njs/njs.h \ - njs/njs_core.h \ - njs/njs_vm.h \ - njs/njs_parser.h \ - njs/njs_lexer.c \ - - $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_lexer.o $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs \ - njs/njs_lexer.c - -$(NXT_BUILDDIR)/njs_lexer_keyword.o: \ - $(NXT_BUILDDIR)/libnxt.a \ - njs/njs.h \ - njs/njs_vm.h \ - njs/njs_number.h \ - njs/njs_object.h \ - njs/njs_parser.h \ - njs/njs_lexer_keyword.c \ - - $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_lexer_keyword.o $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs \ - njs/njs_lexer_keyword.c - -$(NXT_BUILDDIR)/njs_parser.o: \ - $(NXT_BUILDDIR)/libnxt.a \ - njs/njs.h \ - njs/njs_core.h \ - njs/njs_vm.h \ - njs/njs_string.h \ - njs/njs_object.h \ - njs/njs_function.h \ - njs/njs_variable.h \ - njs/njs_parser.h \ - njs/njs_parser.c \ - - $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_parser.o $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs \ - njs/njs_parser.c \ - -$(NXT_BUILDDIR)/njs_parser_expression.o: \ - $(NXT_BUILDDIR)/libnxt.a \ - njs/njs.h \ - njs/njs_core.h \ - njs/njs_vm.h \ - njs/njs_number.h \ - njs/njs_object.h \ - njs/njs_function.h \ - njs/njs_variable.h \ - njs/njs_parser.h \ - njs/njs_parser_expression.c \ - - $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_parser_expression.o \ - $(NXT_CFLAGS) -I$(NXT_LIB) -Injs \ - njs/njs_parser_expression.c - -$(NXT_BUILDDIR)/njs_generator.o: \ - $(NXT_BUILDDIR)/libnxt.a \ - njs/njs.h \ - njs/njs_core.h \ - njs/njs_vm.h \ - njs/njs_parser.h \ - njs/njs_generator.h \ - njs/njs_generator.c \ - - $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_generator.o $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs \ - njs/njs_generator.c - -$(NXT_BUILDDIR)/njs_disassembler.o: \ - $(NXT_BUILDDIR)/libnxt.a \ - njs/njs.h \ - njs/njs_core.h \ - njs/njs_vm.h \ - njs/njs_object.h \ - njs/njs_parser.h \ - njs/njs_disassembler.c \ - - $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_disassembler.o $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs \ - njs/njs_disassembler.c - -$(NXT_BUILDDIR)/njs: \ - $(NXT_BUILDDIR)/libnxt.a \ - $(NXT_BUILDDIR)/libnjs.a \ - njs/njs_shell.c \ - - $(NXT_CC) -o $(NXT_BUILDDIR)/njs $(NXT_CFLAGS) \ - -I$(NXT_LIB) $(NXT_EDITLINE_CFLAGS) -Injs \ - njs/njs_shell.c \ - $(NXT_BUILDDIR)/libnjs.a \ - -lm $(NXT_PCRE_LIB) $(NXT_LIBRT) $(NXT_EDITLINE_LIB) - -$(NXT_BUILDDIR)/njs_unit_test: \ - $(NXT_BUILDDIR)/libnxt.a \ - $(NXT_BUILDDIR)/libnjs.a \ - njs/test/njs_unit_test.c \ - - $(NXT_CC) -o $(NXT_BUILDDIR)/njs_unit_test $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs \ - njs/test/njs_unit_test.c \ - $(NXT_BUILDDIR)/libnjs.a \ - -lm $(NXT_PCRE_LIB) $(NXT_LIBRT) - -$(NXT_BUILDDIR)/njs_interactive_test: \ - $(NXT_BUILDDIR)/libnxt.a \ - $(NXT_BUILDDIR)/libnjs.a \ - njs/test/njs_interactive_test.c \ - - $(NXT_CC) -o $(NXT_BUILDDIR)/njs_interactive_test $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs \ - njs/test/njs_interactive_test.c \ - $(NXT_BUILDDIR)/libnjs.a \ - -lm $(NXT_PCRE_LIB) $(NXT_LIBRT) - -$(NXT_BUILDDIR)/njs_benchmark: \ - $(NXT_BUILDDIR)/libnxt.a \ - $(NXT_BUILDDIR)/libnjs.a \ - njs/test/njs_benchmark.c \ - - $(NXT_CC) -o $(NXT_BUILDDIR)/njs_benchmark $(NXT_CFLAGS) \ - -I$(NXT_LIB) -Injs \ - njs/test/njs_benchmark.c \ - $(NXT_BUILDDIR)/libnjs.a \ - -lm $(NXT_PCRE_LIB) $(NXT_LIBRT) - -include $(NXT_LIB)/Makefile diff -r dcc7965410bd -r a750d6fdc54a auto/clang --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/auto/clang Wed Mar 13 15:04:58 2019 +0800 @@ -0,0 +1,321 @@ + +# Copyright (C) Igor Sysoev +# Copyright (C) NGINX, Inc. + + +$echo checking for C compiler: $CC +cat << END >> $NXT_AUTOCONF_ERR +---------------------------------------- +checking for C compiler: $CC +END + + +# Allow error exit status. +set +e + +if [ -z `which $CC` ]; then + $echo + $echo $0: error: $CC not found. + $echo + exit 1; +fi + + +if `/bin/sh -c "($CC -v)" 2>&1 | grep "gcc version" >> $NXT_AUTOCONF_ERR 2>&1` +then + NXT_CC_NAME=gcc + $echo " + using GNU C compiler" + NXT_CC_VERSION=`/bin/sh -c "($CC -v)" 2>&1 | grep "gcc version" 2>&1` + $echo " + $NXT_CC_VERSION" + +else +if `/bin/sh -c "($CC -v)" 2>&1 | grep "clang version" >> $NXT_AUTOCONF_ERR 2>&1` +then + NXT_CC_NAME=clang + $echo " + using Clang C compiler" + NXT_CC_VERSION=`/bin/sh -c "($CC -v)" 2>&1 | grep "clang version" 2>&1` + $echo " + $NXT_CC_VERSION" + +else +if `/bin/sh -c "($CC -v)" 2>&1 \ + | grep "Apple LLVM version" >> $NXT_AUTOCONF_ERR 2>&1` +then + NXT_CC_NAME=clang + $echo " + using Clang C compiler" + NXT_CC_VERSION=`/bin/sh -c "($CC -v)" 2>&1 | grep "Apple LLVM version" 2>&1` + $echo " + $NXT_CC_VERSION" + +else +if `/bin/sh -c "($CC -V)" 2>&1 | grep "Sun C" >> $NXT_AUTOCONF_ERR 2>&1` +then + NXT_CC_NAME=SunC + $echo " + using Sun C compiler" + NXT_CC_VERSION=`/bin/sh -c "($CC -V)" 2>&1 | grep "Sun C" 2>&1` + $echo " + $NXT_CC_VERSION" + +fi # SunC +fi # Apple LLVM clang +fi # clang +fi # gcc + + +case $NXT_CC_NAME in + + gcc) + nxt_define=NXT_GCC . auto/define + + NXT_CFLAGS="$NXT_CFLAGS -pipe" + NXT_CFLAGS="$NXT_CFLAGS -fPIC" + + # Do not export symbols except explicitly marked with NXT_EXPORT. + NXT_CFLAGS="$NXT_CFLAGS -fvisibility=hidden" + + # c99/gnu99 conflict with Solaris XOPEN. + #NXT_CFLAGS="$NXT_CFLAGS -std=gnu99" + + NXT_CFLAGS="$NXT_CFLAGS -O" + #NXT_CFLAGS="$NXT_CFLAGS -O0" + NXT_CFLAGS="$NXT_CFLAGS -W -Wall -Wextra" + + #NXT_CFLAGS="$NXT_CFLAGS -Wunused-result" + NXT_CFLAGS="$NXT_CFLAGS -Wno-unused-parameter" + #NXT_CFLAGS="$NXT_CFLAGS -Wshorten-64-to-32" + NXT_CFLAGS="$NXT_CFLAGS -Wwrite-strings" + + # -O2 enables -fstrict-aliasing and -fstrict-overflow. + #NXT_CFLAGS="$NXT_CFLAGS -O2" + #NXT_CFLAGS="$NXT_CFLAGS -Wno-strict-aliasing" + + #NXT_CFLAGS="$NXT_CFLAGS -fomit-frame-pointer" + #NXT_CFLAGS="$NXT_CFLAGS -momit-leaf-frame-pointer" + + # -Wstrict-overflow is supported by GCC 4.2+. + #NXT_CFLAGS="$NXT_CFLAGS -Wstrict-overflow=5" + + NXT_CFLAGS="$NXT_CFLAGS -Wmissing-prototypes" + + # Stop on warning. + NXT_CFLAGS="$NXT_CFLAGS -Werror" + + # Debug. + NXT_CFLAGS="$NXT_CFLAGS -g" + ;; + + clang) + nxt_define=NXT_CLANG . auto/define + + NXT_CFLAGS="$NXT_CFLAGS -pipe" + NXT_CFLAGS="$NXT_CFLAGS -fPIC" + + # Do not export symbols except explicitly marked with NXT_EXPORT. + NXT_CFLAGS="$NXT_CFLAGS -fvisibility=hidden" + + NXT_CFLAGS="$NXT_CFLAGS -O" + #NXT_CFLAGS="$NXT_CFLAGS -O0" + NXT_CFLAGS="$NXT_CFLAGS -W -Wall -Wextra" + + #NXT_CFLAGS="$NXT_CFLAGS -Wunused-result" + NXT_CFLAGS="$NXT_CFLAGS -Wno-unused-parameter" + #NXT_CFLAGS="$NXT_CFLAGS -Wshorten-64-to-32" + NXT_CFLAGS="$NXT_CFLAGS -Wwrite-strings" + #NXT_CFLAGS="$NXT_CFLAGS -O2" + #NXT_CFLAGS="$NXT_CFLAGS -fomit-frame-pointer" + NXT_CFLAGS="$NXT_CFLAGS -fstrict-aliasing" + NXT_CFLAGS="$NXT_CFLAGS -Wstrict-overflow=5" + + NXT_CFLAGS="$NXT_CFLAGS -Wmissing-prototypes" + + # Stop on warning. + NXT_CFLAGS="$NXT_CFLAGS -Werror" + + # Debug. + + if [ "$NXT_SYSTEM_PLATFORM" != "powerpc" ]; then + # "-g" flag causes the "unknown pseudo-op: `.cfi_sections'" + # error on PowerPC Clang. + NXT_CFLAGS="$NXT_CFLAGS -g" + fi + ;; + + SunC) + nxt_define=NXT_SUNC . auto/define + + NXT_CFLAGS="$NXT_CFLAGS -fPIC" + # Optimization. + NXT_CFLAGS="$NXT_CFLAGS -O -fast" + # Stop on warning. + NXT_CFLAGS="$NXT_CFLAGS -errwarn=%all" + # Debug. + NXT_CFLAGS="$NXT_CFLAGS -g" + ;; + + *) + ;; + +esac + +# Stop on error exit status again. +set -e + +cat << END >> $NXT_MAKEFILE + +NXT_CC = ${CC} +NXT_CFLAGS = ${NXT_CFLAGS} ${CFLAGS} +END + + +# C language features. + +nxt_feature="GCC unsigned __int128" +nxt_feature_name=NXT_HAVE_UNSIGNED_INT128 +nxt_feature_run=no +nxt_feature_incs= +nxt_feature_libs= +nxt_feature_test="int main(void) { + unsigned __int128 p = 0; + return (int) p; + }" +. auto/feature + + +nxt_feature="GCC __builtin_expect()" +nxt_feature_name=NXT_HAVE_BUILTIN_EXPECT +nxt_feature_run=no +nxt_feature_incs= +nxt_feature_libs= +nxt_feature_test="int main(int argc, char *const *argv) { + if ((__typeof__(argc == 0)) + __builtin_expect((argc == 0), 0)) + return 0; + return 1; + }" +. auto/feature + + +nxt_feature="GCC __builtin_unreachable()" +nxt_feature_name=NXT_HAVE_BUILTIN_UNREACHABLE +nxt_feature_run=no +nxt_feature_incs= +nxt_feature_libs= +nxt_feature_test="int main(void) { + __builtin_unreachable(); + }" +. auto/feature + + +nxt_feature="GCC __builtin_prefetch()" +nxt_feature_name=NXT_HAVE_BUILTIN_PREFETCH +nxt_feature_run=no +nxt_feature_incs= +nxt_feature_libs= +nxt_feature_test="int main(void) { + __builtin_prefetch(0); + return 0; + }" +. auto/feature + + +nxt_feature="GCC __builtin_clz()" +nxt_feature_name=NXT_HAVE_BUILTIN_CLZ +nxt_feature_run=no +nxt_feature_incs= +nxt_feature_libs= +nxt_feature_test="int main(void) { + if (__builtin_clz(1) != 31) { + return 1; + } + return 0; + }" +. auto/feature + + +nxt_feature="GCC __builtin_clzll()" +nxt_feature_name=NXT_HAVE_BUILTIN_CLZLL +nxt_feature_run=no +nxt_feature_incs= +nxt_feature_libs= +nxt_feature_test="int main(void) { + if (__builtin_clzll(1ULL) != 63) { + return 1; + } + return 0; + }" +. auto/feature + + +nxt_feature="GCC __attribute__ visibility" +nxt_feature_name=NXT_HAVE_GCC_ATTRIBUTE_VISIBILITY +nxt_feature_run=no +nxt_feature_path= +nxt_feature_libs= +nxt_feature_test="int n __attribute__ ((visibility(\"default\"))); + + int main(void) { + return 0; + }" +. auto/feature + + +nxt_feature="GCC __attribute__ malloc" +nxt_feature_name=NXT_HAVE_GCC_ATTRIBUTE_MALLOC +nxt_feature_run=no +nxt_feature_path= +nxt_feature_libs= +nxt_feature_test="#include + + void *f(void) __attribute__ ((__malloc__)); + + void *f(void) { + return malloc(1); + } + + int main(void) { + if (f() != NULL) { + return 1; + } + return 0; + }" +. auto/feature + + +nxt_os="$NXT_SYSTEM/$NXT_SYSTEM_PLATFORM" + +if [ "$nxt_os" = "Linux/ppc64le" ]; then + + # Old GNU ld linker may hang on Linux ppc64le platform + # if some of these features are enabled. + + echo "checking for GCC __attribute__ aligned is disabled for $nxt_os." + +else + + nxt_feature="GCC __attribute__ aligned" + nxt_feature_name=NXT_HAVE_GCC_ATTRIBUTE_ALIGNED + nxt_feature_run=no + nxt_feature_path= + nxt_feature_libs= + nxt_feature_test="int n __attribute__ ((aligned(64))); + + int main(void) { + return 0; + }" + . auto/feature + +fi + + +nxt_feature="NAN to uint conversion" +nxt_feature_name=NXT_NAN_TO_UINT_CONVERSION +nxt_feature_run=value +nxt_feature_incs= +nxt_feature_libs=-lm +nxt_feature_test="#include + #include + #include + + int main(void) { + int64_t i64 = acosh(0); + printf(\"%x\", (uint32_t) i64); + return 0; + }" +. auto/feature diff -r dcc7965410bd -r a750d6fdc54a auto/define --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/auto/define Wed Mar 13 15:04:58 2019 +0800 @@ -0,0 +1,12 @@ + +# Copyright (C) Igor Sysoev +# Copyright (C) NGINX, Inc. + + +cat << END >> $NXT_AUTO_CONFIG_H + +#ifndef $nxt_define +#define $nxt_define 1 +#endif + +END diff -r dcc7965410bd -r a750d6fdc54a auto/deps --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/auto/deps Wed Mar 13 15:04:58 2019 +0800 @@ -0,0 +1,29 @@ + +# Copyright (C) Igor Sysoev +# Copyright (C) NGINX, Inc. + + +case "$NXT_CC_NAME" in + + SunC): + nxt_gen_dep_flags() { + $echo "-xMMD -xMF $NXT_BUILD_DIR/$1.tmp" + } + + nxt_gen_dep_post() { + $echo -n "@sed -e 's#^.*:#$NXT_BUILD_DIR/$2:#' " + $echo -n "$NXT_BUILD_DIR/$1.tmp > $NXT_BUILD_DIR/$1" + $echo " && rm -f $NXT_BUILD_DIR/$1.tmp" + } + ;; + + *) + nxt_gen_dep_flags() { + $echo "-MMD -MF $NXT_BUILD_DIR/$1 -MT $NXT_BUILD_DIR/$2" + } + + nxt_gen_dep_post() { + $echo "" + } + ;; +esac diff -r dcc7965410bd -r a750d6fdc54a auto/echo --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/auto/echo Wed Mar 13 15:04:58 2019 +0800 @@ -0,0 +1,12 @@ + +# Copyright (C) Igor Sysoev +# Copyright (C) NGINX, Inc. + + +if [ "x$1" = x-n ]; then + shift + echo "$*\c" + +else + echo "$*" +fi diff -r dcc7965410bd -r a750d6fdc54a auto/editline --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/auto/editline Wed Mar 13 15:04:58 2019 +0800 @@ -0,0 +1,55 @@ +# Copyright (C) Dmitry Volyntsev +# Copyright (C) NGINX, Inc. + + +NXT_EDITLINE_CFLAGS= +NXT_EDITLINE_LIB= + +nxt_found=no + +nxt_feature="editline library" +nxt_feature_name=NXT_HAVE_EDITLINE +nxt_feature_run=no +nxt_feature_incs="-I/usr/include/editline" +nxt_feature_libs="-ledit" +nxt_feature_test="#include + #include + + int main(void) { + add_history(NULL); + return 0; + }" +. auto/feature + +if [ $nxt_found = no ]; then + + # FreeBSD port From xeioex at nginx.com Sun Mar 17 14:17:24 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Sun, 17 Mar 2019 14:17:24 +0000 Subject: [njs] Fixed njs_parser_peek_token(). Message-ID: details: https://hg.nginx.org/njs/rev/82f84bd637a3 branches: changeset: 829:82f84bd637a3 user: hongzhidao date: Sun Mar 17 17:11:09 2019 +0300 description: Fixed njs_parser_peek_token(). diffstat: njs/njs_lexer.h | 10 +++++++--- njs/njs_parser.c | 16 ++++++++++------ njs/njs_parser.h | 18 +++++++++++------- njs/test/njs_unit_test.c | 15 +++++++++++++++ 4 files changed, 43 insertions(+), 16 deletions(-) diffs (132 lines): diff -r a750d6fdc54a -r 82f84bd637a3 njs/njs_lexer.h --- a/njs/njs_lexer.h Wed Mar 13 15:04:58 2019 +0800 +++ b/njs/njs_lexer.h Sun Mar 17 17:11:09 2019 +0300 @@ -247,12 +247,16 @@ typedef struct { nxt_int_t njs_lexer_init(njs_vm_t *vm, njs_lexer_t *lexer, nxt_str_t *file, u_char *start, u_char *end); njs_token_t njs_lexer_token(njs_vm_t *vm, njs_lexer_t *lexer); -njs_token_t njs_lexer_peek_token(njs_vm_t *vm, njs_lexer_t *lexer, size_t offset); +njs_token_t njs_lexer_peek_token(njs_vm_t *vm, njs_lexer_t *lexer, + size_t offset); nxt_int_t njs_lexer_keywords_init(nxt_mp_t *mp, nxt_lvlhsh_t *hash); void njs_lexer_keyword(njs_lexer_t *lexer, njs_lexer_token_t *lt); -#define njs_lexer_rollback(lexer) \ - (lexer)->start = (lexer)->prev_start +#define njs_lexer_rollback(lexer) \ + do { \ + nxt_queue_insert_head(&(lexer)->preread, &(lexer)->lexer_token->link); \ + (lexer)->lexer_token = NULL; \ + } while (0) #endif /* _NJS_LEXER_H_INCLUDED_ */ diff -r a750d6fdc54a -r 82f84bd637a3 njs/njs_parser.c --- a/njs/njs_parser.c Wed Mar 13 15:04:58 2019 +0800 +++ b/njs/njs_parser.c Sun Mar 17 17:11:09 2019 +0300 @@ -332,6 +332,8 @@ static njs_token_t njs_parser_statement(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) { + size_t offset; + parser->node = NULL; switch (token) { @@ -374,12 +376,6 @@ njs_parser_statement(njs_vm_t *vm, njs_p default: - if (token == NJS_TOKEN_NAME - && njs_parser_peek_token(vm, parser, 0) == NJS_TOKEN_COLON) - { - return njs_parser_labelled_statement(vm, parser); - } - switch (token) { case NJS_TOKEN_VAR: token = njs_parser_var_statement(vm, parser); @@ -398,6 +394,14 @@ njs_parser_statement(njs_vm_t *vm, njs_p token = njs_parser_brk_statement(vm, parser, token); break; + case NJS_TOKEN_NAME: + offset = 0; + if (njs_parser_peek_token(vm, parser, &offset) == NJS_TOKEN_COLON) { + return njs_parser_labelled_statement(vm, parser); + } + + /* Fall through. */ + default: token = njs_parser_expression(vm, parser, token); break; diff -r a750d6fdc54a -r 82f84bd637a3 njs/njs_parser.h --- a/njs/njs_parser.h Wed Mar 13 15:04:58 2019 +0800 +++ b/njs/njs_parser.h Sun Mar 17 17:11:09 2019 +0300 @@ -100,10 +100,6 @@ void njs_parser_node_error(njs_vm_t *vm, njs_value_type_t type, const char *fmt, ...); -#define njs_parser_peek_token(vm, parser, offset) \ - njs_lexer_peek_token(vm, (parser)->lexer, offset) - - #define njs_parser_is_lvalue(node) \ ((node)->token == NJS_TOKEN_NAME || (node)->token == NJS_TOKEN_PROPERTY) @@ -128,11 +124,19 @@ njs_parser_token(njs_vm_t *vm, njs_parse do { token = njs_lexer_token(vm, parser->lexer); + } while (nxt_slow_path(token == NJS_TOKEN_LINE_END)); - if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { - return token; - } + return token; +} + +nxt_inline njs_token_t +njs_parser_peek_token(njs_vm_t *vm, njs_parser_t *parser, size_t *offset) +{ + njs_token_t token; + + do { + token = njs_lexer_peek_token(vm, parser->lexer, (*offset)++); } while (nxt_slow_path(token == NJS_TOKEN_LINE_END)); return token; diff -r a750d6fdc54a -r 82f84bd637a3 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Wed Mar 13 15:04:58 2019 +0800 +++ b/njs/test/njs_unit_test.c Sun Mar 17 17:11:09 2019 +0300 @@ -2058,6 +2058,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("var a; a = 0; ++ \n a"), nxt_string("1") }, + { nxt_string("var a; a = 0\n ++a"), + nxt_string("1") }, + { nxt_string("a = 0; a \n ++"), nxt_string("SyntaxError: Unexpected end of input in 2") }, @@ -2508,6 +2511,18 @@ static njs_unit_test_t njs_test[] = { nxt_string("a: throw 'a'"), nxt_string("a") }, + { nxt_string("a\n:\n1"), + nxt_string("1") }, + + { nxt_string("a\n\n:1"), + nxt_string("1") }, + + { nxt_string("a:\n\n1"), + nxt_string("1") }, + + { nxt_string("a:\n\n"), + nxt_string("SyntaxError: Unexpected end of input in 3") }, + { nxt_string("a : var n = 0; b :++n"), nxt_string("1") }, From xeioex at nginx.com Sun Mar 17 14:36:45 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Sun, 17 Mar 2019 14:36:45 +0000 Subject: [njs] Removed unused closures field in njs_variable_t. Message-ID: details: https://hg.nginx.org/njs/rev/65109fd228e0 branches: changeset: 830:65109fd228e0 user: Dmitry Volyntsev date: Sun Mar 17 17:36:17 2019 +0300 description: Removed unused closures field in njs_variable_t. diffstat: njs/njs_variable.h | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diffs (11 lines): diff -r 82f84bd637a3 -r 65109fd228e0 njs/njs_variable.h --- a/njs/njs_variable.h Sun Mar 17 17:11:09 2019 +0300 +++ b/njs/njs_variable.h Sun Mar 17 17:36:17 2019 +0300 @@ -22,7 +22,6 @@ typedef struct { nxt_str_t name; njs_variable_type_t type:8; /* 3 bits */ - uint8_t closure; /* 1 bit */ uint8_t argument; njs_index_t index; From xeioex at nginx.com Sun Mar 17 14:36:46 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Sun, 17 Mar 2019 14:36:46 +0000 Subject: [njs] Style. Message-ID: details: https://hg.nginx.org/njs/rev/9a87bf103c47 branches: changeset: 831:9a87bf103c47 user: hongzhidao date: Sun Mar 17 21:22:30 2019 +0800 description: Style. diffstat: njs/njs_generator.c | 4 ++-- njs/njs_lexer.c | 2 +- njs/njs_parser.c | 6 +++--- njs/njs_parser_expression.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diffs (75 lines): diff -r 65109fd228e0 -r 9a87bf103c47 njs/njs_generator.c --- a/njs/njs_generator.c Sun Mar 17 17:36:17 2019 +0300 +++ b/njs/njs_generator.c Sun Mar 17 21:22:30 2019 +0800 @@ -2431,7 +2431,7 @@ njs_generate_argument_closures(njs_vm_t n--; } - } while(n != 0); + } while (n != 0); return NXT_OK; } @@ -2611,7 +2611,7 @@ njs_generate_method_call(njs_vm_t *vm, n static nxt_noinline nxt_int_t njs_generate_call(njs_vm_t *vm, njs_generator_t *generator, - njs_parser_node_t *node) + njs_parser_node_t *node) { nxt_int_t ret; nxt_uint_t nargs; diff -r 65109fd228e0 -r 9a87bf103c47 njs/njs_lexer.c --- a/njs/njs_lexer.c Sun Mar 17 17:36:17 2019 +0300 +++ b/njs/njs_lexer.c Sun Mar 17 21:22:30 2019 +0800 @@ -404,7 +404,7 @@ njs_lexer_token_name_resolve(njs_lexer_t if (lexer->property) { lexer->property_token = lt->token; - return NJS_TOKEN_NAME; + lt->token = NJS_TOKEN_NAME; } } diff -r 65109fd228e0 -r 9a87bf103c47 njs/njs_parser.c --- a/njs/njs_parser.c Sun Mar 17 17:36:17 2019 +0300 +++ b/njs/njs_parser.c Sun Mar 17 21:22:30 2019 +0800 @@ -639,7 +639,7 @@ njs_parser_function_declaration(njs_vm_t } if (token != NJS_TOKEN_NAME) { - if (token == NJS_TOKEN_ARGUMENTS || token == NJS_TOKEN_EVAL) { + if (token == NJS_TOKEN_ARGUMENTS || token == NJS_TOKEN_EVAL) { njs_parser_syntax_error(vm, parser, "Identifier \"%V\" " "is forbidden in function declaration", njs_parser_text(parser)); @@ -1023,7 +1023,7 @@ njs_parser_var_statement(njs_vm_t *vm, n } if (token != NJS_TOKEN_NAME) { - if (token == NJS_TOKEN_ARGUMENTS || token == NJS_TOKEN_EVAL) { + if (token == NJS_TOKEN_ARGUMENTS || token == NJS_TOKEN_EVAL) { njs_parser_syntax_error(vm, parser, "Identifier \"%V\" " "is forbidden in var declaration", njs_parser_text(parser)); @@ -1475,7 +1475,7 @@ njs_parser_for_var_statement(njs_vm_t *v } if (token != NJS_TOKEN_NAME) { - if (token == NJS_TOKEN_ARGUMENTS || token == NJS_TOKEN_EVAL) { + if (token == NJS_TOKEN_ARGUMENTS || token == NJS_TOKEN_EVAL) { njs_parser_syntax_error(vm, parser, "Identifier \"%V\" " "is forbidden in for-in var declaration", njs_parser_text(parser)); diff -r 65109fd228e0 -r 9a87bf103c47 njs/njs_parser_expression.c --- a/njs/njs_parser_expression.c Sun Mar 17 17:36:17 2019 +0300 +++ b/njs/njs_parser_expression.c Sun Mar 17 21:22:30 2019 +0800 @@ -354,7 +354,7 @@ njs_parser_assignment_expression(njs_vm_ if (!njs_parser_is_lvalue(parser->node)) { token = parser->node->token; - if (token == NJS_TOKEN_ARGUMENTS || token == NJS_TOKEN_EVAL) { + if (token == NJS_TOKEN_ARGUMENTS || token == NJS_TOKEN_EVAL) { njs_parser_syntax_error(vm, parser, "Identifier \"%s\" " "is forbidden as left-hand in assignment", (token == NJS_TOKEN_EVAL) ? "eval" From francesco.giacomini at cnaf.infn.it Mon Mar 18 10:53:52 2019 From: francesco.giacomini at cnaf.infn.it (Francesco Giacomini) Date: Mon, 18 Mar 2019 11:53:52 +0100 Subject: [PATCH] SSL: support for client proxy certificates Message-ID: <0b5d82532ea5c5be20af.1552906432@lapfg.cnaf.infn.it> # HG changeset patch # User Francesco Giacomini # Date 1552665342 -3600 # Fri Mar 15 16:55:42 2019 +0100 # Node ID 0b5d82532ea5c5be20af26f1d82a74b6cd451665 # Parent c74904a1702135f673a275bd0d36f010a3bfb89a SSL: support for client proxy certificates Add the option ssl_allow_proxy_certs to allow client authentication through X.509 proxy certificates (RFC 3820). It used to be possible by setting the environment variable OPENSSL_ALLOW_PROXY_CERTS, but since OpenSSL 1.1 it has to be done programmatically. diff -r c74904a17021 -r 0b5d82532ea5 contrib/vim/syntax/nginx.vim --- a/contrib/vim/syntax/nginx.vim Sat Mar 09 03:03:56 2019 +0300 +++ b/contrib/vim/syntax/nginx.vim Fri Mar 15 16:55:42 2019 +0100 @@ -581,6 +581,7 @@ syn keyword ngxDirective contained ssi_silent_errors syn keyword ngxDirective contained ssi_types syn keyword ngxDirective contained ssi_value_length +syn keyword ngxDirective contained ssl_allow_proxy_certs syn keyword ngxDirective contained ssl_buffer_size syn keyword ngxDirective contained ssl_certificate syn keyword ngxDirective contained ssl_certificate_key diff -r c74904a17021 -r 0b5d82532ea5 src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Sat Mar 09 03:03:56 2019 +0300 +++ b/src/event/ngx_event_openssl.c Fri Mar 15 16:55:42 2019 +0100 @@ -1471,6 +1471,29 @@ ngx_int_t +ngx_ssl_allow_proxy_certs(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_uint_t enable) +{ + X509_STORE *store; + + if (!enable) { + return NGX_OK; + } + + store = SSL_CTX_get_cert_store(ssl->ctx); + + if (store == NULL) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_get_cert_store() failed"); + return NGX_ERROR; + } + + X509_STORE_set_flags(store, X509_V_FLAG_ALLOW_PROXY_CERTS); + + return NGX_OK; +} + + +ngx_int_t ngx_ssl_client_session_cache(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_uint_t enable) { if (!enable) { diff -r c74904a17021 -r 0b5d82532ea5 src/event/ngx_event_openssl.h --- a/src/event/ngx_event_openssl.h Sat Mar 09 03:03:56 2019 +0300 +++ b/src/event/ngx_event_openssl.h Fri Mar 15 16:55:42 2019 +0100 @@ -180,6 +180,8 @@ ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify); ngx_int_t ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_resolver_t *resolver, ngx_msec_t resolver_timeout); +ngx_int_t ngx_ssl_allow_proxy_certs(ngx_conf_t *cf, ngx_ssl_t *ssl, + ngx_uint_t enable); 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); diff -r c74904a17021 -r 0b5d82532ea5 src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c Sat Mar 09 03:03:56 2019 +0300 +++ b/src/http/modules/ngx_http_ssl_module.c Fri Mar 15 16:55:42 2019 +0100 @@ -249,6 +249,13 @@ offsetof(ngx_http_ssl_srv_conf_t, early_data), NULL }, + { ngx_string("ssl_allow_proxy_certs"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_ssl_srv_conf_t, allow_proxy_certs), + NULL }, + ngx_null_command }; @@ -580,6 +587,7 @@ sscf->session_ticket_keys = NGX_CONF_UNSET_PTR; sscf->stapling = NGX_CONF_UNSET; sscf->stapling_verify = NGX_CONF_UNSET; + sscf->allow_proxy_certs = NGX_CONF_UNSET; return sscf; } @@ -647,6 +655,8 @@ ngx_conf_merge_str_value(conf->stapling_responder, prev->stapling_responder, ""); + ngx_conf_merge_value(conf->allow_proxy_certs, prev->allow_proxy_certs, 0); + conf->ssl.log = cf->log; if (conf->enable) { @@ -857,6 +867,10 @@ return NGX_CONF_ERROR; } + if (ngx_ssl_allow_proxy_certs(cf, &conf->ssl, conf->allow_proxy_certs) != NGX_OK) { + return NGX_CONF_ERROR; + } + return NGX_CONF_OK; } diff -r c74904a17021 -r 0b5d82532ea5 src/http/modules/ngx_http_ssl_module.h --- a/src/http/modules/ngx_http_ssl_module.h Sat Mar 09 03:03:56 2019 +0300 +++ b/src/http/modules/ngx_http_ssl_module.h Fri Mar 15 16:55:42 2019 +0100 @@ -59,6 +59,8 @@ ngx_str_t stapling_file; ngx_str_t stapling_responder; + ngx_flag_t allow_proxy_certs; + u_char *file; ngx_uint_t line; } ngx_http_ssl_srv_conf_t; From xeioex at nginx.com Mon Mar 18 13:51:43 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 18 Mar 2019 13:51:43 +0000 Subject: [njs] Fixed native frame arguments number. Message-ID: details: https://hg.nginx.org/njs/rev/8868eed51544 branches: changeset: 832:8868eed51544 user: hongzhidao date: Mon Mar 18 16:05:27 2019 +0300 description: Fixed native frame arguments number. diffstat: njs/njs_function.c | 1 + njs/test/njs_unit_test.c | 11 +++++++++++ 2 files changed, 12 insertions(+), 0 deletions(-) diffs (39 lines): diff -r 9a87bf103c47 -r 8868eed51544 njs/njs_function.c --- a/njs/njs_function.c Sun Mar 17 21:22:30 2019 +0800 +++ b/njs/njs_function.c Mon Mar 18 16:05:27 2019 +0300 @@ -310,6 +310,7 @@ njs_function_lambda_frame(njs_vm_t *vm, } else { n = function->args_offset; + native_frame->nargs += n - 1; do { *value++ = *bound++; diff -r 9a87bf103c47 -r 8868eed51544 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Sun Mar 17 21:22:30 2019 +0800 +++ b/njs/test/njs_unit_test.c Mon Mar 18 16:05:27 2019 +0300 @@ -6306,6 +6306,14 @@ static njs_unit_test_t njs_test[] = "var b = f.bind('1', '2', '3'); b.apply()"), nxt_string("123") }, + { nxt_string("var obj = {prop:'abc'}; " + "var func = function(x) { " + " return this === obj && x === 1 && arguments[0] === 1 " + " && arguments.length === 1 && this.prop === 'abc';" + "};" + "Function.prototype.bind.call(func, obj, 1)()"), + nxt_string("true") }, + { nxt_string("function F(a, b) { this.a = a + b }" "var o = new F(1, 2);" "o.a"), @@ -6457,6 +6465,9 @@ static njs_unit_test_t njs_test[] = { nxt_string("(function(){arguments.length = 1; return arguments.length;})(1,2,3)"), nxt_string("1") }, + { nxt_string("(function(){return arguments[3];}).bind(null, 0)('a','b','c')"), + nxt_string("c") }, + { nxt_string("(function(){return arguments.callee;})()"), nxt_string("TypeError: \"caller\", \"callee\" properties may not be accessed") }, From mdounin at mdounin.ru Mon Mar 18 14:22:41 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 18 Mar 2019 17:22:41 +0300 Subject: [PATCH] Apply cache locking behaviour to stale cache entries. In-Reply-To: References: <20181210190717.GV99070@mdounin.ru> <20190117132401.GJ99070@mdounin.ru> Message-ID: <20190318142241.GC1877@mdounin.ru> Hello! On Fri, Mar 15, 2019 at 10:23:15AM +0000, Thomas Peterson wrote: > It's now been several months since you last responded to this patch - is > there any particular action we can take to help move things along please? I'm still busy with other tasks, sorry about that. A review by a qualified person could help, but I doubt you'll be able to find a reviewer. -- Maxim Dounin http://mdounin.ru/ From mdounin at mdounin.ru Mon Mar 18 15:08:28 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 18 Mar 2019 18:08:28 +0300 Subject: [PATCH] SSL: support for client proxy certificates In-Reply-To: <0b5d82532ea5c5be20af.1552906432@lapfg.cnaf.infn.it> References: <0b5d82532ea5c5be20af.1552906432@lapfg.cnaf.infn.it> Message-ID: <20190318150828.GD1877@mdounin.ru> Hello! On Mon, Mar 18, 2019 at 11:53:52AM +0100, Francesco Giacomini wrote: > # HG changeset patch > # User Francesco Giacomini > # Date 1552665342 -3600 > # Fri Mar 15 16:55:42 2019 +0100 > # Node ID 0b5d82532ea5c5be20af26f1d82a74b6cd451665 > # Parent c74904a1702135f673a275bd0d36f010a3bfb89a > SSL: support for client proxy certificates > > Add the option ssl_allow_proxy_certs to allow client authentication > through X.509 proxy certificates (RFC 3820). > > It used to be possible by setting the environment variable > OPENSSL_ALLOW_PROXY_CERTS, but since OpenSSL 1.1 it has to be > done programmatically. Thanks for the patch. Docs (/doc/HOWTO/proxy_certificates.txt as of OpenSSL 1.1.1b) say: : For these reasons, OpenSSL requires that the use of proxy certificates be : explicitly allowed. Currently, this can be done using the following methods: : : - if the application directly calls X509_verify_cert(), it can first call: : : X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_ALLOW_PROXY_CERTS); : : Where ctx is the pointer which then gets passed to X509_verify_cert(). : : - proxy certificate validation can be enabled before starting the application : by setting the environment variable OPENSSL_ALLOW_PROXY_CERTS. : : In the future, it might be possible to enable proxy certificates by editing : openssl.cnf. Since nginx does not call X509_verify_cert() directly, the only documented approach is to use the OPENSSL_ALLOW_PROXY_CERTS environment variable. If this functionality is important for you, and given that the documented approach no longer works, have you considered filing a bug to the OpenSSL team? It looks like at least one already exists, though lacks proper description of the problem: https://github.com/openssl/openssl/issues/8177 I'm also a bit sceptical about the how proxy certificates are common and if these needs to be supported by nginx, given that there is still no support even in openssl.cnf. -- Maxim Dounin http://mdounin.ru/ From francesco.giacomini at cnaf.infn.it Mon Mar 18 15:39:38 2019 From: francesco.giacomini at cnaf.infn.it (Francesco Giacomini) Date: Mon, 18 Mar 2019 16:39:38 +0100 Subject: [PATCH] SSL: support for client proxy certificates In-Reply-To: <20190318150828.GD1877@mdounin.ru> References: <0b5d82532ea5c5be20af.1552906432@lapfg.cnaf.infn.it> <20190318150828.GD1877@mdounin.ru> Message-ID: <20190318153938.GH27591@imap.cnaf.infn.it> Hello. Thanks for the quick reply. On Mon, Mar 18, 2019 at 06:08:28PM +0300, Maxim Dounin wrote: > On Mon, Mar 18, 2019 at 11:53:52AM +0100, Francesco Giacomini wrote: > > > # HG changeset patch > > # User Francesco Giacomini > > # Date 1552665342 -3600 > > # Fri Mar 15 16:55:42 2019 +0100 > > # Node ID 0b5d82532ea5c5be20af26f1d82a74b6cd451665 > > # Parent c74904a1702135f673a275bd0d36f010a3bfb89a > > SSL: support for client proxy certificates > > > > Add the option ssl_allow_proxy_certs to allow client authentication > > through X.509 proxy certificates (RFC 3820). > > > > It used to be possible by setting the environment variable > > OPENSSL_ALLOW_PROXY_CERTS, but since OpenSSL 1.1 it has to be > > done programmatically. > > Thanks for the patch. Thanks for nginx. > Docs (/doc/HOWTO/proxy_certificates.txt as of OpenSSL 1.1.1b) say: > > : For these reasons, OpenSSL requires that the use of proxy certificates be > : explicitly allowed. Currently, this can be done using the following methods: > : > : - if the application directly calls X509_verify_cert(), it can first call: > : > : X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_ALLOW_PROXY_CERTS); > : > : Where ctx is the pointer which then gets passed to X509_verify_cert(). > : > : - proxy certificate validation can be enabled before starting the application > : by setting the environment variable OPENSSL_ALLOW_PROXY_CERTS. > : > : In the future, it might be possible to enable proxy certificates by editing > : openssl.cnf. > > Since nginx does not call X509_verify_cert() directly, the only > documented approach is to use the OPENSSL_ALLOW_PROXY_CERTS > environment variable. I think they simply forgot to change the documentation. > If this functionality is important for you, and given that the > documented approach no longer works, have you considered filing a > bug to the OpenSSL team? It looks like at least one already > exists, though lacks proper description of the problem: > > https://github.com/openssl/openssl/issues/8177 > > I'm also a bit sceptical about the how proxy certificates are > common and if these needs to be supported by nginx, given that > there is still no support even in openssl.cnf. As far as I know, proxy certificates were introduced as the basic mechanism for authN and authZ in Grid computing, where they are still widely used. It may well be that's the only field though. Indeed also the submitter of that issue is in that field. I didn't consider asking OpenSSL to revert their commit; I tend to agree with their comment that using an environment variable is a hack. Said that, I don't insist that this patch gets merged if you don't see it of general enough use. In fact I have an alternative solution implemented in a module I've written, which consists more or less in the following: static char* ngx_http_mymodule_merge_srv_conf(ngx_conf_t* cf, void*, void*) { ngx_http_ssl_srv_conf_t* conf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_ssl_module); if (conf->ssl.ctx != NULL) { X509_STORE *store = SSL_CTX_get_cert_store(conf->ssl.ctx); X509_STORE_set_flags(store, X509_V_FLAG_ALLOW_PROXY_CERTS); } return NGX_CONF_OK; } I would appreciate if you could tell me if it is viable; I'm not really an expert in nginx development. F. From xeioex at nginx.com Mon Mar 18 16:20:23 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 18 Mar 2019 16:20:23 +0000 Subject: [njs] Setting [[Construct]] internal property for Function Objects. Message-ID: details: https://hg.nginx.org/njs/rev/2037b3ccd677 branches: changeset: 833:2037b3ccd677 user: Dmitry Volyntsev date: Mon Mar 18 19:20:02 2019 +0300 description: Setting [[Construct]] internal property for Function Objects. According to ES5.1: 13.2 [[Construct]] is set by default. diffstat: njs/njs_function.c | 1 + njs/njs_vm.c | 16 ++++++++-------- 2 files changed, 9 insertions(+), 8 deletions(-) diffs (44 lines): diff -r 8868eed51544 -r 2037b3ccd677 njs/njs_function.c --- a/njs/njs_function.c Mon Mar 18 16:05:27 2019 +0300 +++ b/njs/njs_function.c Mon Mar 18 19:20:02 2019 +0300 @@ -32,6 +32,7 @@ njs_function_alloc(njs_vm_t *vm) function->object.shared = 1; function->object.extensible = 1; function->args_offset = 1; + function->ctor = 1; function->u.lambda = nxt_mp_zalloc(vm->mem_pool, sizeof(njs_function_lambda_t)); diff -r 8868eed51544 -r 2037b3ccd677 njs/njs_vm.c --- a/njs/njs_vm.c Mon Mar 18 16:05:27 2019 +0300 +++ b/njs/njs_vm.c Mon Mar 18 19:20:02 2019 +0300 @@ -394,6 +394,7 @@ njs_vmcode_function(njs_vm_t *vm, njs_va function->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_FUNCTION].object; function->object.extensible = 1; function->args_offset = 1; + function->ctor = 1; if (nesting != 0) { function->closure = 1; @@ -1867,14 +1868,13 @@ njs_function_frame_create(njs_vm_t *vm, function = value->data.u.function; if (ctor) { - if (function->native) { - if (!function->ctor) { - njs_type_error(vm, "%s is not a constructor", - njs_type_string(value->type)); - return NXT_ERROR; - } - - } else { + if (!function->ctor) { + njs_type_error(vm, "%s is not a constructor", + njs_type_string(value->type)); + return NXT_ERROR; + } + + if (!function->native) { object = njs_function_new_object(vm, value); if (nxt_slow_path(object == NULL)) { return NXT_ERROR; From mdounin at mdounin.ru Mon Mar 18 16:29:38 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 18 Mar 2019 19:29:38 +0300 Subject: [PATCH] SSL: support for client proxy certificates In-Reply-To: <20190318153938.GH27591@imap.cnaf.infn.it> References: <0b5d82532ea5c5be20af.1552906432@lapfg.cnaf.infn.it> <20190318150828.GD1877@mdounin.ru> <20190318153938.GH27591@imap.cnaf.infn.it> Message-ID: <20190318162938.GE1877@mdounin.ru> Hello! On Mon, Mar 18, 2019 at 04:39:38PM +0100, Francesco Giacomini wrote: > Hello. > > Thanks for the quick reply. > > On Mon, Mar 18, 2019 at 06:08:28PM +0300, Maxim Dounin wrote: > > On Mon, Mar 18, 2019 at 11:53:52AM +0100, Francesco Giacomini wrote: > > > > > # HG changeset patch > > > # User Francesco Giacomini > > > # Date 1552665342 -3600 > > > # Fri Mar 15 16:55:42 2019 +0100 > > > # Node ID 0b5d82532ea5c5be20af26f1d82a74b6cd451665 > > > # Parent c74904a1702135f673a275bd0d36f010a3bfb89a > > > SSL: support for client proxy certificates > > > > > > Add the option ssl_allow_proxy_certs to allow client authentication > > > through X.509 proxy certificates (RFC 3820). > > > > > > It used to be possible by setting the environment variable > > > OPENSSL_ALLOW_PROXY_CERTS, but since OpenSSL 1.1 it has to be > > > done programmatically. > > > > Thanks for the patch. > > Thanks for nginx. > > > Docs (/doc/HOWTO/proxy_certificates.txt as of OpenSSL 1.1.1b) say: > > > > : For these reasons, OpenSSL requires that the use of proxy certificates be > > : explicitly allowed. Currently, this can be done using the following methods: > > : > > : - if the application directly calls X509_verify_cert(), it can first call: > > : > > : X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_ALLOW_PROXY_CERTS); > > : > > : Where ctx is the pointer which then gets passed to X509_verify_cert(). > > : > > : - proxy certificate validation can be enabled before starting the application > > : by setting the environment variable OPENSSL_ALLOW_PROXY_CERTS. > > : > > : In the future, it might be possible to enable proxy certificates by editing > > : openssl.cnf. > > > > Since nginx does not call X509_verify_cert() directly, the only > > documented approach is to use the OPENSSL_ALLOW_PROXY_CERTS > > environment variable. > > I think they simply forgot to change the documentation. Well, this is likely what indeed happened. But either way there is a bug in OpenSSL: either the code or the documentation is wrong. And, given the number of recent cases with OpenSSL changes, I really want them to decide it themselves where the bug is. Note well that the documentation never mentions that the environment variable is a hack and properly written programs which simply use client certificate authentication as with SSL_CTX_set_verify(SSL_VERIFY_PEER) should use X509_STORE_CTX_set_flags(X509_V_FLAG_ALLOW_PROXY_CERTS) instead. Instead, it specifically mentions that OPENSSL_ALLOW_PROXY_CERTS should be used in this case, providing no other alternatives. This makes removing the OPENSSL_ALLOW_PROXY_CERTS environment variable support highly questionable from compatibility point of view, since no application could foresee it will be removed. > > If this functionality is important for you, and given that the > > documented approach no longer works, have you considered filing a > > bug to the OpenSSL team? It looks like at least one already > > exists, though lacks proper description of the problem: > > > > https://github.com/openssl/openssl/issues/8177 > > > > I'm also a bit sceptical about the how proxy certificates are > > common and if these needs to be supported by nginx, given that > > there is still no support even in openssl.cnf. > > As far as I know, proxy certificates were introduced as the basic > mechanism for authN and authZ in Grid computing, where they are still > widely used. It may well be that's the only field though. Indeed also > the submitter of that issue is in that field. Thanks for the details. Indeed it looks like these are only used in Grid computing. It would be interesting to hear how nginx is used in such workloads. > I didn't consider asking OpenSSL to revert their commit; I tend to > agree with their comment that using an environment variable is a hack. > > Said that, I don't insist that this patch gets merged if you don't see > it of general enough use. In fact I have an alternative solution > implemented in a module I've written, which consists more or less in > the following: > > static char* ngx_http_mymodule_merge_srv_conf(ngx_conf_t* cf, void*, void*) > { > ngx_http_ssl_srv_conf_t* conf = > ngx_http_conf_get_module_srv_conf(cf, ngx_http_ssl_module); > > if (conf->ssl.ctx != NULL) { > X509_STORE *store = SSL_CTX_get_cert_store(conf->ssl.ctx); > X509_STORE_set_flags(store, X509_V_FLAG_ALLOW_PROXY_CERTS); > } > > return NGX_CONF_OK; > } > > I would appreciate if you could tell me if it is viable; I'm not > really an expert in nginx development. This approach may have problems with further nginx changes, but likely it will work good enough. For maximum compatibility, my recommendation would be to ask OpenSSL to introduce an openssl.cnf option, so you will be able to configure things via openssl.cnf. -- Maxim Dounin http://mdounin.ru/ From francesco.giacomini at cnaf.infn.it Mon Mar 18 17:34:27 2019 From: francesco.giacomini at cnaf.infn.it (Francesco Giacomini) Date: Mon, 18 Mar 2019 18:34:27 +0100 Subject: [PATCH] SSL: support for client proxy certificates In-Reply-To: <20190318162938.GE1877@mdounin.ru> References: <0b5d82532ea5c5be20af.1552906432@lapfg.cnaf.infn.it> <20190318150828.GD1877@mdounin.ru> <20190318153938.GH27591@imap.cnaf.infn.it> <20190318162938.GE1877@mdounin.ru> Message-ID: <20190318173427.GA20734@imap.cnaf.infn.it> Hello. On Mon, Mar 18, 2019 at 07:29:38PM +0300, Maxim Dounin wrote: > > > Since nginx does not call X509_verify_cert() directly, the only > > > documented approach is to use the OPENSSL_ALLOW_PROXY_CERTS > > > environment variable. > > > > I think they simply forgot to change the documentation. > > Well, this is likely what indeed happened. But either way there > is a bug in OpenSSL: either the code or the documentation is > wrong. And, given the number of recent cases with OpenSSL > changes, I really want them to decide it themselves where the bug > is. Agreed. I'll comment in the issue you mentioned asking for clarification. I also think that when they say "if the application directly calls X509_verify_cert()", they don't mean "directly" literally; I think they rather mean "if the application has control over the SSL context used to verify the cert". > Note well that the documentation never mentions that the > environment variable is a hack and properly written programs which > simply use client certificate authentication as with > SSL_CTX_set_verify(SSL_VERIFY_PEER) should use > X509_STORE_CTX_set_flags(X509_V_FLAG_ALLOW_PROXY_CERTS) instead. > Instead, it specifically mentions that OPENSSL_ALLOW_PROXY_CERTS > should be used in this case, providing no other alternatives. > This makes removing the OPENSSL_ALLOW_PROXY_CERTS environment > variable support highly questionable from compatibility point of > view, since no application could foresee it will be removed. The definition of "hack" was in the code and in the commit that removed it https://github.com/openssl/openssl/commit/8e21938ce3a5306df753eb40a20fe30d17cf4a68 > > As far as I know, proxy certificates were introduced as the basic > > mechanism for authN and authZ in Grid computing, where they are still > > widely used. It may well be that's the only field though. Indeed also > > the submitter of that issue is in that field. > > Thanks for the details. Indeed it looks like these are only used > in Grid computing. It would be interesting to hear how nginx is > used in such workloads. Very little. The module I mentioned enables nginx to read the contents of these proxy certificates -- they contain an extension in the form of an attribute certificate with authZ information -- because we want to use it as a reverse proxy. We'll see how it goes. > This approach may have problems with further nginx changes, but > likely it will work good enough. Good, thanks. > For maximum compatibility, my recommendation would be to ask > OpenSSL to introduce an openssl.cnf option, so you will be able to > configure things via openssl.cnf. I'll check that option as well. Thanks again. F. From xeioex at nginx.com Tue Mar 19 13:20:38 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 19 Mar 2019 13:20:38 +0000 Subject: [njs] Renaming void to undefined. Message-ID: details: https://hg.nginx.org/njs/rev/e9fd5b21f08d branches: changeset: 834:e9fd5b21f08d user: Dmitry Volyntsev date: Tue Mar 19 16:02:07 2019 +0300 description: Renaming void to undefined. diffstat: njs/njs.c | 6 ++-- njs/njs.h | 7 +++-- njs/njs_array.c | 26 +++++++++--------- njs/njs_builtin.c | 4 +- njs/njs_error.c | 2 +- njs/njs_fs.c | 14 +++++----- njs/njs_function.c | 14 +++++----- njs/njs_generator.c | 6 ++-- njs/njs_json.c | 22 ++++++++-------- njs/njs_object.c | 42 ++++++++++++++++--------------- njs/njs_parser.c | 2 +- njs/njs_regexp.c | 14 +++++----- njs/njs_shell.c | 14 +++++----- njs/njs_string.c | 26 +++++++++--------- njs/njs_time.c | 4 +- njs/njs_variable.c | 3 +- njs/njs_vm.c | 63 ++++++++++++++++++++++++++--------------------- njs/njs_vm.h | 21 ++++++++------- njs/test/njs_unit_test.c | 2 +- 19 files changed, 152 insertions(+), 140 deletions(-) diffs (truncated from 1160 to 1000 lines): diff -r 2037b3ccd677 -r e9fd5b21f08d njs/njs.c --- a/njs/njs.c Mon Mar 18 19:20:02 2019 +0300 +++ b/njs/njs.c Tue Mar 19 16:02:07 2019 +0300 @@ -245,7 +245,7 @@ njs_vm_compile(njs_vm_t *vm, u_char **st nxt_array_reset(vm->backtrace); } - vm->retval = njs_value_void; + vm->retval = njs_value_undefined; ret = njs_parser(vm, parser, prev); if (nxt_slow_path(ret != NXT_OK)) { @@ -439,7 +439,7 @@ njs_vm_init(njs_vm_t *vm) } if (njs_is_null(&vm->retval)) { - vm->retval = njs_value_void; + vm->retval = njs_value_undefined; } return NXT_OK; @@ -462,7 +462,7 @@ njs_vm_invoke(njs_vm_t *vm, njs_function njs_ret_t ret; njs_value_t *this; - this = (njs_value_t *) &njs_value_void; + this = (njs_value_t *) &njs_value_undefined; current = vm->current; diff -r 2037b3ccd677 -r e9fd5b21f08d njs/njs.h --- a/njs/njs.h Mon Mar 18 19:20:02 2019 +0300 +++ b/njs/njs.h Tue Mar 19 16:02:07 2019 +0300 @@ -45,10 +45,10 @@ typedef struct { (njs_value_t *) ((u_char *) args + n * 16) -extern const njs_value_t njs_value_void; +extern const njs_value_t njs_value_undefined; #define njs_arg(args, nargs, n) \ - ((n < nargs) ? njs_argument(args, n) : &njs_value_void) + ((n < nargs) ? njs_argument(args, n) : &njs_value_undefined) #define njs_value_assign(dst, src) \ *((njs_opaque_value_t *) dst) = *((njs_opaque_value_t *) src); @@ -265,7 +265,8 @@ NXT_EXPORT void *njs_value_data(const nj NXT_EXPORT njs_function_t *njs_value_function(const njs_value_t *value); NXT_EXPORT nxt_int_t njs_value_is_null(const njs_value_t *value); -NXT_EXPORT nxt_int_t njs_value_is_void(const njs_value_t *value); +NXT_EXPORT nxt_int_t njs_value_is_undefined(const njs_value_t *value); +NXT_EXPORT nxt_int_t njs_value_is_null_or_undefined(const njs_value_t *value); NXT_EXPORT nxt_int_t njs_value_is_boolean(const njs_value_t *value); NXT_EXPORT nxt_int_t njs_value_is_number(const njs_value_t *value); NXT_EXPORT nxt_int_t njs_value_is_valid_number(const njs_value_t *value); diff -r 2037b3ccd677 -r e9fd5b21f08d njs/njs_array.c --- a/njs/njs_array.c Mon Mar 18 19:20:02 2019 +0300 +++ b/njs/njs_array.c Tue Mar 19 16:02:07 2019 +0300 @@ -509,7 +509,7 @@ njs_array_prototype_slice_continuation(n length = 0; } else { - if (!njs_is_void(njs_arg(args, nargs, 2))) { + if (!njs_is_undefined(njs_arg(args, nargs, 2))) { end = (int32_t) njs_primitive_value_to_integer(&args[2]); } else { @@ -664,7 +664,7 @@ njs_array_prototype_pop(njs_vm_t *vm, nj njs_array_t *array; const njs_value_t *retval, *value; - retval = &njs_value_void; + retval = &njs_value_undefined; if (njs_is_array(&args[0])) { array = args[0].data.u.array; @@ -730,7 +730,7 @@ njs_array_prototype_shift(njs_vm_t *vm, njs_array_t *array; const njs_value_t *retval, *value; - retval = &njs_value_void; + retval = &njs_value_undefined; if (njs_is_array(&args[0])) { array = args[0].data.u.array; @@ -963,7 +963,7 @@ njs_array_prototype_join(njs_vm_t *vm, n if (!njs_is_string(value) && njs_is_valid(value) - && !njs_is_null_or_void(value)) + && !njs_is_null_or_undefined(value)) { max++; } @@ -989,7 +989,7 @@ njs_array_prototype_join(njs_vm_t *vm, n if (!njs_is_string(value) && njs_is_valid(value) - && !njs_is_null_or_void(value)) + && !njs_is_null_or_undefined(value)) { values[n++] = *value; @@ -1037,7 +1037,7 @@ njs_array_prototype_join_continuation(nj for (i = 0; i < array->length; i++) { value = &array->start[i]; - if (njs_is_valid(value) && !njs_is_null_or_void(value)) { + if (njs_is_valid(value) && !njs_is_null_or_undefined(value)) { if (!njs_is_string(value)) { value = &values[n++]; @@ -1084,7 +1084,7 @@ njs_array_prototype_join_continuation(nj for (i = 0; i < array->length; i++) { value = &array->start[i]; - if (njs_is_valid(value) && !njs_is_null_or_void(value)) { + if (njs_is_valid(value) && !njs_is_null_or_undefined(value)) { if (!njs_is_string(value)) { value = &values[n++]; } @@ -1465,7 +1465,7 @@ njs_array_prototype_for_each_continuatio index = njs_array_iterator_index(args[0].data.u.array, iter); if (index == NJS_ARRAY_INVALID_INDEX) { - vm->retval = njs_value_void; + vm->retval = njs_value_undefined; return NXT_OK; } @@ -1660,7 +1660,7 @@ njs_array_prototype_find_continuation(nj njs_array_find_t *find; const njs_value_t *retval; - retval = &njs_value_void; + retval = &njs_value_undefined; find = njs_vm_continuation(vm); iter = &find->iter; @@ -1752,7 +1752,7 @@ njs_array_prototype_find_apply(njs_vm_t value = &args[0].data.u.array->start[n]; if (!njs_is_valid(value)) { - value = &njs_value_void; + value = &njs_value_undefined; } arguments[1] = *value; @@ -1899,7 +1899,7 @@ njs_array_prototype_reduce_continuation( return NXT_OK; } - arguments[0] = njs_value_void; + arguments[0] = njs_value_undefined; /* GC: array elt, array */ arguments[1] = iter->retval; @@ -2036,7 +2036,7 @@ njs_array_prototype_reduce_right_continu return NXT_OK; } - arguments[0] = njs_value_void; + arguments[0] = njs_value_undefined; /* GC: array elt, array */ arguments[1] = iter->retval; @@ -2177,7 +2177,7 @@ njs_array_prototype_sort_continuation(nj if (njs_is_valid(&start[n])) { if (njs_is_valid(&start[n - 1])) { - arguments[0] = njs_value_void; + arguments[0] = njs_value_undefined; /* GC: array elt, array */ arguments[1] = start[n - 1]; diff -r 2037b3ccd677 -r e9fd5b21f08d njs/njs_builtin.c --- a/njs/njs_builtin.c Mon Mar 18 19:20:02 2019 +0300 +++ b/njs/njs_builtin.c Tue Mar 19 16:02:07 2019 +0300 @@ -403,7 +403,7 @@ static njs_ret_t njs_prototype_function(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) { - vm->retval = njs_value_void; + vm->retval = njs_value_undefined; return NXT_OK; } @@ -1105,7 +1105,7 @@ static const njs_object_prop_t njs_glob { .type = NJS_PROPERTY, .name = njs_string("undefined"), - .value = njs_value(NJS_VOID, 0, NAN), + .value = njs_value(NJS_UNDEFINED, 0, NAN), }, }; diff -r 2037b3ccd677 -r e9fd5b21f08d njs/njs_error.c --- a/njs/njs_error.c Mon Mar 18 19:20:02 2019 +0300 +++ b/njs/njs_error.c Tue Mar 19 16:02:07 2019 +0300 @@ -538,7 +538,7 @@ njs_memory_error_prototype_create(njs_vm proto = njs_property_prototype_create(vm, &function->object.hash, &vm->prototypes[index].object); if (proto == NULL) { - proto = (njs_value_t *) &njs_value_void; + proto = (njs_value_t *) &njs_value_undefined; } *retval = *proto; diff -r 2037b3ccd677 -r e9fd5b21f08d njs/njs_fs.c --- a/njs/njs_fs.c Mon Mar 18 19:20:02 2019 +0300 +++ b/njs/njs_fs.c Tue Mar 19 16:02:07 2019 +0300 @@ -279,13 +279,13 @@ done: return NJS_ERROR; } - arguments[2] = njs_value_void; + arguments[2] = njs_value_undefined; } else { - arguments[1] = njs_value_void; + arguments[1] = njs_value_undefined; } - arguments[0] = njs_value_void; + arguments[0] = njs_value_undefined; cont = njs_vm_continuation(vm); cont->u.cont.function = njs_fs_done; @@ -702,10 +702,10 @@ done: } } else { - arguments[1] = njs_value_void; + arguments[1] = njs_value_undefined; } - arguments[0] = njs_value_void; + arguments[0] = njs_value_undefined; cont = njs_vm_continuation(vm); cont->u.cont.function = njs_fs_done; @@ -874,7 +874,7 @@ done: } } else { - vm->retval = njs_value_void; + vm->retval = njs_value_undefined; } return NJS_OK; @@ -884,7 +884,7 @@ done: static njs_ret_t njs_fs_done(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) { - vm->retval = njs_value_void; + vm->retval = njs_value_undefined; return NJS_OK; } diff -r 2037b3ccd677 -r e9fd5b21f08d njs/njs_function.c --- a/njs/njs_function.c Mon Mar 18 19:20:02 2019 +0300 +++ b/njs/njs_function.c Tue Mar 19 16:02:07 2019 +0300 @@ -330,7 +330,7 @@ njs_function_lambda_frame(njs_vm_t *vm, } while (max_args != 0) { - *value++ = njs_value_void; + *value++ = njs_value_undefined; max_args--; } @@ -575,7 +575,7 @@ njs_normalize_args(njs_vm_t *vm, njs_val case NJS_STRING_OBJECT_ARG: - if (njs_is_null_or_void(args)) { + if (njs_is_null_or_undefined(args)) { goto type_error; } @@ -638,7 +638,7 @@ njs_normalize_args(njs_vm_t *vm, njs_val case NJS_REGEXP_ARG: switch (args->type) { - case NJS_VOID: + case NJS_UNDEFINED: case NJS_STRING: case NJS_REGEXP: break; @@ -659,7 +659,7 @@ njs_normalize_args(njs_vm_t *vm, njs_val case NJS_OBJECT_ARG: - if (njs_is_null_or_void(args)) { + if (njs_is_null_or_undefined(args)) { goto type_error; } @@ -876,7 +876,7 @@ njs_function_prototype_call(njs_vm_t *vm nargs -= 2; } else { - this = (njs_value_t *) &njs_value_void; + this = (njs_value_t *) &njs_value_undefined; nargs = 0; } @@ -924,7 +924,7 @@ njs_function_prototype_apply(njs_vm_t *v } else { if (nargs == 1) { - this = (njs_value_t *) &njs_value_void; + this = (njs_value_t *) &njs_value_undefined; } nargs = 0; @@ -1007,7 +1007,7 @@ njs_function_prototype_bind(njs_vm_t *vm function->object.extensible = 1; if (nargs == 1) { - args = (njs_value_t *) &njs_value_void; + args = (njs_value_t *) &njs_value_undefined; } else { nargs--; diff -r 2037b3ccd677 -r e9fd5b21f08d njs/njs_generator.c --- a/njs/njs_generator.c Mon Mar 18 19:20:02 2019 +0300 +++ b/njs/njs_generator.c Tue Mar 19 16:02:07 2019 +0300 @@ -1606,7 +1606,7 @@ njs_generate_stop_statement(njs_vm_t *vm } if (index == NJS_INDEX_NONE) { - index = njs_value_index(vm, &njs_value_void, generator->runtime); + index = njs_value_index(vm, &njs_value_undefined, generator->runtime); } stop->retval = index; @@ -2377,7 +2377,7 @@ njs_generate_scope(njs_vm_t *vm, njs_gen value = (njs_value_t *) (p + size); for (n = scope_size - size; n != 0; n -= sizeof(njs_value_t)) { - *value++ = njs_value_void; + *value++ = njs_value_undefined; } if (vm->code == NULL) { @@ -2459,7 +2459,7 @@ 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_undefined, generator->runtime); } immediate = njs_generate_lookup_block(generator->block, NJS_GENERATOR_TRY, diff -r 2037b3ccd677 -r e9fd5b21f08d njs/njs_json.c --- a/njs/njs_json.c Mon Mar 18 19:20:02 2019 +0300 +++ b/njs/njs_json.c Tue Mar 19 16:02:07 2019 +0300 @@ -176,7 +176,7 @@ njs_json_parse(njs_vm_t *vm, njs_value_t } if (nargs < 2) { - arg = njs_string_void; + arg = njs_string_undefined; } else { arg = args[1]; } @@ -256,7 +256,7 @@ njs_json_stringify(njs_vm_t *vm, njs_val njs_json_stringify_t *stringify; if (nargs < 2) { - vm->retval = njs_value_void; + vm->retval = njs_value_undefined; return NXT_OK; } @@ -277,7 +277,7 @@ njs_json_stringify(njs_vm_t *vm, njs_val } } else { - stringify->replacer = njs_value_void; + stringify->replacer = njs_value_undefined; } stringify->space.length = 0; @@ -975,7 +975,7 @@ njs_json_parse_continuation(njs_vm_t *vm lhq.proto = &njs_object_hash_proto; lhq.pool = vm->mem_pool; - if (njs_is_void(&parse->retval)) { + if (njs_is_undefined(&parse->retval)) { ret = nxt_lvlhsh_delete(&state->value.data.u.object->hash, &lhq); @@ -1244,7 +1244,7 @@ njs_json_stringify_continuation(njs_vm_t prop = lhq.value; if (!prop->enumerable - || njs_is_void(&prop->value) + || njs_is_undefined(&prop->value) || !njs_is_valid(&prop->value) || njs_is_function(&prop->value)) { @@ -1282,7 +1282,7 @@ njs_json_stringify_continuation(njs_vm_t break; case NJS_JSON_OBJECT_TO_JSON_REPLACED: - if (njs_is_void(&stringify->retval)) { + if (njs_is_undefined(&stringify->retval)) { state->type = NJS_JSON_OBJECT_CONTINUE; break; } @@ -1298,7 +1298,7 @@ njs_json_stringify_continuation(njs_vm_t case NJS_JSON_OBJECT_REPLACED: state->type = NJS_JSON_OBJECT_CONTINUE; - if (njs_is_void(&stringify->retval)) { + if (njs_is_undefined(&stringify->retval)) { break; } @@ -1372,7 +1372,7 @@ njs_json_stringify_continuation(njs_vm_t break; case NJS_JSON_ARRAY_TO_JSON_REPLACED: - if (!njs_is_void(&stringify->retval) + if (!njs_is_undefined(&stringify->retval) && njs_is_function(&stringify->replacer)) { return njs_json_stringify_replacer(vm, stringify, NULL, @@ -1412,7 +1412,7 @@ done: * An empty object means empty result. */ if (str.length <= nxt_length("{\n\n}")) { - vm->retval = njs_value_void; + vm->retval = njs_value_undefined; goto release; } @@ -1735,7 +1735,7 @@ njs_json_append_value(njs_json_stringify return njs_json_buf_append(stringify, "false", 5); } - case NJS_VOID: + case NJS_UNDEFINED: case NJS_NULL: case NJS_INVALID: case NJS_FUNCTION: @@ -2150,7 +2150,7 @@ njs_dump_value(njs_json_stringify_t *str break; - case NJS_VOID: + case NJS_UNDEFINED: njs_dump("undefined"); break; diff -r 2037b3ccd677 -r e9fd5b21f08d njs/njs_object.c --- a/njs/njs_object.c Mon Mar 18 19:20:02 2019 +0300 +++ b/njs/njs_object.c Tue Mar 19 16:02:07 2019 +0300 @@ -286,7 +286,7 @@ njs_property_query(njs_vm_t *vm, njs_pro break; case NJS_STRING: - if (nxt_fast_path(!njs_is_null_or_void_or_boolean(property))) { + if (nxt_fast_path(!njs_is_null_or_undefined_or_boolean(property))) { index = njs_value_to_index(property); if (nxt_fast_path(index < NJS_STRING_MAX_LENGTH)) { @@ -298,7 +298,7 @@ njs_property_query(njs_vm_t *vm, njs_pro break; case NJS_OBJECT_STRING: - if (nxt_fast_path(!njs_is_null_or_void_or_boolean(property))) { + if (nxt_fast_path(!njs_is_null_or_undefined_or_boolean(property))) { index = njs_value_to_index(property); if (nxt_fast_path(index < NJS_STRING_MAX_LENGTH)) { @@ -316,7 +316,7 @@ njs_property_query(njs_vm_t *vm, njs_pro break; case NJS_ARRAY: - if (nxt_fast_path(!njs_is_null_or_void_or_boolean(property))) { + if (nxt_fast_path(!njs_is_null_or_undefined_or_boolean(property))) { index = njs_value_to_index(property); if (nxt_fast_path(index < NJS_ARRAY_MAX_LENGTH)) { @@ -357,7 +357,7 @@ njs_property_query(njs_vm_t *vm, njs_pro obj = NULL; break; - case NJS_VOID: + case NJS_UNDEFINED: case NJS_NULL: default: ret = njs_primitive_value_to_string(vm, &pq->value, property); @@ -434,7 +434,9 @@ njs_object_property_query(njs_vm_t *vm, goto next; } - if (proto != object && !njs_is_null_or_void_or_boolean(property)) { + if (proto != object + && !njs_is_null_or_undefined_or_boolean(property)) + { switch (proto->type) { case NJS_ARRAY: index = njs_value_to_index(property); @@ -776,7 +778,7 @@ njs_object_constructor(njs_vm_t *vm, njs value = njs_arg(args, nargs, 1); type = value->type; - if (njs_is_null_or_void(value)) { + if (njs_is_null_or_undefined(value)) { object = njs_object_alloc(vm); if (nxt_slow_path(object == NULL)) { @@ -865,7 +867,7 @@ njs_object_keys(njs_vm_t *vm, njs_value_ value = njs_arg(args, nargs, 1); - if (njs_is_null_or_void(value)) { + if (njs_is_null_or_undefined(value)) { njs_type_error(vm, "cannot convert %s argument to object", njs_type_string(value->type)); @@ -894,7 +896,7 @@ njs_object_values(njs_vm_t *vm, njs_valu value = njs_arg(args, nargs, 1); - if (njs_is_null_or_void(value)) { + if (njs_is_null_or_undefined(value)) { njs_type_error(vm, "cannot convert %s argument to object", njs_type_string(value->type)); @@ -923,7 +925,7 @@ njs_object_entries(njs_vm_t *vm, njs_val value = njs_arg(args, nargs, 1); - if (njs_is_null_or_void(value)) { + if (njs_is_null_or_undefined(value)) { njs_type_error(vm, "cannot convert %s argument to object", njs_type_string(value->type)); @@ -1366,7 +1368,7 @@ njs_descriptor_prop(njs_vm_t *vm, const njs_object_prop_t *prop, *pr; nxt_lvlhsh_query_t pq; - value = unset ? &njs_value_invalid : &njs_value_void; + value = unset ? &njs_value_invalid : &njs_value_undefined; prop = njs_object_prop_alloc(vm, name, value, 0); if (nxt_slow_path(prop == NULL)) { return NULL; @@ -1465,7 +1467,7 @@ njs_define_property(njs_vm_t *vm, njs_va if (njs_is_valid(&desc->value)) { *current->value.data.u.value = desc->value; } else { - *current->value.data.u.value = njs_value_void; + *current->value.data.u.value = njs_value_undefined; } return NXT_OK; @@ -1563,7 +1565,7 @@ njs_object_get_own_property_descriptor(n value = njs_arg(args, nargs, 1); - if (njs_is_null_or_void(value)) { + if (njs_is_null_or_undefined(value)) { njs_type_error(vm, "cannot convert %s argument to object", njs_type_string(value->type)); return NXT_ERROR; @@ -1580,7 +1582,7 @@ njs_object_get_own_property_descriptor(n break; case NXT_DECLINED: - vm->retval = njs_value_void; + vm->retval = njs_value_undefined; return NXT_OK; case NJS_TRAP: @@ -1747,7 +1749,7 @@ njs_object_freeze(njs_vm_t *vm, njs_valu value = njs_arg(args, nargs, 1); if (!njs_is_object(value)) { - vm->retval = njs_value_void; + vm->retval = njs_value_undefined; return NXT_OK; } @@ -2015,7 +2017,7 @@ njs_object_prototype_create(njs_vm_t *vm } if (proto == NULL) { - proto = &njs_value_void; + proto = &njs_value_undefined; } *retval = *proto; @@ -2032,9 +2034,9 @@ njs_property_prototype_create(njs_vm_t * njs_object_prop_t *prop; nxt_lvlhsh_query_t lhq; - static const njs_value_t prototype_string = njs_string("prototype"); - - prop = njs_object_prop_alloc(vm, &prototype_string, &njs_value_void, 0); + static const njs_value_t proto_string = njs_string("prototype"); + + prop = njs_object_prop_alloc(vm, &proto_string, &njs_value_undefined, 0); if (nxt_slow_path(prop == NULL)) { return NULL; } @@ -2428,7 +2430,7 @@ njs_object_prototype_has_own_property(nj value = njs_arg(args, nargs, 0); - if (njs_is_null_or_void(value)) { + if (njs_is_null_or_undefined(value)) { njs_type_error(vm, "cannot convert %s argument to object", njs_type_string(value->type)); return NXT_ERROR; @@ -2468,7 +2470,7 @@ njs_object_prototype_prop_is_enumerable( value = njs_arg(args, nargs, 0); - if (njs_is_null_or_void(value)) { + if (njs_is_null_or_undefined(value)) { njs_type_error(vm, "cannot convert %s argument to object", njs_type_string(value->type)); return NXT_ERROR; diff -r 2037b3ccd677 -r e9fd5b21f08d njs/njs_parser.c --- a/njs/njs_parser.c Mon Mar 18 19:20:02 2019 +0300 +++ b/njs/njs_parser.c Tue Mar 19 16:02:07 2019 +0300 @@ -2128,7 +2128,7 @@ njs_parser_reference(njs_vm_t *vm, njs_p case NJS_TOKEN_UNDEFINED: nxt_thread_log_debug("JS: undefined"); - node->u.value = njs_value_void; + node->u.value = njs_value_undefined; break; case NJS_TOKEN_THIS: diff -r 2037b3ccd677 -r e9fd5b21f08d njs/njs_regexp.c --- a/njs/njs_regexp.c Mon Mar 18 19:20:02 2019 +0300 +++ b/njs/njs_regexp.c Tue Mar 19 16:02:07 2019 +0300 @@ -589,7 +589,7 @@ njs_regexp_prototype_test(njs_vm_t *vm, value = &args[1]; } else { - value = (njs_value_t *) &njs_string_void; + value = (njs_value_t *) &njs_string_undefined; } (void) njs_string_prop(&string, value); @@ -637,7 +637,7 @@ njs_regexp_prototype_exec(njs_vm_t *vm, value = &args[1]; } else { - value = (njs_value_t *) &njs_string_void; + value = (njs_value_t *) &njs_string_undefined; } regexp = args[0].data.u.regexp; @@ -706,8 +706,8 @@ njs_regexp_exec_result(njs_vm_t *vm, njs njs_object_prop_t *prop; nxt_lvlhsh_query_t lhq; - static const njs_value_t njs_string_index = njs_string("index"); - static const njs_value_t njs_string_input = njs_string("input"); + static const njs_value_t string_index = njs_string("index"); + static const njs_value_t string_input = njs_string("input"); array = njs_array_alloc(vm, regexp->pattern->ncaptures, 0); if (nxt_slow_path(array == NULL)) { @@ -732,11 +732,11 @@ njs_regexp_exec_result(njs_vm_t *vm, njs } } else { - array->start[i] = njs_value_void; + array->start[i] = njs_value_undefined; } } - prop = njs_object_prop_alloc(vm, &njs_string_index, &njs_value_void, 1); + prop = njs_object_prop_alloc(vm, &string_index, &njs_value_undefined, 1); if (nxt_slow_path(prop == NULL)) { goto fail; } @@ -762,7 +762,7 @@ njs_regexp_exec_result(njs_vm_t *vm, njs goto fail; } - prop = njs_object_prop_alloc(vm, &njs_string_input, ®exp->string, 1); + prop = njs_object_prop_alloc(vm, &string_input, ®exp->string, 1); if (nxt_slow_path(prop == NULL)) { goto fail; } diff -r 2037b3ccd677 -r e9fd5b21f08d njs/njs_shell.c --- a/njs/njs_shell.c Mon Mar 18 19:20:02 2019 +0300 +++ b/njs/njs_shell.c Tue Mar 19 16:02:07 2019 +0300 @@ -847,7 +847,7 @@ njs_ext_console_log(njs_vm_t *vm, njs_va printf("\n"); } - vm->retval = njs_value_void; + vm->retval = njs_value_undefined; return NJS_OK; } @@ -878,7 +878,7 @@ njs_ext_console_dump(njs_vm_t *vm, njs_v printf("\n"); } - vm->retval = njs_value_void; + vm->retval = njs_value_undefined; return NJS_OK; } @@ -909,7 +909,7 @@ njs_ext_console_help(njs_vm_t *vm, njs_v printf("\n"); - vm->retval = njs_value_void; + vm->retval = njs_value_undefined; return NJS_OK; } @@ -921,7 +921,7 @@ njs_ext_console_time(njs_vm_t *vm, njs_v { njs_console_t *console; - if (!njs_value_is_void(njs_arg(args, nargs, 1))) { + if (!njs_value_is_undefined(njs_arg(args, nargs, 1))) { njs_vm_error(vm, "labels not implemented"); return NJS_ERROR; } @@ -933,7 +933,7 @@ njs_ext_console_time(njs_vm_t *vm, njs_v console->time = nxt_time(); - vm->retval = njs_value_void; + vm->retval = njs_value_undefined; return NJS_OK; } @@ -948,7 +948,7 @@ njs_ext_console_time_end(njs_vm_t *vm, n ns = nxt_time(); - if (!njs_value_is_void(njs_arg(args, nargs, 1))) { + if (!njs_value_is_undefined(njs_arg(args, nargs, 1))) { njs_vm_error(vm, "labels not implemented"); return NJS_ERROR; } @@ -973,7 +973,7 @@ njs_ext_console_time_end(njs_vm_t *vm, n printf("Timer \"default\" doesn?t exist.\n"); } - vm->retval = njs_value_void; + vm->retval = njs_value_undefined; return NJS_OK; } diff -r 2037b3ccd677 -r e9fd5b21f08d njs/njs_string.c --- a/njs/njs_string.c Mon Mar 18 19:20:02 2019 +0300 +++ b/njs/njs_string.c Tue Mar 19 16:02:07 2019 +0300 @@ -829,7 +829,7 @@ njs_string_prototype_concat(njs_vm_t *vm nxt_uint_t i; njs_string_prop_t string; - if (njs_is_null_or_void(&args[0])) { + if (njs_is_null_or_undefined(&args[0])) { njs_type_error(vm, "\"this\" argument is null or undefined"); return NXT_ERROR; } @@ -1249,7 +1249,7 @@ njs_string_slice_args(njs_slice_prop_t * length = 0; } else { - if (!njs_is_void(njs_arg(args, nargs, 2))) { + if (!njs_is_undefined(njs_arg(args, nargs, 2))) { value = njs_arg(args, nargs, 2); end = value->data.u.number; @@ -2540,7 +2540,7 @@ njs_string_prototype_search(njs_vm_t *vm goto done; - case NJS_VOID: + case NJS_UNDEFINED: default: goto done; } @@ -2860,7 +2860,7 @@ found: goto done; - case NJS_VOID: + case NJS_UNDEFINED: default: break; } @@ -2958,7 +2958,7 @@ njs_string_prototype_replace(njs_vm_t *v /* A literal replacement is stored in the second part. */ if (nargs == 2) { - njs_string_replacement_copy(&r->part[1], &njs_string_void); + njs_string_replacement_copy(&r->part[1], &njs_string_undefined); } else if (njs_is_string(&args[2])) { njs_string_replacement_copy(&r->part[1], &args[2]); @@ -3122,7 +3122,7 @@ njs_string_replace_regexp_function(njs_v return NXT_ERROR; } - arguments[0] = njs_value_void; + arguments[0] = njs_value_undefined; /* Matched substring and parenthesized submatch strings. */ for (k = 0, i = 1; i <= n; i++) { @@ -3261,7 +3261,7 @@ njs_string_replace_search_function(njs_v r->u.cont.function = njs_string_replace_search_continuation; - arguments[0] = njs_value_void; + arguments[0] = njs_value_undefined; /* GC, args[0], args[1] */ @@ -3560,8 +3560,8 @@ njs_primitive_value_to_string(njs_vm_t * value = &njs_string_null; break; - case NJS_VOID: - value = &njs_string_void; + case NJS_UNDEFINED: + value = &njs_string_undefined; break; case NJS_BOOLEAN: @@ -4003,7 +4003,7 @@ njs_string_encode_uri(njs_vm_t *vm, njs_ return njs_string_encode(vm, &args[1], escape); } - vm->retval = njs_string_void; + vm->retval = njs_string_undefined; return NXT_OK; } @@ -4039,7 +4039,7 @@ njs_string_encode_uri_component(njs_vm_t return njs_string_encode(vm, &args[1], escape); } - vm->retval = njs_string_void; + vm->retval = njs_string_undefined; return NXT_OK; } @@ -4134,7 +4134,7 @@ njs_string_decode_uri(njs_vm_t *vm, njs_ return njs_string_decode(vm, &args[1], reserve); } - vm->retval = njs_string_void; + vm->retval = njs_string_undefined; return NXT_OK; } @@ -4170,7 +4170,7 @@ njs_string_decode_uri_component(njs_vm_t return njs_string_decode(vm, &args[1], reserve); } - vm->retval = njs_string_void; + vm->retval = njs_string_undefined; return NXT_OK; } diff -r 2037b3ccd677 -r e9fd5b21f08d njs/njs_time.c --- a/njs/njs_time.c Mon Mar 18 19:20:02 2019 +0300 +++ b/njs/njs_time.c Tue Mar 19 16:02:07 2019 +0300 @@ -106,7 +106,7 @@ njs_clear_timeout(njs_vm_t *vm, njs_valu nxt_lvlhsh_query_t lhq; if (nxt_fast_path(nargs < 2) || !njs_is_number(&args[1])) { - vm->retval = njs_value_void; + vm->retval = njs_value_undefined; return NJS_OK; } @@ -125,7 +125,7 @@ njs_clear_timeout(njs_vm_t *vm, njs_valu njs_del_event(vm, event, NJS_EVENT_RELEASE | NJS_EVENT_DELETE); } - vm->retval = njs_value_void; + vm->retval = njs_value_undefined; return NJS_OK; } diff -r 2037b3ccd677 -r e9fd5b21f08d njs/njs_variable.c --- a/njs/njs_variable.c Mon Mar 18 19:20:02 2019 +0300 +++ b/njs/njs_variable.c Tue Mar 19 16:02:07 2019 +0300 @@ -397,7 +397,8 @@ njs_variable_resolve(njs_vm_t *vm, njs_p goto not_found; } - default_value = njs_is_object(&var->value) ? &var->value : &njs_value_void; + default_value = njs_is_object(&var->value) ? &var->value : + &njs_value_undefined; index = njs_scope_next_index(vm, vr->scope, scope_index, default_value); diff -r 2037b3ccd677 -r e9fd5b21f08d njs/njs_vm.c --- a/njs/njs_vm.c Mon Mar 18 19:20:02 2019 +0300 +++ b/njs/njs_vm.c Tue Mar 19 16:02:07 2019 +0300 @@ -66,7 +66,7 @@ void njs_debug(njs_index_t index, njs_va const njs_value_t njs_value_null = njs_value(NJS_NULL, 0, 0.0); -const njs_value_t njs_value_void = njs_value(NJS_VOID, 0, NAN); +const njs_value_t njs_value_undefined = njs_value(NJS_UNDEFINED, 0, NAN); const njs_value_t njs_value_false = njs_value(NJS_BOOLEAN, 0, 0.0); const njs_value_t njs_value_true = njs_value(NJS_BOOLEAN, 1, 1.0); const njs_value_t njs_value_zero = njs_value(NJS_NUMBER, 0, 0.0); @@ -77,7 +77,7 @@ const njs_value_t njs_value_invalid = const njs_value_t njs_string_empty = njs_string(""); const njs_value_t njs_string_comma = njs_string(","); const njs_value_t njs_string_null = njs_string("null"); -const njs_value_t njs_string_void = njs_string("undefined"); +const njs_value_t njs_string_undefined = njs_string("undefined"); const njs_value_t njs_string_boolean = njs_string("boolean"); const njs_value_t njs_string_false = njs_string("false"); const njs_value_t njs_string_true = njs_string("true"); @@ -591,7 +591,7 @@ njs_vmcode_property_set(njs_vm_t *vm, nj } } - prop = njs_object_prop_alloc(vm, &pq.value, &njs_value_void, 1); + prop = njs_object_prop_alloc(vm, &pq.value, &njs_value_undefined, 1); if (nxt_slow_path(prop == NULL)) { return NXT_ERROR; } @@ -897,7 +897,7 @@ njs_vmcode_instance_of(njs_vm_t *vm, njs retval = &njs_value_false; if (njs_is_object(object)) { - value = njs_value_void; + value = njs_value_undefined; ret = njs_value_property(vm, constructor, &prototype_string, &value); if (nxt_fast_path(ret == NXT_OK)) { @@ -1026,21 +1026,21 @@ njs_vmcode_typeof(njs_vm_t *vm, njs_valu static const njs_value_t *types[NJS_TYPE_MAX] = { &njs_string_object, - &njs_string_void, + &njs_string_undefined, &njs_string_boolean, &njs_string_number, &njs_string_string, - &njs_string_void, - &njs_string_void, - &njs_string_void, - &njs_string_void, - &njs_string_void, - &njs_string_void, - &njs_string_void, - &njs_string_void, - &njs_string_void, - &njs_string_void, - &njs_string_void, + &njs_string_undefined, + &njs_string_undefined, + &njs_string_undefined, + &njs_string_undefined, + &njs_string_undefined, + &njs_string_undefined, + &njs_string_undefined, + &njs_string_undefined, + &njs_string_undefined, + &njs_string_undefined, + &njs_string_undefined, &njs_string_object, &njs_string_object, @@ -1062,7 +1062,7 @@ njs_vmcode_typeof(njs_vm_t *vm, njs_valu }; /* A zero index means non-declared variable. */ - type = (value != NULL) ? value->type : NJS_VOID; + type = (value != NULL) ? value->type : NJS_UNDEFINED; vm->retval = *types[type]; @@ -1073,7 +1073,7 @@ njs_vmcode_typeof(njs_vm_t *vm, njs_valu njs_ret_t njs_vmcode_void(njs_vm_t *vm, njs_value_t *invld1, njs_value_t *invld2) { - vm->retval = njs_value_void; + vm->retval = njs_value_undefined; return sizeof(njs_vmcode_2addr_t); } From xeioex at nginx.com Wed Mar 20 12:59:34 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 20 Mar 2019 12:59:34 +0000 Subject: [njs] HTTP: handling absence of value while iterating over r.args. Message-ID: details: https://hg.nginx.org/njs/rev/64dc0795c2f0 branches: changeset: 836:64dc0795c2f0 user: Dmitry Volyntsev date: Wed Mar 20 15:56:22 2019 +0300 description: HTTP: handling absence of value while iterating over r.args. diffstat: nginx/ngx_http_js_module.c | 20 +++++++++++--------- 1 files changed, 11 insertions(+), 9 deletions(-) diffs (40 lines): diff -r 04032d0970b4 -r 64dc0795c2f0 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Tue Mar 19 18:26:44 2019 +0300 +++ b/nginx/ngx_http_js_module.c Wed Mar 20 15:56:22 2019 +0300 @@ -1564,7 +1564,7 @@ ngx_http_js_ext_next_arg(njs_vm_t *vm, n ngx_str_t **e = next; size_t len; - u_char *p, *start, *end; + u_char *v, *p, *start, *end; ngx_str_t *entry; entry = *e; @@ -1576,17 +1576,19 @@ ngx_http_js_ext_next_arg(njs_vm_t *vm, n start = entry->data; end = start + entry->len; - p = ngx_strlchr(start, end, '='); + p = ngx_strlchr(start, end, '&'); if (p == NULL) { - return NJS_ERROR; + p = end; } - len = p - start; - p++; - - p = ngx_strlchr(p, end, '&'); - - if (p) { + v = ngx_strlchr(start, p, '='); + if (v == NULL) { + v = p; + } + + len = v - start; + + if (p != end) { entry->data = &p[1]; entry->len = end - entry->data; From arut at nginx.com Thu Mar 21 11:09:54 2019 From: arut at nginx.com (Roman Arutyunyan) Date: Thu, 21 Mar 2019 11:09:54 +0000 Subject: [nginx] Multiple addresses in "listen". Message-ID: details: https://hg.nginx.org/nginx/rev/4f9b72a229c1 branches: changeset: 7478:4f9b72a229c1 user: Roman Arutyunyan date: Fri Mar 15 15:45:56 2019 +0300 description: Multiple addresses in "listen". Previously only one address was used by the listen directive handler even if host name resolved to multiple addresses. Now a separate listening socket is created for each address. diffstat: src/core/ngx_inet.c | 354 +++++++++++++---------------------- src/core/ngx_inet.h | 1 + src/http/ngx_http.c | 34 +- src/http/ngx_http_core_module.c | 81 ++++--- src/http/ngx_http_core_module.h | 5 +- src/mail/ngx_mail.c | 42 +--- src/mail/ngx_mail.h | 3 +- src/mail/ngx_mail_core_module.c | 83 +++---- src/stream/ngx_stream.c | 42 +--- src/stream/ngx_stream.h | 3 +- src/stream/ngx_stream_core_module.c | 75 +++---- 11 files changed, 286 insertions(+), 437 deletions(-) diffs (truncated from 1286 to 1000 lines): diff -r c74904a17021 -r 4f9b72a229c1 src/core/ngx_inet.c --- a/src/core/ngx_inet.c Sat Mar 09 03:03:56 2019 +0300 +++ b/src/core/ngx_inet.c Fri Mar 15 15:45:56 2019 +0300 @@ -12,6 +12,8 @@ static ngx_int_t ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u); static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u); static ngx_int_t ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u); +static ngx_int_t ngx_inet_add_addr(ngx_pool_t *pool, ngx_url_t *u, + struct sockaddr *sockaddr, socklen_t socklen, ngx_uint_t total); in_addr_t @@ -780,13 +782,10 @@ ngx_parse_unix_domain_url(ngx_pool_t *po static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u) { - u_char *p, *host, *port, *last, *uri, *args; - size_t len; - ngx_int_t n; - struct sockaddr_in *sin; -#if (NGX_HAVE_INET6) - struct sockaddr_in6 *sin6; -#endif + u_char *host, *port, *last, *uri, *args; + size_t len; + ngx_int_t n; + struct sockaddr_in *sin; u->socklen = sizeof(struct sockaddr_in); sin = (struct sockaddr_in *) &u->sockaddr; @@ -864,13 +863,15 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx u->port = (in_port_t) n; sin->sin_port = htons((in_port_t) n); + sin->sin_addr.s_addr = INADDR_ANY; u->port_text.len = last - host; u->port_text.data = host; u->wildcard = 1; - return NGX_OK; + return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr, + u->socklen, 1); } } } @@ -893,7 +894,7 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx if (u->listen && len == 1 && *host == '*') { sin->sin_addr.s_addr = INADDR_ANY; u->wildcard = 1; - return NGX_OK; + return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr, u->socklen, 1); } sin->sin_addr.s_addr = ngx_inet_addr(host, len); @@ -904,33 +905,7 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx u->wildcard = 1; } - u->naddrs = 1; - - u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t)); - if (u->addrs == NULL) { - return NGX_ERROR; - } - - sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in)); - if (sin == NULL) { - return NGX_ERROR; - } - - ngx_memcpy(sin, &u->sockaddr, sizeof(struct sockaddr_in)); - - u->addrs[0].sockaddr = (struct sockaddr *) sin; - u->addrs[0].socklen = sizeof(struct sockaddr_in); - - p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1); - if (p == NULL) { - return NGX_ERROR; - } - - u->addrs[0].name.len = ngx_sprintf(p, "%V:%d", - &u->host, u->port) - p; - u->addrs[0].name.data = p; - - return NGX_OK; + return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr, u->socklen, 1); } if (u->no_resolve) { @@ -944,29 +919,7 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx u->family = u->addrs[0].sockaddr->sa_family; u->socklen = u->addrs[0].socklen; ngx_memcpy(&u->sockaddr, u->addrs[0].sockaddr, u->addrs[0].socklen); - - switch (u->family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - sin6 = (struct sockaddr_in6 *) &u->sockaddr; - - if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { - u->wildcard = 1; - } - - break; -#endif - - default: /* AF_INET */ - sin = (struct sockaddr_in *) &u->sockaddr; - - if (sin->sin_addr.s_addr == INADDR_ANY) { - u->wildcard = 1; - } - - break; - } + u->wildcard = ngx_inet_wildcard(&u->sockaddr.sockaddr); return NGX_OK; } @@ -1061,33 +1014,8 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ng } u->family = AF_INET6; - u->naddrs = 1; - u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t)); - if (u->addrs == NULL) { - return NGX_ERROR; - } - - sin6 = ngx_pcalloc(pool, sizeof(struct sockaddr_in6)); - if (sin6 == NULL) { - return NGX_ERROR; - } - - ngx_memcpy(sin6, &u->sockaddr, sizeof(struct sockaddr_in6)); - - u->addrs[0].sockaddr = (struct sockaddr *) sin6; - u->addrs[0].socklen = sizeof(struct sockaddr_in6); - - p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1); - if (p == NULL) { - return NGX_ERROR; - } - - u->addrs[0].name.len = ngx_sprintf(p, "%V:%d", - &u->host, u->port) - p; - u->addrs[0].name.data = p; - - return NGX_OK; + return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr, u->socklen, 1); #else @@ -1104,15 +1032,9 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ng ngx_int_t ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u) { - u_char *p, *host; - size_t len; - in_port_t port; - ngx_uint_t i; - struct addrinfo hints, *res, *rp; - struct sockaddr_in *sin; - struct sockaddr_in6 *sin6; - - port = htons(u->port); + u_char *host; + ngx_uint_t n; + struct addrinfo hints, *res, *rp; host = ngx_alloc(u->host.len + 1, pool->log); if (host == NULL) { @@ -1136,7 +1058,7 @@ ngx_inet_resolve_host(ngx_pool_t *pool, ngx_free(host); - for (i = 0, rp = res; rp != NULL; rp = rp->ai_next) { + for (n = 0, rp = res; rp != NULL; rp = rp->ai_next) { switch (rp->ai_family) { @@ -1148,25 +1070,16 @@ ngx_inet_resolve_host(ngx_pool_t *pool, continue; } - i++; + n++; } - if (i == 0) { + if (n == 0) { u->err = "host not found"; goto failed; } /* MP: ngx_shared_palloc() */ - u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t)); - if (u->addrs == NULL) { - goto failed; - } - - u->naddrs = i; - - i = 0; - /* AF_INET addresses first */ for (rp = res; rp != NULL; rp = rp->ai_next) { @@ -1175,31 +1088,11 @@ ngx_inet_resolve_host(ngx_pool_t *pool, continue; } - sin = ngx_pcalloc(pool, rp->ai_addrlen); - if (sin == NULL) { + if (ngx_inet_add_addr(pool, u, rp->ai_addr, rp->ai_addrlen, n) + != NGX_OK) + { goto failed; } - - ngx_memcpy(sin, rp->ai_addr, rp->ai_addrlen); - - sin->sin_port = port; - - u->addrs[i].sockaddr = (struct sockaddr *) sin; - u->addrs[i].socklen = rp->ai_addrlen; - - len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1; - - p = ngx_pnalloc(pool, len); - if (p == NULL) { - goto failed; - } - - len = ngx_sock_ntop((struct sockaddr *) sin, rp->ai_addrlen, p, len, 1); - - u->addrs[i].name.len = len; - u->addrs[i].name.data = p; - - i++; } for (rp = res; rp != NULL; rp = rp->ai_next) { @@ -1208,32 +1101,11 @@ ngx_inet_resolve_host(ngx_pool_t *pool, continue; } - sin6 = ngx_pcalloc(pool, rp->ai_addrlen); - if (sin6 == NULL) { + if (ngx_inet_add_addr(pool, u, rp->ai_addr, rp->ai_addrlen, n) + != NGX_OK) + { goto failed; } - - ngx_memcpy(sin6, rp->ai_addr, rp->ai_addrlen); - - sin6->sin6_port = port; - - u->addrs[i].sockaddr = (struct sockaddr *) sin6; - u->addrs[i].socklen = rp->ai_addrlen; - - len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1; - - p = ngx_pnalloc(pool, len); - if (p == NULL) { - goto failed; - } - - len = ngx_sock_ntop((struct sockaddr *) sin6, rp->ai_addrlen, p, - len, 1); - - u->addrs[i].name.len = len; - u->addrs[i].name.data = p; - - i++; } freeaddrinfo(res); @@ -1250,21 +1122,19 @@ failed: ngx_int_t ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u) { - u_char *p, *host; - size_t len; - in_port_t port; - in_addr_t in_addr; - ngx_uint_t i; + u_char *host; + ngx_uint_t i, n; struct hostent *h; - struct sockaddr_in *sin; + struct sockaddr_in sin; /* AF_INET only */ - port = htons(u->port); + ngx_memzero(&sin, sizeof(struct sockaddr_in)); - in_addr = ngx_inet_addr(u->host.data, u->host.len); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = ngx_inet_addr(u->host.data, u->host.len); - if (in_addr == INADDR_NONE) { + if (sin.sin_addr.s_addr == INADDR_NONE) { host = ngx_alloc(u->host.len + 1, pool->log); if (host == NULL) { return NGX_ERROR; @@ -1281,76 +1151,31 @@ ngx_inet_resolve_host(ngx_pool_t *pool, return NGX_ERROR; } - for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ } + for (n = 0; h->h_addr_list[n] != NULL; n++) { /* void */ } /* MP: ngx_shared_palloc() */ - u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t)); - if (u->addrs == NULL) { - return NGX_ERROR; - } + for (i = 0; i < n; i++) { + sin.sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]); - u->naddrs = i; - - for (i = 0; i < u->naddrs; i++) { - - sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in)); - if (sin == NULL) { + if (ngx_inet_add_addr(pool, u, (struct sockaddr *) &sin, + sizeof(struct sockaddr_in), n) + != NGX_OK) + { return NGX_ERROR; } - - sin->sin_family = AF_INET; - sin->sin_port = port; - sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]); - - u->addrs[i].sockaddr = (struct sockaddr *) sin; - u->addrs[i].socklen = sizeof(struct sockaddr_in); - - len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1; - - p = ngx_pnalloc(pool, len); - if (p == NULL) { - return NGX_ERROR; - } - - len = ngx_sock_ntop((struct sockaddr *) sin, - sizeof(struct sockaddr_in), p, len, 1); - - u->addrs[i].name.len = len; - u->addrs[i].name.data = p; } } else { /* MP: ngx_shared_palloc() */ - u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t)); - if (u->addrs == NULL) { - return NGX_ERROR; - } - - sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in)); - if (sin == NULL) { + if (ngx_inet_add_addr(pool, u, (struct sockaddr *) &sin, + sizeof(struct sockaddr_in), 1) + != NGX_OK) + { return NGX_ERROR; } - - u->naddrs = 1; - - sin->sin_family = AF_INET; - sin->sin_port = port; - sin->sin_addr.s_addr = in_addr; - - u->addrs[0].sockaddr = (struct sockaddr *) sin; - u->addrs[0].socklen = sizeof(struct sockaddr_in); - - p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1); - if (p == NULL) { - return NGX_ERROR; - } - - u->addrs[0].name.len = ngx_sprintf(p, "%V:%d", - &u->host, ntohs(port)) - p; - u->addrs[0].name.data = p; } return NGX_OK; @@ -1359,6 +1184,62 @@ ngx_inet_resolve_host(ngx_pool_t *pool, #endif /* NGX_HAVE_GETADDRINFO && NGX_HAVE_INET6 */ +static ngx_int_t +ngx_inet_add_addr(ngx_pool_t *pool, ngx_url_t *u, struct sockaddr *sockaddr, + socklen_t socklen, ngx_uint_t total) +{ + u_char *p; + size_t len; + ngx_addr_t *addr; + struct sockaddr *sa; + + if (u->addrs == NULL) { + u->addrs = ngx_palloc(pool, total * sizeof(ngx_addr_t)); + if (u->addrs == NULL) { + return NGX_ERROR; + } + } + + sa = ngx_pcalloc(pool, socklen); + if (sa == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(sa, sockaddr, socklen); + + ngx_inet_set_port(sa, u->port); + + switch (sa->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65536") - 1; + break; +#endif + + default: /* AF_INET */ + len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1; + } + + p = ngx_pnalloc(pool, len); + if (p == NULL) { + return NGX_ERROR; + } + + len = ngx_sock_ntop(sa, socklen, p, len, 1); + + addr = &u->addrs[u->naddrs++]; + + addr->sockaddr = sa; + addr->socklen = socklen; + + addr->name.len = len; + addr->name.data = p; + + return NGX_OK; +} + + ngx_int_t ngx_cmp_sockaddr(struct sockaddr *sa1, socklen_t slen1, struct sockaddr *sa2, socklen_t slen2, ngx_uint_t cmp_port) @@ -1495,3 +1376,40 @@ ngx_inet_set_port(struct sockaddr *sa, i break; } } + + +ngx_uint_t +ngx_inet_wildcard(struct sockaddr *sa) +{ + struct sockaddr_in *sin; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; +#endif + + switch (sa->sa_family) { + + case AF_INET: + sin = (struct sockaddr_in *) sa; + + if (sin->sin_addr.s_addr == INADDR_ANY) { + return 1; + } + + break; + +#if (NGX_HAVE_INET6) + + case AF_INET6: + sin6 = (struct sockaddr_in6 *) sa; + + if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { + return 1; + } + + break; + +#endif + } + + return 0; +} diff -r c74904a17021 -r 4f9b72a229c1 src/core/ngx_inet.h --- a/src/core/ngx_inet.h Sat Mar 09 03:03:56 2019 +0300 +++ b/src/core/ngx_inet.h Fri Mar 15 15:45:56 2019 +0300 @@ -125,6 +125,7 @@ ngx_int_t ngx_cmp_sockaddr(struct sockad struct sockaddr *sa2, socklen_t slen2, ngx_uint_t cmp_port); in_port_t ngx_inet_get_port(struct sockaddr *sa); void ngx_inet_set_port(struct sockaddr *sa, in_port_t port); +ngx_uint_t ngx_inet_wildcard(struct sockaddr *sa); #endif /* _NGX_INET_H_INCLUDED_ */ diff -r c74904a17021 -r 4f9b72a229c1 src/http/ngx_http.c --- a/src/http/ngx_http.c Sat Mar 09 03:03:56 2019 +0300 +++ b/src/http/ngx_http.c Fri Mar 15 15:45:56 2019 +0300 @@ -1157,7 +1157,7 @@ ngx_http_add_listen(ngx_conf_t *cf, ngx_ } } - sa = &lsopt->sockaddr.sockaddr; + sa = lsopt->sockaddr; p = ngx_inet_get_port(sa); port = cmcf->ports->elts; @@ -1209,8 +1209,8 @@ ngx_http_add_addresses(ngx_conf_t *cf, n for (i = 0; i < port->addrs.nelts; i++) { - if (ngx_cmp_sockaddr(&lsopt->sockaddr.sockaddr, lsopt->socklen, - &addr[i].opt.sockaddr.sockaddr, + if (ngx_cmp_sockaddr(lsopt->sockaddr, lsopt->socklen, + addr[i].opt.sockaddr, addr[i].opt.socklen, 0) != NGX_OK) { @@ -1239,7 +1239,8 @@ ngx_http_add_addresses(ngx_conf_t *cf, n if (addr[i].opt.set) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "duplicate listen options for %s", addr[i].opt.addr); + "duplicate listen options for %V", + &addr[i].opt.addr_text); return NGX_ERROR; } @@ -1252,7 +1253,8 @@ ngx_http_add_addresses(ngx_conf_t *cf, n if (default_server) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "a duplicate default server for %s", addr[i].opt.addr); + "a duplicate default server for %V", + &addr[i].opt.addr_text); return NGX_ERROR; } @@ -1305,8 +1307,8 @@ ngx_http_add_address(ngx_conf_t *cf, ngx if (lsopt->http2 && lsopt->ssl) { ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "nginx was built with OpenSSL that lacks ALPN " - "and NPN support, HTTP/2 is not enabled for %s", - lsopt->addr); + "and NPN support, HTTP/2 is not enabled for %V", + &lsopt->addr_text); } #endif @@ -1354,7 +1356,8 @@ ngx_http_add_server(ngx_conf_t *cf, ngx_ for (i = 0; i < addr->servers.nelts; i++) { if (server[i] == cscf) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "a duplicate listen %s", addr->opt.addr); + "a duplicate listen %V", + &addr->opt.addr_text); return NGX_ERROR; } } @@ -1471,15 +1474,15 @@ ngx_http_server_names(ngx_conf_t *cf, ng if (rc == NGX_DECLINED) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "invalid server name or wildcard \"%V\" on %s", - &name[n].name, addr->opt.addr); + "invalid server name or wildcard \"%V\" on %V", + &name[n].name, &addr->opt.addr_text); return NGX_ERROR; } if (rc == NGX_BUSY) { ngx_log_error(NGX_LOG_WARN, cf->log, 0, - "conflicting server name \"%V\" on %s, ignored", - &name[n].name, addr->opt.addr); + "conflicting server name \"%V\" on %V, ignored", + &name[n].name, &addr->opt.addr_text); } } } @@ -1700,8 +1703,7 @@ ngx_http_add_listening(ngx_conf_t *cf, n ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; - ls = ngx_create_listening(cf, &addr->opt.sockaddr.sockaddr, - addr->opt.socklen); + ls = ngx_create_listening(cf, addr->opt.sockaddr, addr->opt.socklen); if (ls == NULL) { return NULL; } @@ -1791,7 +1793,7 @@ ngx_http_add_addrs(ngx_conf_t *cf, ngx_h for (i = 0; i < hport->naddrs; i++) { - sin = &addr[i].opt.sockaddr.sockaddr_in; + sin = (struct sockaddr_in *) addr[i].opt.sockaddr; addrs[i].addr = sin->sin_addr.s_addr; addrs[i].conf.default_server = addr[i].default_server; #if (NGX_HTTP_SSL) @@ -1856,7 +1858,7 @@ ngx_http_add_addrs6(ngx_conf_t *cf, ngx_ for (i = 0; i < hport->naddrs; i++) { - sin6 = &addr[i].opt.sockaddr.sockaddr_in6; + sin6 = (struct sockaddr_in6 *) addr[i].opt.sockaddr; addrs6[i].addr6 = sin6->sin6_addr; addrs6[i].conf.default_server = addr[i].default_server; #if (NGX_HTTP_SSL) diff -r c74904a17021 -r 4f9b72a229c1 src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c Sat Mar 09 03:03:56 2019 +0300 +++ b/src/http/ngx_http_core_module.c Fri Mar 15 15:45:56 2019 +0300 @@ -2715,6 +2715,8 @@ ngx_http_core_server(ngx_conf_t *cf, ngx { char *rv; void *mconf; + size_t len; + u_char *p; ngx_uint_t i; ngx_conf_t pcf; ngx_http_module_t *module; @@ -2802,7 +2804,14 @@ ngx_http_core_server(ngx_conf_t *cf, ngx if (rv == NGX_CONF_OK && !cscf->listen) { ngx_memzero(&lsopt, sizeof(ngx_http_listen_opt_t)); - sin = &lsopt.sockaddr.sockaddr_in; + p = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in)); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + lsopt.sockaddr = (struct sockaddr *) p; + + sin = (struct sockaddr_in *) p; sin->sin_family = AF_INET; #if (NGX_WIN32) @@ -2825,8 +2834,16 @@ ngx_http_core_server(ngx_conf_t *cf, ngx #endif lsopt.wildcard = 1; - (void) ngx_sock_ntop(&lsopt.sockaddr.sockaddr, lsopt.socklen, - lsopt.addr, NGX_SOCKADDR_STRLEN, 1); + len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1; + + p = ngx_pnalloc(cf->pool, len); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + lsopt.addr_text.data = p; + lsopt.addr_text.len = ngx_sock_ntop(lsopt.sockaddr, lsopt.socklen, p, + len, 1); if (ngx_http_add_listen(cf, cscf, &lsopt) != NGX_OK) { return NGX_CONF_ERROR; @@ -3779,9 +3796,6 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx ngx_memzero(&lsopt, sizeof(ngx_http_listen_opt_t)); - ngx_memcpy(&lsopt.sockaddr.sockaddr, &u.sockaddr, u.socklen); - - lsopt.socklen = u.socklen; lsopt.backlog = NGX_LISTEN_BACKLOG; lsopt.rcvbuf = -1; lsopt.sndbuf = -1; @@ -3791,14 +3805,10 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx #if (NGX_HAVE_TCP_FASTOPEN) lsopt.fastopen = -1; #endif - lsopt.wildcard = u.wildcard; #if (NGX_HAVE_INET6) lsopt.ipv6only = 1; #endif - (void) ngx_sock_ntop(&lsopt.sockaddr.sockaddr, lsopt.socklen, lsopt.addr, - NGX_SOCKADDR_STRLEN, 1); - for (n = 2; n < cf->args->nelts; n++) { if (ngx_strcmp(value[n].data, "default_server") == 0 @@ -3923,34 +3933,22 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx if (ngx_strncmp(value[n].data, "ipv6only=o", 10) == 0) { #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) - struct sockaddr *sa; - - sa = &lsopt.sockaddr.sockaddr; - - if (sa->sa_family == AF_INET6) { - - if (ngx_strcmp(&value[n].data[10], "n") == 0) { - lsopt.ipv6only = 1; - - } else if (ngx_strcmp(&value[n].data[10], "ff") == 0) { - lsopt.ipv6only = 0; - - } else { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid ipv6only flags \"%s\"", - &value[n].data[9]); - return NGX_CONF_ERROR; - } - - lsopt.set = 1; - lsopt.bind = 1; + if (ngx_strcmp(&value[n].data[10], "n") == 0) { + lsopt.ipv6only = 1; + + } else if (ngx_strcmp(&value[n].data[10], "ff") == 0) { + lsopt.ipv6only = 0; } else { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "ipv6only is not supported " - "on addr \"%s\", ignored", lsopt.addr); + "invalid ipv6only flags \"%s\"", + &value[n].data[9]); + return NGX_CONF_ERROR; } + lsopt.set = 1; + lsopt.bind = 1; + continue; #else ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, @@ -4106,11 +4104,18 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx return NGX_CONF_ERROR; } - if (ngx_http_add_listen(cf, cscf, &lsopt) == NGX_OK) { - return NGX_CONF_OK; - } - - return NGX_CONF_ERROR; + for (n = 0; n < u.naddrs; n++) { + lsopt.sockaddr = u.addrs[n].sockaddr; + lsopt.socklen = u.addrs[n].socklen; + lsopt.addr_text = u.addrs[n].name; + lsopt.wildcard = ngx_inet_wildcard(lsopt.sockaddr); + + if (ngx_http_add_listen(cf, cscf, &lsopt) != NGX_OK) { + return NGX_CONF_ERROR; + } + } + + return NGX_CONF_OK; } diff -r c74904a17021 -r 4f9b72a229c1 src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h Sat Mar 09 03:03:56 2019 +0300 +++ b/src/http/ngx_http_core_module.h Fri Mar 15 15:45:56 2019 +0300 @@ -65,8 +65,9 @@ typedef struct ngx_http_core_loc_conf_s typedef struct { - ngx_sockaddr_t sockaddr; + struct sockaddr *sockaddr; socklen_t socklen; + ngx_str_t addr_text; unsigned set:1; unsigned default_server:1; @@ -100,8 +101,6 @@ typedef struct { #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) char *accept_filter; #endif - - u_char addr[NGX_SOCKADDR_STRLEN + 1]; } ngx_http_listen_opt_t; diff -r c74904a17021 -r 4f9b72a229c1 src/mail/ngx_mail.c --- a/src/mail/ngx_mail.c Sat Mar 09 03:03:56 2019 +0300 +++ b/src/mail/ngx_mail.c Fri Mar 15 15:45:56 2019 +0300 @@ -231,7 +231,7 @@ ngx_mail_add_ports(ngx_conf_t *cf, ngx_a ngx_mail_conf_port_t *port; ngx_mail_conf_addr_t *addr; - sa = &listen->sockaddr.sockaddr; + sa = listen->sockaddr; p = ngx_inet_get_port(sa); port = ports->elts; @@ -316,7 +316,7 @@ ngx_mail_optimize_servers(ngx_conf_t *cf continue; } - ls = ngx_create_listening(cf, &addr[i].opt.sockaddr.sockaddr, + ls = ngx_create_listening(cf, addr[i].opt.sockaddr, addr[i].opt.socklen); if (ls == NULL) { return NGX_CONF_ERROR; @@ -384,12 +384,9 @@ static ngx_int_t ngx_mail_add_addrs(ngx_conf_t *cf, ngx_mail_port_t *mport, ngx_mail_conf_addr_t *addr) { - u_char *p; - size_t len; ngx_uint_t i; ngx_mail_in_addr_t *addrs; struct sockaddr_in *sin; - u_char buf[NGX_SOCKADDR_STRLEN]; mport->addrs = ngx_pcalloc(cf->pool, mport->naddrs * sizeof(ngx_mail_in_addr_t)); @@ -401,26 +398,14 @@ ngx_mail_add_addrs(ngx_conf_t *cf, ngx_m for (i = 0; i < mport->naddrs; i++) { - sin = &addr[i].opt.sockaddr.sockaddr_in; + sin = (struct sockaddr_in *) addr[i].opt.sockaddr; addrs[i].addr = sin->sin_addr.s_addr; addrs[i].conf.ctx = addr[i].opt.ctx; #if (NGX_MAIL_SSL) addrs[i].conf.ssl = addr[i].opt.ssl; #endif - - len = ngx_sock_ntop(&addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen, - buf, NGX_SOCKADDR_STRLEN, 1); - - p = ngx_pnalloc(cf->pool, len); - if (p == NULL) { - return NGX_ERROR; - } - - ngx_memcpy(p, buf, len); - - addrs[i].conf.addr_text.len = len; - addrs[i].conf.addr_text.data = p; + addrs[i].conf.addr_text = addr[i].opt.addr_text; } return NGX_OK; @@ -433,12 +418,9 @@ static ngx_int_t ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_mail_port_t *mport, ngx_mail_conf_addr_t *addr) { - u_char *p; - size_t len; ngx_uint_t i; ngx_mail_in6_addr_t *addrs6; struct sockaddr_in6 *sin6; - u_char buf[NGX_SOCKADDR_STRLEN]; mport->addrs = ngx_pcalloc(cf->pool, mport->naddrs * sizeof(ngx_mail_in6_addr_t)); @@ -450,26 +432,14 @@ ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_ for (i = 0; i < mport->naddrs; i++) { - sin6 = &addr[i].opt.sockaddr.sockaddr_in6; + sin6 = (struct sockaddr_in6 *) addr[i].opt.sockaddr; addrs6[i].addr6 = sin6->sin6_addr; addrs6[i].conf.ctx = addr[i].opt.ctx; #if (NGX_MAIL_SSL) addrs6[i].conf.ssl = addr[i].opt.ssl; #endif - - len = ngx_sock_ntop(&addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen, - buf, NGX_SOCKADDR_STRLEN, 1); - - p = ngx_pnalloc(cf->pool, len); - if (p == NULL) { - return NGX_ERROR; - } - - ngx_memcpy(p, buf, len); - - addrs6[i].conf.addr_text.len = len; - addrs6[i].conf.addr_text.data = p; + addrs6[i].conf.addr_text = addr[i].opt.addr_text; } return NGX_OK; diff -r c74904a17021 -r 4f9b72a229c1 src/mail/ngx_mail.h --- a/src/mail/ngx_mail.h Sat Mar 09 03:03:56 2019 +0300 +++ b/src/mail/ngx_mail.h Fri Mar 15 15:45:56 2019 +0300 @@ -27,8 +27,9 @@ typedef struct { typedef struct { - ngx_sockaddr_t sockaddr; + struct sockaddr *sockaddr; socklen_t socklen; + ngx_str_t addr_text; /* server ctx */ ngx_mail_conf_ctx_t *ctx; diff -r c74904a17021 -r 4f9b72a229c1 src/mail/ngx_mail_core_module.c --- a/src/mail/ngx_mail_core_module.c Sat Mar 09 03:03:56 2019 +0300 +++ b/src/mail/ngx_mail_core_module.c Fri Mar 15 15:45:56 2019 +0300 @@ -297,8 +297,8 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx ngx_str_t *value, size; ngx_url_t u; - ngx_uint_t i, m; - ngx_mail_listen_t *ls; + ngx_uint_t i, n, m; + ngx_mail_listen_t *ls, *als; ngx_mail_module_t *module; ngx_mail_core_main_conf_t *cmcf; @@ -323,36 +323,16 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx cmcf = ngx_mail_conf_get_module_main_conf(cf, ngx_mail_core_module); - ls = cmcf->listen.elts; - - for (i = 0; i < cmcf->listen.nelts; i++) { - - if (ngx_cmp_sockaddr(&ls[i].sockaddr.sockaddr, ls[i].socklen, - (struct sockaddr *) &u.sockaddr, u.socklen, 1) - != NGX_OK) - { - continue; - } - - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "duplicate \"%V\" address and port pair", &u.url); - return NGX_CONF_ERROR; - } - - ls = ngx_array_push(&cmcf->listen); + ls = ngx_array_push_n(&cmcf->listen, u.naddrs); if (ls == NULL) { return NGX_CONF_ERROR; } ngx_memzero(ls, sizeof(ngx_mail_listen_t)); - ngx_memcpy(&ls->sockaddr.sockaddr, &u.sockaddr, u.socklen); - - ls->socklen = u.socklen; ls->backlog = NGX_LISTEN_BACKLOG; ls->rcvbuf = -1; ls->sndbuf = -1; - ls->wildcard = u.wildcard; ls->ctx = cf->ctx; #if (NGX_HAVE_INET6) @@ -434,35 +414,20 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) - size_t len; - u_char buf[NGX_SOCKADDR_STRLEN]; - - if (ls->sockaddr.sockaddr.sa_family == AF_INET6) { - - if (ngx_strcmp(&value[i].data[10], "n") == 0) { - ls->ipv6only = 1; + if (ngx_strcmp(&value[i].data[10], "n") == 0) { + ls->ipv6only = 1; - } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) { - ls->ipv6only = 0; - - } else { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid ipv6only flags \"%s\"", - &value[i].data[9]); - return NGX_CONF_ERROR; - } - - ls->bind = 1; + } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) { + ls->ipv6only = 0; } else { - len = ngx_sock_ntop(&ls->sockaddr.sockaddr, ls->socklen, buf, - NGX_SOCKADDR_STRLEN, 1); - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "ipv6only is not supported " - "on addr \"%*s\", ignored", len, buf); + "invalid ipv6only flags \"%s\"", From arut at nginx.com Thu Mar 21 11:09:56 2019 From: arut at nginx.com (Roman Arutyunyan) Date: Thu, 21 Mar 2019 11:09:56 +0000 Subject: [nginx] Removed sorting of getaddrinfo() results. Message-ID: details: https://hg.nginx.org/nginx/rev/8be88b22fe81 branches: changeset: 7479:8be88b22fe81 user: Roman Arutyunyan date: Wed Mar 20 20:31:59 2019 +0300 description: Removed sorting of getaddrinfo() results. Previously the ngx_inet_resolve_host() function sorted addresses in a way that IPv4 addresses came before IPv6 addresses. This was implemented in eaf95350d75c (1.3.10) along with the introduction of getaddrinfo() which could resolve host names to IPv6 addresses. Since the "listen" directive only used the first address, sorting allowed to preserve "listen" compatibility with the previous behavior and with the behavior of nginx built without IPv6 support. Now "listen" uses all resolved addresses which makes sorting pointless. diffstat: src/core/ngx_inet.c | 19 +++++-------------- 1 files changed, 5 insertions(+), 14 deletions(-) diffs (33 lines): diff -r 4f9b72a229c1 -r 8be88b22fe81 src/core/ngx_inet.c --- a/src/core/ngx_inet.c Fri Mar 15 15:45:56 2019 +0300 +++ b/src/core/ngx_inet.c Wed Mar 20 20:31:59 2019 +0300 @@ -1080,24 +1080,15 @@ ngx_inet_resolve_host(ngx_pool_t *pool, /* MP: ngx_shared_palloc() */ - /* AF_INET addresses first */ - for (rp = res; rp != NULL; rp = rp->ai_next) { - if (rp->ai_family != AF_INET) { - continue; - } + switch (rp->ai_family) { - if (ngx_inet_add_addr(pool, u, rp->ai_addr, rp->ai_addrlen, n) - != NGX_OK) - { - goto failed; - } - } + case AF_INET: + case AF_INET6: + break; - for (rp = res; rp != NULL; rp = rp->ai_next) { - - if (rp->ai_family != AF_INET6) { + default: continue; } From arut at nginx.com Thu Mar 21 11:09:58 2019 From: arut at nginx.com (Roman Arutyunyan) Date: Thu, 21 Mar 2019 11:09:58 +0000 Subject: [nginx] Listen port ranges. Message-ID: details: https://hg.nginx.org/nginx/rev/d9c3917c7f90 branches: changeset: 7480:d9c3917c7f90 user: Roman Arutyunyan date: Wed Mar 06 20:46:09 2019 +0300 description: Listen port ranges. A range is specified with a dash. For each port in a range a separate listen socket is created. Examples: listen 8080-9000; listen example.com:80-88; diffstat: src/core/ngx_inet.c | 147 +++++++++++++++++++++++++++++++++++++++++---------- src/core/ngx_inet.h | 1 + 2 files changed, 119 insertions(+), 29 deletions(-) diffs (262 lines): diff -r 8be88b22fe81 -r d9c3917c7f90 src/core/ngx_inet.c --- a/src/core/ngx_inet.c Wed Mar 20 20:31:59 2019 +0300 +++ b/src/core/ngx_inet.c Wed Mar 06 20:46:09 2019 +0300 @@ -782,7 +782,7 @@ ngx_parse_unix_domain_url(ngx_pool_t *po static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u) { - u_char *host, *port, *last, *uri, *args; + u_char *host, *port, *last, *uri, *args, *dash; size_t len; ngx_int_t n; struct sockaddr_in *sin; @@ -830,6 +830,25 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx len = last - port; + if (u->listen) { + dash = ngx_strlchr(port, last, '-'); + + if (dash) { + dash++; + + n = ngx_atoi(dash, last - dash); + + if (n < 1 || n > 65535) { + u->err = "invalid port"; + return NGX_ERROR; + } + + u->last_port = (in_port_t) n; + + len = dash - port - 1; + } + } + n = ngx_atoi(port, len); if (n < 1 || n > 65535) { @@ -837,10 +856,15 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx return NGX_ERROR; } + if (u->last_port && n > u->last_port) { + u->err = "invalid port range"; + return NGX_ERROR; + } + u->port = (in_port_t) n; sin->sin_port = htons((in_port_t) n); - u->port_text.len = len; + u->port_text.len = last - port; u->port_text.data = port; last = port - 1; @@ -852,15 +876,47 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx /* test value as port only */ - n = ngx_atoi(host, last - host); + len = last - host; + + dash = ngx_strlchr(host, last, '-'); + + if (dash) { + dash++; + + n = ngx_atoi(dash, last - dash); + + if (n == NGX_ERROR) { + goto no_port; + } + + if (n < 1 || n > 65535) { + u->err = "invalid port"; + + } else { + u->last_port = (in_port_t) n; + } + + len = dash - host - 1; + } + + n = ngx_atoi(host, len); if (n != NGX_ERROR) { + if (u->err) { + return NGX_ERROR; + } + if (n < 1 || n > 65535) { u->err = "invalid port"; return NGX_ERROR; } + if (u->last_port && n > u->last_port) { + u->err = "invalid port range"; + return NGX_ERROR; + } + u->port = (in_port_t) n; sin->sin_port = htons((in_port_t) n); sin->sin_addr.s_addr = INADDR_ANY; @@ -876,9 +932,13 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx } } +no_port: + + u->err = NULL; u->no_port = 1; u->port = u->default_port; sin->sin_port = htons(u->default_port); + u->last_port = 0; } len = last - host; @@ -929,7 +989,7 @@ static ngx_int_t ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u) { #if (NGX_HAVE_INET6) - u_char *p, *host, *port, *last, *uri; + u_char *p, *host, *port, *last, *uri, *dash; size_t len; ngx_int_t n; struct sockaddr_in6 *sin6; @@ -975,6 +1035,25 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ng len = last - port; + if (u->listen) { + dash = ngx_strlchr(port, last, '-'); + + if (dash) { + dash++; + + n = ngx_atoi(dash, last - dash); + + if (n < 1 || n > 65535) { + u->err = "invalid port"; + return NGX_ERROR; + } + + u->last_port = (in_port_t) n; + + len = dash - port - 1; + } + } + n = ngx_atoi(port, len); if (n < 1 || n > 65535) { @@ -982,10 +1061,15 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ng return NGX_ERROR; } + if (u->last_port && n > u->last_port) { + u->err = "invalid port range"; + return NGX_ERROR; + } + u->port = (in_port_t) n; sin6->sin6_port = htons((in_port_t) n); - u->port_text.len = len; + u->port_text.len = last - port; u->port_text.data = port; } else { @@ -1181,51 +1265,56 @@ ngx_inet_add_addr(ngx_pool_t *pool, ngx_ { u_char *p; size_t len; + ngx_uint_t i, nports; ngx_addr_t *addr; struct sockaddr *sa; + nports = u->last_port ? u->last_port - u->port + 1 : 1; + if (u->addrs == NULL) { - u->addrs = ngx_palloc(pool, total * sizeof(ngx_addr_t)); + u->addrs = ngx_palloc(pool, total * nports * sizeof(ngx_addr_t)); if (u->addrs == NULL) { return NGX_ERROR; } } - sa = ngx_pcalloc(pool, socklen); - if (sa == NULL) { - return NGX_ERROR; - } + for (i = 0; i < nports; i++) { + sa = ngx_pcalloc(pool, socklen); + if (sa == NULL) { + return NGX_ERROR; + } - ngx_memcpy(sa, sockaddr, socklen); + ngx_memcpy(sa, sockaddr, socklen); - ngx_inet_set_port(sa, u->port); + ngx_inet_set_port(sa, u->port + i); - switch (sa->sa_family) { + switch (sa->sa_family) { #if (NGX_HAVE_INET6) - case AF_INET6: - len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65536") - 1; - break; + case AF_INET6: + len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65536") - 1; + break; #endif - default: /* AF_INET */ - len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1; - } + default: /* AF_INET */ + len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1; + } - p = ngx_pnalloc(pool, len); - if (p == NULL) { - return NGX_ERROR; - } + p = ngx_pnalloc(pool, len); + if (p == NULL) { + return NGX_ERROR; + } - len = ngx_sock_ntop(sa, socklen, p, len, 1); + len = ngx_sock_ntop(sa, socklen, p, len, 1); - addr = &u->addrs[u->naddrs++]; + addr = &u->addrs[u->naddrs++]; - addr->sockaddr = sa; - addr->socklen = socklen; + addr->sockaddr = sa; + addr->socklen = socklen; - addr->name.len = len; - addr->name.data = p; + addr->name.len = len; + addr->name.data = p; + } return NGX_OK; } diff -r 8be88b22fe81 -r d9c3917c7f90 src/core/ngx_inet.h --- a/src/core/ngx_inet.h Wed Mar 20 20:31:59 2019 +0300 +++ b/src/core/ngx_inet.h Wed Mar 06 20:46:09 2019 +0300 @@ -86,6 +86,7 @@ typedef struct { in_port_t port; in_port_t default_port; + in_port_t last_port; int family; unsigned listen:1; From xeioex at nginx.com Fri Mar 22 17:49:42 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 22 Mar 2019 17:49:42 +0000 Subject: [njs] Added initial modules support. Message-ID: details: https://hg.nginx.org/njs/rev/53dc000e8c14 branches: changeset: 837:53dc000e8c14 user: hongzhidao date: Sat Mar 02 20:31:10 2019 +0800 description: Added initial modules support. The following syntax is supported: 1) default import statements: import lib1 from '../relative/path/lib.js'; import lib2 from '/abs/path/lib.js'; import fs from 'fs'; // built-in modules 2) default export statements: export default {fun1, fun2, ...}; // export module object Modules look up procedure: 1) absolute paths (start with '/') are used as is. 2) otherwise the following paths are tried: dir + '/' + path where dir is a) the directory of the current file. b) additions paths provided with njs_vm_add_path(). This closes #91 on Github. diffstat: njs/njs.c | 31 ++ njs/njs.h | 2 + njs/njs_builtin.c | 2 + njs/njs_core.h | 4 +- njs/njs_generator.c | 98 ++++++- njs/njs_lexer.h | 4 + njs/njs_lexer_keyword.c | 7 +- njs/njs_module.c | 455 ++++++++++++++++++++++++++++++++++ njs/njs_module.h | 4 + njs/njs_parser.c | 308 ++++++++++++++++++++++- njs/njs_parser.h | 7 + njs/njs_shell.c | 102 ++++++- njs/njs_variable.c | 2 +- njs/njs_vm.c | 1 + njs/njs_vm.h | 5 + njs/test/module/exception.js | 4 + njs/test/module/export.js | 4 + njs/test/module/export_non_default.js | 3 + njs/test/module/lib1.js | 19 + njs/test/module/lib2.js | 7 + njs/test/module/lib3.js | 11 + njs/test/module/libs/hash.js | 9 + njs/test/module/loading_exception.js | 3 + njs/test/module/normal.js | 35 ++ njs/test/module/recursive.js | 3 + njs/test/module/return.js | 1 + njs/test/module/sub/sub1.js | 12 + njs/test/module/sub/sub2.js | 7 + njs/test/njs_expect_test.exp | 52 +++- njs/test/njs_unit_test.c | 29 ++ 30 files changed, 1191 insertions(+), 40 deletions(-) diffs (truncated from 1695 to 1000 lines): diff -r 64dc0795c2f0 -r 53dc000e8c14 njs/njs.c --- a/njs/njs.c Wed Mar 20 15:56:22 2019 +0300 +++ b/njs/njs.c Sat Mar 02 20:31:10 2019 +0800 @@ -332,6 +332,8 @@ njs_vm_clone(njs_vm_t *vm, njs_external_ nvm->variables_hash = vm->variables_hash; nvm->values_hash = vm->values_hash; + + nvm->modules = vm->modules; nvm->modules_hash = vm->modules_hash; nvm->externals_hash = vm->externals_hash; @@ -580,6 +582,11 @@ njs_vm_start(njs_vm_t *vm) { njs_ret_t ret; + ret = njs_module_load(vm); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } + ret = njs_vmcode_interpreter(vm); if (ret == NJS_STOP) { @@ -628,6 +635,30 @@ njs_vm_handle_events(njs_vm_t *vm) } +nxt_int_t +njs_vm_add_path(njs_vm_t *vm, const nxt_str_t *path) +{ + nxt_str_t *item; + + if (vm->paths == NULL) { + vm->paths = nxt_array_create(4, sizeof(nxt_str_t), + &njs_array_mem_proto, vm->mem_pool); + if (nxt_slow_path(vm->paths == NULL)) { + return NXT_ERROR; + } + } + + item = nxt_array_add(vm->paths, &njs_array_mem_proto, vm->mem_pool); + if (nxt_slow_path(item == NULL)) { + return NXT_ERROR; + } + + *item = *path; + + return NXT_OK; +} + + nxt_noinline njs_value_t * njs_vm_retval(njs_vm_t *vm) { diff -r 64dc0795c2f0 -r 53dc000e8c14 njs/njs.h --- a/njs/njs.h Wed Mar 20 15:56:22 2019 +0300 +++ b/njs/njs.h Sat Mar 02 20:31:10 2019 +0800 @@ -215,6 +215,8 @@ NXT_EXPORT nxt_int_t njs_vm_run(njs_vm_t */ NXT_EXPORT nxt_int_t njs_vm_start(njs_vm_t *vm); +NXT_EXPORT nxt_int_t njs_vm_add_path(njs_vm_t *vm, const nxt_str_t *path); + NXT_EXPORT const njs_extern_t *njs_vm_external_prototype(njs_vm_t *vm, njs_external_t *external); NXT_EXPORT nxt_int_t njs_vm_external_create(njs_vm_t *vm, diff -r 64dc0795c2f0 -r 53dc000e8c14 njs/njs_builtin.c --- a/njs/njs_builtin.c Wed Mar 20 15:56:22 2019 +0300 +++ b/njs/njs_builtin.c Sat Mar 02 20:31:10 2019 +0800 @@ -294,6 +294,8 @@ njs_builtin_objects_create(njs_vm_t *vm) return NJS_ERROR; } + module->function.native = 1; + ret = njs_object_hash_create(vm, &module->object.shared_hash, obj->properties, obj->items); if (nxt_slow_path(ret != NXT_OK)) { diff -r 64dc0795c2f0 -r 53dc000e8c14 njs/njs_core.h --- a/njs/njs_core.h Wed Mar 20 15:56:22 2019 +0300 +++ b/njs/njs_core.h Sat Mar 02 20:31:10 2019 +0800 @@ -7,6 +7,7 @@ #ifndef _NJS_CORE_H_INCLUDED_ #define _NJS_CORE_H_INCLUDED_ + #include #include @@ -46,7 +47,8 @@ #include #include +#include +#include -#include #endif /* _NJS_CORE_H_INCLUDED_ */ diff -r 64dc0795c2f0 -r 53dc000e8c14 njs/njs_generator.c --- a/njs/njs_generator.c Wed Mar 20 15:56:22 2019 +0300 +++ b/njs/njs_generator.c Sat Mar 02 20:31:10 2019 +0800 @@ -154,6 +154,10 @@ static nxt_int_t njs_generate_try_statem njs_generator_t *generator, njs_parser_node_t *node); static nxt_int_t njs_generate_throw_statement(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node); +static nxt_int_t njs_generate_import_statement(njs_vm_t *vm, + njs_generator_t *generator, njs_parser_node_t *node); +static nxt_int_t njs_generate_export_statement(njs_vm_t *vm, + njs_generator_t *generator, njs_parser_node_t *node); static nxt_noinline njs_index_t njs_generate_dest_index(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node); static nxt_noinline njs_index_t @@ -171,8 +175,9 @@ static nxt_noinline nxt_int_t njs_genera static nxt_noinline nxt_int_t njs_generate_index_release(njs_vm_t *vm, 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, njs_parser_node_t *node); +static nxt_int_t njs_generate_function_debug(njs_vm_t *vm, + const nxt_str_t *name, njs_function_lambda_t *lambda, + njs_parser_node_t *node); #define njs_generate_code(generator, type, _code, _operation, nargs, _retval) \ @@ -467,6 +472,12 @@ njs_generator(njs_vm_t *vm, njs_generato case NJS_TOKEN_THROW: return njs_generate_throw_statement(vm, generator, node); + case NJS_TOKEN_IMPORT: + return njs_generate_import_statement(vm, generator, node); + + case NJS_TOKEN_EXPORT: + return njs_generate_export_statement(vm, generator, node); + default: nxt_thread_log_debug("unknown token: %d", node->token); njs_internal_error(vm, "Generator failed: unknown token"); @@ -1909,19 +1920,25 @@ njs_generate_function(njs_vm_t *vm, njs_ njs_parser_node_t *node) { nxt_int_t ret; + nxt_bool_t module; + const nxt_str_t *name; njs_function_lambda_t *lambda; njs_vmcode_function_t *function; lambda = node->u.value.data.u.lambda; - - ret = njs_generate_function_scope(vm, lambda, node, &njs_entry_anonymous); + module = node->right->scope->module; + + name = module ? &njs_entry_module : &njs_entry_anonymous; + + ret = njs_generate_function_scope(vm, lambda, node, name); if (nxt_slow_path(ret != NXT_OK)) { return ret; } if (vm->debug != NULL) { - ret = njs_generate_function_debug(vm, NULL, lambda, node); + ret = njs_generate_function_debug(vm, name, lambda, + module ? node->right : node); if (nxt_slow_path(ret != NXT_OK)) { return ret; } @@ -2450,7 +2467,6 @@ njs_generate_return_statement(njs_vm_t * njs_vmcode_try_return_t *try_return; ret = njs_generator(vm, generator, node->right); - if (nxt_slow_path(ret != NXT_OK)) { return ret; } @@ -3012,6 +3028,66 @@ njs_generate_throw_statement(njs_vm_t *v } +static nxt_int_t +njs_generate_import_statement(njs_vm_t *vm, njs_generator_t *generator, + njs_parser_node_t *node) +{ + nxt_int_t ret; + njs_index_t index; + njs_module_t *module; + njs_parser_node_t *lvalue, *expr; + njs_vmcode_object_copy_t *copy; + + lvalue = node->left; + expr = node->right; + + index = njs_variable_index(vm, lvalue); + if (nxt_slow_path(index == NJS_INDEX_ERROR)) { + return NXT_ERROR; + } + + if (expr->left != NULL) { + ret = njs_generator(vm, generator, expr->left); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } + } + + module = (njs_module_t *) expr->index; + + njs_generate_code(generator, njs_vmcode_object_copy_t, copy, + njs_vmcode_object_copy, 2, 1); + copy->retval = index; + copy->object = module->index; + + return NXT_OK; +} + + +static nxt_int_t +njs_generate_export_statement(njs_vm_t *vm, njs_generator_t *generator, + njs_parser_node_t *node) +{ + nxt_int_t ret; + njs_parser_node_t *obj; + njs_vmcode_return_t *code; + + obj = node->right; + + ret = njs_generator(vm, generator, obj); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } + + njs_generate_code(generator, njs_vmcode_return_t, code, + njs_vmcode_return, 1, 0); + code->retval = obj->index; + node->index = obj->index; + + return NXT_OK; +} + + static nxt_noinline njs_index_t njs_generate_dest_index(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node) @@ -3162,7 +3238,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_generate_function_debug(njs_vm_t *vm, const nxt_str_t *name, njs_function_lambda_t *lambda, njs_parser_node_t *node) { njs_function_debug_t *debug; @@ -3172,16 +3248,10 @@ njs_generate_function_debug(njs_vm_t *vm return NXT_ERROR; } - if (name != NULL) { - debug->name = *name; - - } else { - debug->name = no_label; - } - debug->lambda = lambda; debug->line = node->token_line; debug->file = node->scope->file; + debug->name = (name != NULL) ? *name : no_label; return NXT_OK; } diff -r 64dc0795c2f0 -r 53dc000e8c14 njs/njs_lexer.h --- a/njs/njs_lexer.h Wed Mar 20 15:56:22 2019 +0300 +++ b/njs/njs_lexer.h Sat Mar 02 20:31:10 2019 +0800 @@ -203,6 +203,10 @@ typedef enum { NJS_TOKEN_SET_IMMEDIATE, NJS_TOKEN_CLEAR_TIMEOUT, + NJS_TOKEN_IMPORT, + NJS_TOKEN_FROM, + NJS_TOKEN_EXPORT, + NJS_TOKEN_RESERVED, } njs_token_t; diff -r 64dc0795c2f0 -r 53dc000e8c14 njs/njs_lexer_keyword.c --- a/njs/njs_lexer_keyword.c Wed Mar 20 15:56:22 2019 +0300 +++ b/njs/njs_lexer_keyword.c Sat Mar 02 20:31:10 2019 +0800 @@ -93,6 +93,11 @@ static const njs_keyword_t njs_keywords { nxt_string("setImmediate"), NJS_TOKEN_SET_IMMEDIATE, 0 }, { nxt_string("clearTimeout"), NJS_TOKEN_CLEAR_TIMEOUT, 0 }, + /* Module. */ + { nxt_string("import"), NJS_TOKEN_IMPORT, 0 }, + { nxt_string("from"), NJS_TOKEN_FROM, 0 }, + { nxt_string("export"), NJS_TOKEN_EXPORT, 0 }, + /* Reserved words. */ { nxt_string("await"), NJS_TOKEN_RESERVED, 0 }, @@ -100,10 +105,8 @@ static const njs_keyword_t njs_keywords { nxt_string("const"), NJS_TOKEN_RESERVED, 0 }, { nxt_string("debugger"), 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("implements"), NJS_TOKEN_RESERVED, 0 }, - { nxt_string("import"), NJS_TOKEN_RESERVED, 0 }, { nxt_string("interface"), NJS_TOKEN_RESERVED, 0 }, { nxt_string("let"), NJS_TOKEN_RESERVED, 0 }, { nxt_string("package"), NJS_TOKEN_RESERVED, 0 }, diff -r 64dc0795c2f0 -r 53dc000e8c14 njs/njs_module.c --- a/njs/njs_module.c Wed Mar 20 15:56:22 2019 +0300 +++ b/njs/njs_module.c Sat Mar 02 20:31:10 2019 +0800 @@ -8,6 +8,369 @@ #include #include #include +#include +#include +#include +#include +#include +#include + + +typedef struct { + int fd; + nxt_str_t name; + nxt_str_t file; +} njs_module_info_t; + + +static nxt_int_t njs_module_lookup(njs_vm_t *vm, const nxt_str_t *cwd, + njs_module_info_t *info); +static nxt_noinline nxt_int_t njs_module_relative_path(njs_vm_t *vm, + const nxt_str_t *dir, njs_module_info_t *info); +static nxt_int_t njs_module_absolute_path(njs_vm_t *vm, + njs_module_info_t *info); +static nxt_bool_t njs_module_realpath_equal(const nxt_str_t *path1, + const nxt_str_t *path2); +static nxt_int_t njs_module_read(njs_vm_t *vm, int fd, nxt_str_t *body); +static njs_module_t *njs_module_find(njs_vm_t *vm, nxt_str_t *name); +static njs_module_t *njs_module_add(njs_vm_t *vm, nxt_str_t *name); +static nxt_int_t njs_module_insert(njs_vm_t *vm, njs_module_t *module); + + +nxt_int_t +njs_module_load(njs_vm_t *vm) +{ + nxt_int_t ret; + nxt_uint_t i; + njs_value_t *value; + njs_module_t **item, *module; + + if (vm->modules == NULL) { + return NXT_OK; + } + + item = vm->modules->start; + + for (i = 0; i < vm->modules->items; i++) { + module = *item; + + if (module->function.native) { + value = njs_vmcode_operand(vm, module->index); + value->data.u.object = &module->object; + value->type = NJS_OBJECT; + value->data.truth = 1; + + } else { + ret = njs_vm_invoke(vm, &module->function, NULL, 0, module->index); + if (ret == NXT_ERROR) { + goto done; + } + } + + item++; + } + + ret = NXT_OK; + +done: + + if (vm->options.accumulative) { + nxt_array_reset(vm->modules); + } + + return ret; +} + + +nxt_int_t +njs_parser_module(njs_vm_t *vm, njs_parser_t *parser) +{ + nxt_int_t ret; + nxt_str_t name, text; + njs_lexer_t *prev, lexer; + njs_token_t token; + njs_module_t *module; + njs_parser_node_t *node; + njs_module_info_t info; + + name = *njs_parser_text(parser); + + parser->node = NULL; + + module = njs_module_find(vm, &name); + if (module != NULL) { + goto found; + } + + prev = parser->lexer; + + nxt_memzero(&text, sizeof(nxt_str_t)); + + if (vm->options.sandbox || name.length == 0) { + njs_parser_syntax_error(vm, parser, "Cannot find module \"%V\"", &name); + goto fail; + } + + /* Non-native module. */ + + nxt_memzero(&info, sizeof(njs_module_info_t)); + + info.name = name; + + ret = njs_module_lookup(vm, &parser->scope->cwd, &info); + if (nxt_slow_path(ret != NXT_OK)) { + njs_parser_syntax_error(vm, parser, "Cannot find module \"%V\"", &name); + goto fail; + } + + ret = njs_module_read(vm, info.fd, &text); + + close(info.fd); + + if (nxt_slow_path(ret != NXT_OK)) { + njs_internal_error(vm, "while reading \"%V\" module", &name); + goto fail; + } + + if (njs_module_realpath_equal(&prev->file, &info.file)) { + njs_parser_syntax_error(vm, parser, "Cannot import itself \"%V\"", + &name); + goto fail; + } + + ret = njs_lexer_init(vm, &lexer, &info.file, text.start, + text.start + text.length); + if (nxt_slow_path(ret != NXT_OK)) { + return NJS_ERROR; + } + + parser->lexer = &lexer; + + token = njs_parser_token(vm, parser); + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + goto fail; + } + + token = njs_parser_module_lambda(vm, parser); + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + goto fail; + } + + module = njs_module_add(vm, &name); + if (nxt_slow_path(module == NULL)) { + goto fail; + } + + module->function.u.lambda = parser->node->u.value.data.u.lambda; + + nxt_mp_free(vm->mem_pool, text.start); + + parser->lexer = prev; + +found: + + node = njs_parser_node_new(vm, parser, 0); + if (nxt_slow_path(node == NULL)) { + return NXT_ERROR; + } + + node->left = parser->node; + + if (module->index == 0) { + ret = njs_module_insert(vm, module); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } + } + + node->index = (njs_index_t) module; + + parser->node = node; + + return NXT_OK; + +fail: + + parser->lexer = prev; + + if (text.start != NULL) { + nxt_mp_free(vm->mem_pool, text.start); + } + + return NXT_ERROR; +} + + +static nxt_int_t +njs_module_lookup(njs_vm_t *vm, const nxt_str_t *cwd, njs_module_info_t *info) +{ + nxt_int_t ret; + nxt_str_t *path; + nxt_uint_t i; + + if (info->name.start[0] == '/') { + return njs_module_absolute_path(vm, info); + } + + ret = njs_module_relative_path(vm, cwd, info); + if (ret == NXT_OK) { + return ret; + } + + if (vm->paths == NULL) { + return NXT_DECLINED; + } + + path = vm->paths->start; + + for (i = 0; i < vm->paths->items; i++) { + ret = njs_module_relative_path(vm, path, info); + if (ret == NXT_OK) { + return ret; + } + + path++; + } + + return NXT_DECLINED; +} + + +static nxt_int_t +njs_module_absolute_path(njs_vm_t *vm, njs_module_info_t *info) +{ + nxt_str_t file; + + file.length = info->name.length; + file.start = nxt_mp_alloc(vm->mem_pool, file.length + 1); + if (nxt_slow_path(file.start == NULL)) { + return NXT_ERROR; + } + + memcpy(file.start, info->name.start, file.length); + file.start[file.length] = '\0'; + + info->fd = open((char *) file.start, O_RDONLY); + if (info->fd < 0) { + nxt_mp_free(vm->mem_pool, file.start); + return NXT_DECLINED; + } + + info->file = file; + + return NXT_OK; +} + + +static nxt_noinline nxt_int_t +njs_module_relative_path(njs_vm_t *vm, const nxt_str_t *dir, + njs_module_info_t *info) +{ + u_char *p; + nxt_str_t file; + nxt_bool_t trail; + + file.length = dir->length; + + trail = (dir->start[dir->length - 1] != '/'); + + if (trail) { + file.length++; + } + + file.length += info->name.length; + + file.start = nxt_mp_alloc(vm->mem_pool, file.length + 1); + if (nxt_slow_path(file.start == NULL)) { + return NXT_ERROR; + } + + p = nxt_cpymem(file.start, dir->start, dir->length); + + if (trail) { + *p++ = '/'; + } + + p = nxt_cpymem(p, info->name.start, info->name.length); + *p = '\0'; + + info->fd = open((char *) file.start, O_RDONLY); + if (info->fd < 0) { + nxt_mp_free(vm->mem_pool, file.start); + return NXT_DECLINED; + } + + info->file = file; + + return NXT_OK; +} + + +#define NJS_MODULE_START "function() {" +#define NJS_MODULE_END "}" + +static nxt_int_t +njs_module_read(njs_vm_t *vm, int fd, nxt_str_t *text) +{ + u_char *p; + ssize_t n; + struct stat sb; + + if (fstat(fd, &sb) == -1) { + goto fail; + } + + text->length = nxt_length(NJS_MODULE_START); + + if (S_ISREG(sb.st_mode) && sb.st_size) { + text->length += sb.st_size; + } + + text->length += nxt_length(NJS_MODULE_END); + + text->start = nxt_mp_alloc(vm->mem_pool, text->length); + if (text->start == NULL) { + goto fail; + } + + p = nxt_cpymem(text->start, NJS_MODULE_START, nxt_length(NJS_MODULE_START)); + + n = read(fd, p, sb.st_size); + + if (n < 0) { + goto fail; + } + + if (n != sb.st_size) { + goto fail; + } + + p += n; + + memcpy(p, NJS_MODULE_END, nxt_length(NJS_MODULE_END)); + + return NXT_OK; + +fail: + + if (text->start != NULL) { + nxt_mp_free(vm->mem_pool, text->start); + } + + return NXT_ERROR; +} + + +static nxt_bool_t +njs_module_realpath_equal(const nxt_str_t *path1, const nxt_str_t *path2) +{ + char rpath1[MAXPATHLEN], rpath2[MAXPATHLEN]; + + realpath((char *) path1->start, rpath1); + realpath((char *) path2->start, rpath2); + + return (strcmp(rpath1, rpath2) == 0); +} static nxt_int_t @@ -36,6 +399,98 @@ const nxt_lvlhsh_proto_t njs_modules_ha }; +static njs_module_t * +njs_module_find(njs_vm_t *vm, nxt_str_t *name) +{ + nxt_lvlhsh_query_t lhq; + + lhq.key = *name; + lhq.key_hash = nxt_djb_hash(name->start, name->length); + lhq.proto = &njs_modules_hash_proto; + + if (nxt_lvlhsh_find(&vm->modules_hash, &lhq) == NXT_OK) { + return lhq.value; + } + + return NULL; +} + + +static njs_module_t * +njs_module_add(njs_vm_t *vm, nxt_str_t *name) +{ + nxt_int_t ret; + njs_module_t *module; + nxt_lvlhsh_query_t lhq; + + module = nxt_mp_zalloc(vm->mem_pool, sizeof(njs_module_t)); + if (nxt_slow_path(module == NULL)) { + njs_memory_error(vm); + return NULL; + } + + ret = njs_name_copy(vm, &module->name, name); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_mp_free(vm->mem_pool, module); + njs_memory_error(vm); + return NULL; + } + + lhq.replace = 0; + lhq.key = *name; + lhq.key_hash = nxt_djb_hash(name->start, name->length); + lhq.value = module; + lhq.pool = vm->mem_pool; + lhq.proto = &njs_modules_hash_proto; + + ret = nxt_lvlhsh_insert(&vm->modules_hash, &lhq); + + if (nxt_fast_path(ret == NXT_OK)) { + return module; + } + + nxt_mp_free(vm->mem_pool, module->name.start); + nxt_mp_free(vm->mem_pool, module); + + njs_internal_error(vm, "lvlhsh insert failed"); + + return NULL; +} + + +static nxt_int_t +njs_module_insert(njs_vm_t *vm, njs_module_t *module) +{ + njs_module_t **value; + njs_parser_scope_t *scope; + + scope = njs_parser_global_scope(vm); + + module->index = njs_scope_next_index(vm, scope, NJS_SCOPE_INDEX_LOCAL, + &njs_value_undefined); + if (nxt_slow_path(module->index == NJS_INDEX_ERROR)) { + return NXT_ERROR; + } + + if (vm->modules == NULL) { + vm->modules = nxt_array_create(4, sizeof(njs_module_t *), + &njs_array_mem_proto, vm->mem_pool); + if (nxt_slow_path(vm->modules == NULL)) { + return NXT_ERROR; + } + } + + value = nxt_array_add(vm->modules, &njs_array_mem_proto, vm->mem_pool); + if (nxt_slow_path(value == NULL)) { + return NXT_ERROR; + } + + *value = module; + + return NXT_OK; +} + + njs_ret_t njs_module_require(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) { diff -r 64dc0795c2f0 -r 53dc000e8c14 njs/njs_module.h --- a/njs/njs_module.h Wed Mar 20 15:56:22 2019 +0300 +++ b/njs/njs_module.h Sat Mar 02 20:31:10 2019 +0800 @@ -11,9 +11,13 @@ typedef struct { nxt_str_t name; njs_object_t object; + njs_index_t index; + njs_function_t function; } njs_module_t; +nxt_int_t njs_module_load(njs_vm_t *vm); +nxt_int_t njs_parser_module(njs_vm_t *vm, njs_parser_t *parser); njs_ret_t njs_module_require(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); diff -r 64dc0795c2f0 -r 53dc000e8c14 njs/njs_parser.c --- a/njs/njs_parser.c Wed Mar 20 15:56:22 2019 +0300 +++ b/njs/njs_parser.c Sat Mar 02 20:31:10 2019 +0800 @@ -59,6 +59,13 @@ static njs_token_t njs_parser_try_statem 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, njs_parser_t *parser); +static njs_token_t njs_parser_import_statement(njs_vm_t *vm, + njs_parser_t *parser); +static njs_token_t njs_parser_export_statement(njs_vm_t *vm, + njs_parser_t *parser); +static nxt_int_t njs_parser_import_hoist(njs_vm_t *vm, njs_parser_t *parser, + njs_parser_node_t *new_node); +static nxt_int_t njs_parser_export_sink(njs_vm_t *vm, njs_parser_t *parser); static njs_token_t njs_parser_grouping_expression(njs_vm_t *vm, njs_parser_t *parser); static njs_parser_node_t *njs_parser_reference(njs_vm_t *vm, @@ -87,9 +94,6 @@ static njs_token_t njs_parser_unexpected #define njs_parser_chain_top_set(parser, node) \ (parser)->scope->top = node -#define njs_parser_text(parser) \ - &(parser)->lexer->lexer_token->text - #define njs_parser_key_hash(parser) \ (parser)->lexer->lexer_token->key_hash @@ -259,6 +263,7 @@ njs_parser_scope_begin(njs_vm_t *vm, njs if (lexer->file.length != 0) { nxt_file_basename(&lexer->file, &scope->file); + nxt_file_dirname(&lexer->file, &scope->cwd); } parent = parser->scope; @@ -394,6 +399,14 @@ njs_parser_statement(njs_vm_t *vm, njs_p token = njs_parser_brk_statement(vm, parser, token); break; + case NJS_TOKEN_IMPORT: + token = njs_parser_import_statement(vm, parser); + break; + + case NJS_TOKEN_EXPORT: + token = njs_parser_export_statement(vm, parser); + break; + case NJS_TOKEN_NAME: offset = 0; if (njs_parser_peek_token(vm, parser, &offset) == NJS_TOKEN_COLON) { @@ -955,9 +968,13 @@ njs_parser_return_statement(njs_vm_t *vm njs_parser_scope_t *scope; for (scope = parser->scope; - scope->type != NJS_SCOPE_FUNCTION; + scope != NULL; scope = scope->parent) { + if (scope->type == NJS_SCOPE_FUNCTION && !scope->module) { + break; + } + if (scope->type == NJS_SCOPE_GLOBAL) { njs_parser_syntax_error(vm, parser, "Illegal return statement"); @@ -1878,6 +1895,289 @@ njs_parser_throw_statement(njs_vm_t *vm, static njs_token_t +njs_parser_import_statement(njs_vm_t *vm, njs_parser_t *parser) +{ + njs_ret_t ret; + njs_token_t token; + njs_variable_t *var; + njs_parser_node_t *name, *import; + + if (parser->scope->type != NJS_SCOPE_GLOBAL + && !parser->scope->module) + { + njs_parser_syntax_error(vm, parser, "Illegal import statement"); + + return NJS_TOKEN_ERROR; + } + + token = njs_parser_token(vm, parser); + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return token; + } + + if (token != NJS_TOKEN_NAME) { + njs_parser_syntax_error(vm, parser, + "Non-default import is not supported"); + return NJS_TOKEN_ILLEGAL; + } + + var = njs_parser_variable_add(vm, parser, NJS_VARIABLE_VAR); + if (nxt_slow_path(var == NULL)) { + return NJS_TOKEN_ERROR; + } + + name = njs_parser_node_new(vm, parser, NJS_TOKEN_NAME); + if (nxt_slow_path(name == NULL)) { + return NJS_TOKEN_ERROR; + } + + ret = njs_parser_variable_reference(vm, parser, name, NJS_DECLARATION); + if (nxt_slow_path(ret != NXT_OK)) { + return NJS_TOKEN_ERROR; + } + + token = njs_parser_token(vm, parser); + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return token; + } + + token = njs_parser_match(vm, parser, token, NJS_TOKEN_FROM); + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return token; + } + + if (token != NJS_TOKEN_STRING) { + return NJS_TOKEN_ILLEGAL; + } + + ret = njs_parser_module(vm, parser); + if (nxt_slow_path(ret != NXT_OK)) { + return NJS_TOKEN_ERROR; + } + + import = njs_parser_node_new(vm, parser, NJS_TOKEN_IMPORT); + if (nxt_slow_path(import == NULL)) { + return NJS_TOKEN_ERROR; + } + + import->left = name; + import->right = parser->node; + + ret = njs_parser_import_hoist(vm, parser, import); + if (nxt_slow_path(ret != NXT_OK)) { + return NJS_TOKEN_ERROR; + } + + parser->node = NULL; + + return njs_parser_token(vm, parser); +} + + +njs_token_t +njs_parser_module_lambda(njs_vm_t *vm, njs_parser_t *parser) +{ + njs_ret_t ret; + njs_token_t token; + njs_parser_node_t *node, *parent; + njs_function_lambda_t *lambda; + + node = njs_parser_node_new(vm, parser, NJS_TOKEN_FUNCTION_EXPRESSION); + if (nxt_slow_path(node == NULL)) { + return NJS_TOKEN_ERROR; + } + + node->token_line = njs_parser_token_line(parser); + + token = njs_parser_token(vm, parser); + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return token; + } + + lambda = nxt_mp_zalloc(vm->mem_pool, sizeof(njs_function_lambda_t)); + if (nxt_slow_path(lambda == NULL)) { + return NJS_TOKEN_ERROR; + } + + node->u.value.data.u.lambda = lambda; + parser->node = node; + + ret = njs_parser_scope_begin(vm, parser, NJS_SCOPE_FUNCTION); + if (nxt_slow_path(ret != NXT_OK)) { + return NJS_TOKEN_ERROR; + } + + parser->scope->module = 1; + + token = njs_parser_match(vm, parser, token, NJS_TOKEN_OPEN_PARENTHESIS); + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return token; + } + + parent = parser->node; + + token = njs_parser_match(vm, parser, token, NJS_TOKEN_CLOSE_PARENTHESIS); + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return token; + } + + token = njs_parser_lambda_statements(vm, parser, token); + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return token; + } + + ret = njs_parser_export_sink(vm, parser); From xeioex at nginx.com Sat Mar 23 12:38:55 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Sat, 23 Mar 2019 12:38:55 +0000 Subject: [njs] Fixed nxt_file_dirname() for paths with no dir component. Message-ID: details: https://hg.nginx.org/njs/rev/aaf68d999559 branches: changeset: 838:aaf68d999559 user: hongzhidao date: Sat Mar 23 14:57:52 2019 +0300 description: Fixed nxt_file_dirname() for paths with no dir component. Making it more similar to dirname shell cmd. This closes #114 issue on Github. diffstat: njs/test/njs_unit_test.c | 4 ++-- nxt/nxt_file.c | 12 ++++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diffs (53 lines): diff -r 53dc000e8c14 -r aaf68d999559 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Sat Mar 02 20:31:10 2019 +0800 +++ b/njs/test/njs_unit_test.c Sat Mar 23 14:57:52 2019 +0300 @@ -12456,13 +12456,13 @@ nxt_file_dirname_test(njs_vm_t * vm, nxt nxt_str_t path; nxt_str_t expected; } tests[] = { - { nxt_string(""), nxt_string("") }, + { 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(".") }, { nxt_string("a/"), nxt_string("a") }, { nxt_string("a//"), nxt_string("a") }, { nxt_string("p1/p2/name"), nxt_string("p1/p2") }, diff -r 53dc000e8c14 -r aaf68d999559 nxt/nxt_file.c --- a/nxt/nxt_file.c Sat Mar 02 20:31:10 2019 +0800 +++ b/nxt/nxt_file.c Sat Mar 23 14:57:52 2019 +0300 @@ -38,8 +38,7 @@ nxt_file_dirname(const nxt_str_t *path, const u_char *p, *end; if (path->length == 0) { - *name = nxt_string_value(""); - return; + goto current_dir; } p = path->start + path->length - 1; @@ -51,8 +50,7 @@ nxt_file_dirname(const nxt_str_t *path, end = p + 1; if (end == path->start) { - *name = nxt_string_value(""); - return; + goto current_dir; } /* Stripping trailing slashes. */ @@ -67,4 +65,10 @@ nxt_file_dirname(const nxt_str_t *path, name->start = path->start; name->length = p - path->start; + + return; + +current_dir: + + *name = nxt_string_value("."); } From xeioex at nginx.com Sat Mar 23 15:47:32 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Sat, 23 Mar 2019 15:47:32 +0000 Subject: [njs] Fixed accesing global function and objects in modules. Message-ID: details: https://hg.nginx.org/njs/rev/81303df0fd67 branches: changeset: 839:81303df0fd67 user: Dmitry Volyntsev date: Sat Mar 23 16:39:40 2019 +0300 description: Fixed accesing global function and objects in modules. diffstat: njs/njs_variable.c | 2 +- njs/test/module/normal.js | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diffs (59 lines): diff -r aaf68d999559 -r 81303df0fd67 njs/njs_variable.c --- a/njs/njs_variable.c Sat Mar 23 14:57:52 2019 +0300 +++ b/njs/njs_variable.c Sat Mar 23 16:39:40 2019 +0300 @@ -488,7 +488,7 @@ njs_variable_reference_resolve(njs_vm_t return NXT_OK; } - if (scope->module || scope->parent == NULL) { + if (scope->parent == NULL) { /* A global scope. */ vr->scope = scope; diff -r aaf68d999559 -r 81303df0fd67 njs/test/module/normal.js --- a/njs/test/module/normal.js Sat Mar 23 14:57:52 2019 +0300 +++ b/njs/test/module/normal.js Sat Mar 23 16:39:40 2019 +0300 @@ -6,30 +6,36 @@ import crypto from 'crypto'; var h = crypto.createHash('md5'); var hash = h.update('AB').digest('hex'); +var fails = 0; if (lib1.hash() != hash) { - console.log("failed!"); + fails++; } if (lib2.hash() != hash) { - console.log("failed!"); + fails++; } if (lib1.get() != 0) { - console.log("failed!"); + fails++; } if (lib1_2.get() != 0) { - console.log("failed!"); + fails++; } lib1.inc(); if (lib1.get() != 1) { - console.log("failed!"); + fails++; } if (lib1_2.get() != 1) { - console.log("failed!"); + fails++; } -console.log("passed!"); +if (JSON.stringify({}) != "{}") { + fails++; +} + +setImmediate(console.log, + fails ? "failed: " + fails : "passed!"); From lv at haitao.dev Sun Mar 24 08:57:54 2019 From: lv at haitao.dev (=?utf-8?B?5ZCV5rW35rab?=) Date: Sun, 24 Mar 2019 16:57:54 +0800 Subject: HTTP: add connect_timeout for proxy_next_upstream Message-ID: <024819FA-2437-4214-8926-480C3382ACCF@haitao.dev> commit c6f872f4dfa4abecc953f09cdb3e1537d866d2f4 Author: ??? Date: Sun Mar 24 16:46:56 2019 +0800 HTTP: add connect_timeout for proxy_next_upstream Nginx support both timeout and non_idempotent flag for proxy_next_upstream. However, in some environment, even the GET method is non_idempotent. We need nginx try the next upstream if and only if the tcp connect is timeout. diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c index 3aafb999..6a5419e3 100644 --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -212,6 +212,7 @@ static ngx_conf_post_t ngx_http_proxy_lowat_post = static ngx_conf_bitmask_t ngx_http_proxy_next_upstream_masks[] = { { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR }, { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT }, + { ngx_string("connect_timeout"), NGX_HTTP_UPSTREAM_FT_CONNECT_TIMEOUT }, { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER }, { ngx_string("non_idempotent"), NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT }, { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 }, diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index a7391d09..b491db6d 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -4158,8 +4158,17 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u, } if (ft_type == NGX_HTTP_UPSTREAM_FT_TIMEOUT) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_ETIMEDOUT, - "upstream timed out"); + if (!u->request_sent + && (u->conf->next_upstream & NGX_HTTP_UPSTREAM_FT_CONNECT_TIMEOUT)) + { + ft_type = NGX_HTTP_UPSTREAM_FT_CONNECT_TIMEOUT; + + ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_ETIMEDOUT, + "upstream connect timed out"); + } else { + ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_ETIMEDOUT, + "upstream timed out"); + } } if (u->peer.cached && ft_type == NGX_HTTP_UPSTREAM_FT_ERROR) { @@ -4171,6 +4180,7 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u, case NGX_HTTP_UPSTREAM_FT_TIMEOUT: case NGX_HTTP_UPSTREAM_FT_HTTP_504: + case NGX_HTTP_UPSTREAM_FT_CONNECT_TIMEOUT: status = NGX_HTTP_GATEWAY_TIME_OUT; break; diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h index 6079d723..8449b463 100644 --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -31,6 +31,7 @@ #define NGX_HTTP_UPSTREAM_FT_BUSY_LOCK 0x00001000 #define NGX_HTTP_UPSTREAM_FT_MAX_WAITING 0x00002000 #define NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT 0x00004000 +#define NGX_HTTP_UPSTREAM_FT_CONNECT_TIMEOUT 0x00010000 #define NGX_HTTP_UPSTREAM_FT_NOLIVE 0x40000000 #define NGX_HTTP_UPSTREAM_FT_OFF 0x80000000 From xeioex at nginx.com Mon Mar 25 12:59:39 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 25 Mar 2019 12:59:39 +0000 Subject: [njs] Shell: fixed potential memory leak in main(). Message-ID: details: https://hg.nginx.org/njs/rev/3aa52df685bc branches: changeset: 840:3aa52df685bc user: Dmitry Volyntsev date: Mon Mar 25 15:41:21 2019 +0300 description: Shell: fixed potential memory leak in main(). diffstat: njs/njs_shell.c | 19 ++++++++++++------- 1 files changed, 12 insertions(+), 7 deletions(-) diffs (65 lines): diff -r 81303df0fd67 -r 3aa52df685bc njs/njs_shell.c --- a/njs/njs_shell.c Sat Mar 23 16:39:40 2019 +0300 +++ b/njs/njs_shell.c Mon Mar 25 15:41:21 2019 +0300 @@ -209,12 +209,14 @@ main(int argc, char **argv) ret = njs_get_options(&opts, argc, argv); if (ret != NXT_OK) { - return (ret == NXT_DONE) ? EXIT_SUCCESS : EXIT_FAILURE; + ret = (ret == NXT_DONE) ? NXT_OK : NXT_ERROR; + goto done; } if (opts.version != 0) { printf("%s\n", NJS_VERSION); - return EXIT_SUCCESS; + ret = NXT_OK; + goto done; } nxt_memzero(&vm_options, sizeof(njs_vm_opt_t)); @@ -224,7 +226,8 @@ main(int argc, char **argv) p = getcwd(path, sizeof(path)); if (p == NULL) { fprintf(stderr, "getcwd() failed:%s\n", strerror(errno)); - return EXIT_FAILURE; + ret = NXT_ERROR; + goto done; } memcpy(path + strlen(path), "/shell", sizeof("/shell")); @@ -249,6 +252,8 @@ main(int argc, char **argv) ret = njs_process_file(&opts, &vm_options); } +done: + if (opts.paths != NULL) { free(opts.paths); } @@ -260,7 +265,7 @@ main(int argc, char **argv) static nxt_int_t njs_get_options(njs_opts_t *opts, int argc, char** argv) { - char *p; + char *p, **paths; nxt_int_t i, ret; static const char help[] = @@ -309,13 +314,13 @@ njs_get_options(njs_opts_t *opts, int ar case 'p': if (argv[++i] != NULL) { opts->n_paths++; - opts->paths = realloc(opts->paths, - opts->n_paths * sizeof(char *)); - if (opts->paths == NULL) { + paths = realloc(opts->paths, opts->n_paths * sizeof(char *)); + if (paths == NULL) { fprintf(stderr, "failed to add path\n"); return NXT_ERROR; } + opts->paths = paths; opts->paths[opts->n_paths - 1] = argv[i]; break; } From xeioex at nginx.com Mon Mar 25 14:51:28 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 25 Mar 2019 14:51:28 +0000 Subject: [njs] Resetting loaded modules in accumulative mode. Message-ID: details: https://hg.nginx.org/njs/rev/e3ee3a2d9994 branches: changeset: 841:e3ee3a2d9994 user: Dmitry Volyntsev date: Mon Mar 25 17:51:19 2019 +0300 description: Resetting loaded modules in accumulative mode. This closes #113 issue on Github. diffstat: njs/njs.c | 4 ++++ njs/njs_module.c | 36 ++++++++++++++++++++++++++++++------ njs/njs_module.h | 1 + njs/test/module/ref_exception.js | 1 + njs/test/njs_expect_test.exp | 12 +++++++++--- 5 files changed, 45 insertions(+), 9 deletions(-) diffs (115 lines): diff -r 3aa52df685bc -r e3ee3a2d9994 njs/njs.c --- a/njs/njs.c Mon Mar 25 15:41:21 2019 +0300 +++ b/njs/njs.c Mon Mar 25 17:51:19 2019 +0300 @@ -226,6 +226,10 @@ njs_vm_compile(njs_vm_t *vm, u_char **st return NJS_ERROR; } + if (vm->modules != NULL && vm->options.accumulative) { + njs_module_reset(vm); + } + parser = nxt_mp_zalloc(vm->mem_pool, sizeof(njs_parser_t)); if (nxt_slow_path(parser == NULL)) { return NJS_ERROR; diff -r 3aa52df685bc -r e3ee3a2d9994 njs/njs_module.c --- a/njs/njs_module.c Mon Mar 25 15:41:21 2019 +0300 +++ b/njs/njs_module.c Mon Mar 25 17:51:19 2019 +0300 @@ -63,22 +63,46 @@ njs_module_load(njs_vm_t *vm) } else { ret = njs_vm_invoke(vm, &module->function, NULL, 0, module->index); if (ret == NXT_ERROR) { - goto done; + return ret; } } item++; } - ret = NXT_OK; + return NXT_OK; +} + -done: +void +njs_module_reset(njs_vm_t *vm) +{ + nxt_uint_t i; + njs_module_t **item, *module; + nxt_lvlhsh_query_t lhq; - if (vm->options.accumulative) { - nxt_array_reset(vm->modules); + if (vm->modules == NULL) { + return; } - return ret; + item = vm->modules->start; + + for (i = 0; i < vm->modules->items; i++) { + module = *item; + + if (!module->function.native) { + lhq.key = module->name; + lhq.key_hash = nxt_djb_hash(lhq.key.start, lhq.key.length); + lhq.proto = &njs_modules_hash_proto; + lhq.pool = vm->mem_pool; + + (void) nxt_lvlhsh_delete(&vm->modules_hash, &lhq); + } + + item++; + } + + nxt_array_reset(vm->modules); } diff -r 3aa52df685bc -r e3ee3a2d9994 njs/njs_module.h --- a/njs/njs_module.h Mon Mar 25 15:41:21 2019 +0300 +++ b/njs/njs_module.h Mon Mar 25 17:51:19 2019 +0300 @@ -17,6 +17,7 @@ typedef struct { nxt_int_t njs_module_load(njs_vm_t *vm); +void njs_module_reset(njs_vm_t *vm); nxt_int_t njs_parser_module(njs_vm_t *vm, njs_parser_t *parser); njs_ret_t njs_module_require(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); diff -r 3aa52df685bc -r e3ee3a2d9994 njs/test/module/ref_exception.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/njs/test/module/ref_exception.js Mon Mar 25 17:51:19 2019 +0300 @@ -0,0 +1,1 @@ +export default {type:typeof undeclared, undeclared}; diff -r 3aa52df685bc -r e3ee3a2d9994 njs/test/njs_expect_test.exp --- a/njs/test/njs_expect_test.exp Mon Mar 25 15:41:21 2019 +0300 +++ b/njs/test/njs_expect_test.exp Mon Mar 25 17:51:19 2019 +0300 @@ -659,9 +659,7 @@ njs_test { # modules njs_test { - {"import lib1 from 'lib1.js'\r\n" - "undefined\r\n"} - {"import lib2 from 'lib1.js'\r\n" + {"import lib1 from 'lib1.js'; import lib2 from 'lib1.js'\r\n" "undefined\r\n"} {"lib2.inc()\r\n" "undefined\r\n"} @@ -675,6 +673,14 @@ njs_test { "Identifier \"default\" has already been declared in export.js:5\r\n"} {"import m from 'export_non_default.js'\r\n" "Non-default export is not supported in export_non_default.js:3\r\n"} + {"import ref from 'ref_exception.js'\r\n" + "ReferenceError: \"undeclared\" is not defined in ref_exception.js:1"} + {"ref\r\n" + "ReferenceError: \"ref\" is not defined in shell:1\r\n"} + {"var ref\r\n" + "undefined\r\n"} + {"import ref from 'ref_exception.js'\r\n" + "ReferenceError: \"undeclared\" is not defined in ref_exception.js:1"} {"import m from 'loading_exception.js'\r\n" "Error: loading exception\r\n at module \\(loading_exception.js:1\\)"} {"import lib3 from 'lib1.js'\r\n" From mdounin at mdounin.ru Mon Mar 25 17:06:11 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 25 Mar 2019 20:06:11 +0300 Subject: HTTP: add connect_timeout for proxy_next_upstream In-Reply-To: <024819FA-2437-4214-8926-480C3382ACCF@haitao.dev> References: <024819FA-2437-4214-8926-480C3382ACCF@haitao.dev> Message-ID: <20190325170611.GZ1877@mdounin.ru> Hello! On Sun, Mar 24, 2019 at 04:57:54PM +0800, ??? wrote: > commit c6f872f4dfa4abecc953f09cdb3e1537d866d2f4 > Author: ??? > Date: Sun Mar 24 16:46:56 2019 +0800 > > HTTP: add connect_timeout for proxy_next_upstream > > Nginx support both timeout and non_idempotent flag for > proxy_next_upstream. However, in some environment, > even the GET method is non_idempotent. > > We need nginx try the next upstream if and only if the > tcp connect is timeout. Thank you for your patch. If GET requests are not idempotent in your environment, you have a serious problem regardless of nginx request handling, as browsers and other clients will not consider these requests non-idempotent, and will re-try requests as needed. You may want to re-engineer your request handling instead of trying to introduce workarounds in nginx. [...] -- Maxim Dounin http://mdounin.ru/ From n.morozov at securitycode.ru Tue Mar 26 07:02:33 2019 From: n.morozov at securitycode.ru (Nikolay Morozov) Date: Tue, 26 Mar 2019 10:02:33 +0300 Subject: [PATCH] Remove memory leak in ngx_event_openssl.c Message-ID: # HG changeset patch # User Nikolay Morozov # Date 1553582037 -10800 # Tue Mar 26 09:33:57 2019 +0300 # Node ID e3d5aaa0f3df9e0d60e384e78e40f6fb7bd4524f # Parent d9c3917c7f901ac2a0f4a483f3229a63b51840c5 Remove memory leak in ngx_event_openssl.c If X509_get_issuer_name() or X509_get_subject_name() return an error, certificate leaks. diff -r d9c3917c7f90 -r e3d5aaa0f3df src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Wed Mar 06 20:46:09 2019 +0300 +++ b/src/event/ngx_event_openssl.c Tue Mar 26 09:33:57 2019 +0300 @@ -4622,6 +4622,7 @@ name = X509_get_subject_name(cert); if (name == NULL) { + X509_free(cert); return NGX_ERROR; } @@ -4673,6 +4674,7 @@ name = X509_get_issuer_name(cert); if (name == NULL) { + X509_free(cert); return NGX_ERROR; } ????????? ? ?????????????????? ?????? ??????????? ?????? ? ????? ?????????? ? ???? ???????? ????????????????? ? ????????????? ????????????? ??? ????????. ???? ?? ?? ????????? ????????? ??????? ??????, ??????????, ????????? ?????????? ???????????, ?? ??????????? ?????????? ?????? ?????, ?? ??????????? ??? ? ?????-???? ?????, ?? ??????? ? ?? ????????? ?????????? ????? ????????. From xeioex at nginx.com Tue Mar 26 12:53:46 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 26 Mar 2019 12:53:46 +0000 Subject: [njs] Modules: returning undefined value for absent values. Message-ID: details: https://hg.nginx.org/njs/rev/b758915e2406 branches: changeset: 842:b758915e2406 user: Dmitry Volyntsev date: Tue Mar 26 14:51:03 2019 +0300 description: Modules: returning undefined value for absent values. Instead of empty string. diffstat: nginx/ngx_http_js_module.c | 17 +++++++++++------ nginx/ngx_stream_js_module.c | 3 ++- 2 files changed, 13 insertions(+), 7 deletions(-) diffs (68 lines): diff -r e3ee3a2d9994 -r b758915e2406 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Mon Mar 25 17:51:19 2019 +0300 +++ b/nginx/ngx_http_js_module.c Tue Mar 26 14:51:03 2019 +0300 @@ -922,7 +922,8 @@ 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_vm_value_string_set(vm, value, NULL, 0); + njs_value_undefined_set(value); + return NJS_OK; } return njs_vm_value_string_set(vm, value, h->value.data, h->value.len); @@ -1433,8 +1434,8 @@ ngx_http_js_ext_get_request_body(njs_vm_ } if (r->request_body == NULL || r->request_body->bufs == NULL) { - njs_vm_error(vm, "request body is unavailable"); - return NJS_ERROR; + njs_value_undefined_set(value); + return NJS_OK; } if (r->request_body->temp_file) { @@ -1502,7 +1503,8 @@ 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_vm_value_string_set(vm, value, NULL, 0); + njs_value_undefined_set(value); + return NJS_OK; } return njs_vm_value_string_set(vm, value, h->value.data, h->value.len); @@ -1531,7 +1533,9 @@ ngx_http_js_ext_get_arg(njs_vm_t *vm, nj return njs_vm_value_string_set(vm, value, arg.data, arg.len); } - return njs_vm_value_string_set(vm, value, NULL, 0); + njs_value_undefined_set(value); + + return NJS_OK; } @@ -1620,7 +1624,8 @@ 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_vm_value_string_set(vm, value, NULL, 0); + njs_value_undefined_set(value); + return NJS_OK; } return njs_vm_value_string_set(vm, value, vv->data, vv->len); diff -r e3ee3a2d9994 -r b758915e2406 nginx/ngx_stream_js_module.c --- a/nginx/ngx_stream_js_module.c Mon Mar 25 17:51:19 2019 +0300 +++ b/nginx/ngx_stream_js_module.c Tue Mar 26 14:51:03 2019 +0300 @@ -1203,7 +1203,8 @@ 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_vm_value_string_set(vm, value, NULL, 0); + njs_value_undefined_set(value); + return NJS_OK; } return njs_vm_value_string_set(vm, value, vv->data, vv->len); From xeioex at nginx.com Tue Mar 26 12:53:46 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 26 Mar 2019 12:53:46 +0000 Subject: [njs] Treating null and undefined as empty string for external prop set. Message-ID: details: https://hg.nginx.org/njs/rev/c2c8cc00176f branches: changeset: 843:c2c8cc00176f user: Dmitry Volyntsev date: Tue Mar 26 15:28:18 2019 +0300 description: Treating null and undefined as empty string for external prop set. diffstat: njs/njs_object.c | 11 ++++++++--- 1 files changed, 8 insertions(+), 3 deletions(-) diffs (21 lines): diff -r b758915e2406 -r c2c8cc00176f njs/njs_object.c --- a/njs/njs_object.c Tue Mar 26 14:51:03 2019 +0300 +++ b/njs/njs_object.c Tue Mar 26 15:28:18 2019 +0300 @@ -684,9 +684,14 @@ njs_external_property_set(njs_vm_t *vm, pq = (njs_property_query_t *) vm->stash; - ret = njs_vm_value_to_ext_string(vm, &s, setval, 0); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; + if (!njs_is_null_or_undefined(setval)) { + ret = njs_vm_value_to_ext_string(vm, &s, setval, 0); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } + + } else { + s = nxt_string_value(""); } *retval = *setval; From xeioex at nginx.com Tue Mar 26 12:53:46 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 26 Mar 2019 12:53:46 +0000 Subject: [njs] Modules: improved working with arguments. Message-ID: details: https://hg.nginx.org/njs/rev/4c7862cf1ba1 branches: changeset: 844:4c7862cf1ba1 user: Dmitry Volyntsev date: Tue Mar 26 15:35:45 2019 +0300 description: Modules: improved working with arguments. According to ES 5.1:10.5 direct checking of the number of arguments should be avoided. diffstat: nginx/ngx_http_js_module.c | 131 +++++++++++++++++++----------------------- nginx/ngx_stream_js_module.c | 28 +++++++- 2 files changed, 82 insertions(+), 77 deletions(-) diffs (309 lines): diff -r c2c8cc00176f -r 4c7862cf1ba1 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Tue Mar 26 15:28:18 2019 +0300 +++ b/nginx/ngx_http_js_module.c Tue Mar 26 15:35:45 2019 +0300 @@ -138,6 +138,8 @@ static void ngx_http_js_clear_timer(njs_ static void ngx_http_js_timer_handler(ngx_event_t *ev); static void ngx_http_js_handle_event(ngx_http_request_t *r, njs_vm_event_t vm_event, njs_value_t *args, nxt_uint_t nargs); +static njs_ret_t ngx_http_js_string(njs_vm_t *vm, const njs_value_t *value, + nxt_str_t *str); static char *ngx_http_js_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); @@ -1205,17 +1207,17 @@ ngx_http_js_ext_return(njs_vm_t *vm, njs { nxt_str_t text; ngx_int_t status; - njs_value_t *value; ngx_http_js_ctx_t *ctx; ngx_http_request_t *r; + const njs_value_t *value; ngx_http_complex_value_t cv; - if (nargs < 2) { - njs_vm_error(vm, "too few arguments"); + r = njs_vm_external(vm, njs_arg(args, nargs, 0)); + if (nxt_slow_path(r == NULL)) { return NJS_ERROR; } - value = njs_argument(args, 1); + value = njs_arg(args, nargs, 1); if (!njs_value_is_valid_number(value)) { njs_vm_error(vm, "code is not a number"); return NJS_ERROR; @@ -1228,21 +1230,8 @@ ngx_http_js_ext_return(njs_vm_t *vm, njs return NJS_ERROR; } - if (nargs < 3) { - text.start = NULL; - text.length = 0; - - } else { - if (njs_vm_value_to_ext_string(vm, &text, njs_argument(args, 2), 0) - == NJS_ERROR) - { - njs_vm_error(vm, "failed to convert text"); - return NJS_ERROR; - } - } - - r = njs_vm_external(vm, njs_argument(args, 0)); - if (nxt_slow_path(r == NULL)) { + if (ngx_http_js_string(vm, njs_arg(args, nargs, 2), &text) != NJS_OK) { + njs_vm_error(vm, "failed to convert text"); return NJS_ERROR; } @@ -1277,21 +1266,14 @@ ngx_http_js_ext_internal_redirect(njs_vm ngx_http_js_ctx_t *ctx; ngx_http_request_t *r; - if (nargs < 2) { - njs_vm_error(vm, "too few arguments"); - return NJS_ERROR; - } - - r = njs_vm_external(vm, njs_argument(args, 0)); + r = njs_vm_external(vm, njs_arg(args, nargs, 0)); if (nxt_slow_path(r == NULL)) { return NJS_ERROR; } ctx = ngx_http_get_module_ctx(r, ngx_http_js_module); - if (njs_vm_value_to_ext_string(vm, &uri, njs_argument(args, 1), 0) - == NJS_ERROR) - { + if (ngx_http_js_string(vm, njs_arg(args, nargs, 1), &uri) != NJS_OK) { njs_vm_error(vm, "failed to convert uri arg"); return NJS_ERROR; } @@ -1707,10 +1689,11 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, { ngx_int_t rc; nxt_str_t uri_arg, args_arg, method_name, body_arg; - ngx_uint_t cb_index, method, n, has_body; - njs_value_t *arg2, *options, *value; + ngx_uint_t method, n, has_body; + njs_value_t *value; njs_function_t *callback; ngx_http_js_ctx_t *ctx; + const njs_value_t *arg, *options; ngx_http_request_t *r, *sr; ngx_http_request_body_t *rb; @@ -1739,12 +1722,7 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, static const nxt_str_t method_key = nxt_string("method"); static const nxt_str_t body_key = nxt_string("body"); - if (nargs < 2) { - njs_vm_error(vm, "too few arguments"); - return NJS_ERROR; - } - - r = njs_vm_external(vm, njs_argument(args, 0)); + r = njs_vm_external(vm, njs_arg(args, nargs, 0)); if (nxt_slow_path(r == NULL)) { return NJS_ERROR; } @@ -1757,51 +1735,47 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, return NJS_ERROR; } - if (njs_vm_value_to_ext_string(vm, &uri_arg, njs_argument(args, 1), 0) - == NJS_ERROR) - { + if (ngx_http_js_string(vm, njs_arg(args, nargs, 1), &uri_arg) != NJS_OK) { njs_vm_error(vm, "failed to convert uri arg"); return NJS_ERROR; } + if (uri_arg.length == 0) { + njs_vm_error(vm, "uri is empty"); + return NJS_ERROR; + } + options = NULL; + callback = NULL; method = 0; args_arg.length = 0; args_arg.start = NULL; has_body = 0; - if (nargs > 2 && !njs_value_is_function(njs_argument(args, 2))) { - arg2 = njs_argument(args, 2); - - if (njs_value_is_object(arg2)) { - options = arg2; - - } else if (njs_value_is_string(arg2)) { - if (njs_vm_value_to_ext_string(vm, &args_arg, arg2, 0) - == NJS_ERROR) - { - njs_vm_error(vm, "failed to convert args"); - return NJS_ERROR; - } - - } else { + arg = njs_arg(args, nargs, 2); + + if (njs_value_is_string(arg)) { + if (njs_vm_value_to_ext_string(vm, &args_arg, arg, 0) != NJS_OK) { njs_vm_error(vm, "failed to convert args"); return NJS_ERROR; } - cb_index = 3; - - } else { - cb_index = 2; + } else if (njs_value_is_function(arg)) { + callback = njs_value_function(arg); + + } else if (njs_value_is_object(arg)) { + options = arg; + + } else if (!njs_value_is_undefined(arg)) { + njs_vm_error(vm, "failed to convert args"); + return NJS_ERROR; } if (options != NULL) { value = njs_vm_object_prop(vm, options, &args_key); if (value != NULL) { - if (njs_vm_value_to_ext_string(vm, &args_arg, value, 0) - == NJS_ERROR) - { + if (ngx_http_js_string(vm, value, &args_arg) != NJS_OK) { njs_vm_error(vm, "failed to convert options.args"); return NJS_ERROR; } @@ -1809,9 +1783,7 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, value = njs_vm_object_prop(vm, options, &method_key); if (value != NULL) { - if (njs_vm_value_to_ext_string(vm, &method_name, value, 0) - == NJS_ERROR) - { + if (ngx_http_js_string(vm, value, &method_name) != NJS_OK) { njs_vm_error(vm, "failed to convert options.method"); return NJS_ERROR; } @@ -1838,9 +1810,7 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, value = njs_vm_object_prop(vm, options, &body_key); if (value != NULL) { - if (njs_vm_value_to_ext_string(vm, &body_arg, value, 0) - == NJS_ERROR) - { + if (ngx_http_js_string(vm, value, &body_arg) != NJS_OK) { njs_vm_error(vm, "failed to convert options.body"); return NJS_ERROR; } @@ -1849,15 +1819,15 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, } } - callback = NULL; - - if (cb_index < nargs) { - if (!njs_value_is_function(njs_argument(args, cb_index))) { + arg = njs_arg(args, nargs, 3); + + if (callback == NULL && !njs_value_is_undefined(arg)) { + if (!njs_value_is_function(arg)) { njs_vm_error(vm, "callback is not a function"); return NJS_ERROR; } else { - callback = njs_value_function(njs_argument(args, cb_index)); + callback = njs_value_function(arg); } } @@ -2174,6 +2144,23 @@ ngx_http_js_handle_event(ngx_http_reques } +static njs_ret_t +ngx_http_js_string(njs_vm_t *vm, const njs_value_t *value, nxt_str_t *str) +{ + if (!njs_value_is_null_or_undefined(value)) { + if (njs_vm_value_to_ext_string(vm, str, value, 0) == NJS_ERROR) { + return NJS_ERROR; + } + + } else { + str->start = NULL; + str->length = 0; + } + + return NJS_OK; +} + + static char * ngx_http_js_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { diff -r c2c8cc00176f -r 4c7862cf1ba1 nginx/ngx_stream_js_module.c --- a/nginx/ngx_stream_js_module.c Tue Mar 26 15:28:18 2019 +0300 +++ b/nginx/ngx_stream_js_module.c Tue Mar 26 15:35:45 2019 +0300 @@ -109,6 +109,8 @@ static void ngx_stream_js_clear_timer(nj static void ngx_stream_js_timer_handler(ngx_event_t *ev); static void ngx_stream_js_handle_event(ngx_stream_session_t *s, njs_vm_event_t vm_event, njs_value_t *args, nxt_uint_t nargs); +static njs_ret_t ngx_stream_js_string(njs_vm_t *vm, const njs_value_t *value, + nxt_str_t *str); static char *ngx_stream_js_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); @@ -930,8 +932,9 @@ ngx_stream_js_ext_set_status(njs_vm_t *v return NJS_ERROR; } - if (nargs > 1) { - code = njs_arg(args, nargs, 1); + code = njs_arg(args, nargs, 1); + + if (!njs_value_is_undefined(code)) { if (!njs_value_is_valid_number(code)) { njs_vm_error(vm, "code is not a number"); return NJS_ERROR; @@ -1132,9 +1135,7 @@ ngx_stream_js_ext_send(njs_vm_t *vm, njs return NJS_ERROR; } - if (njs_vm_value_to_ext_string(vm, &buffer, njs_arg(args, nargs, 1), 0) - == NJS_ERROR) - { + if (ngx_stream_js_string(vm, njs_arg(args, nargs, 1), &buffer) != NJS_OK) { njs_vm_error(vm, "failed to get buffer arg"); return NJS_ERROR; } @@ -1367,6 +1368,23 @@ ngx_stream_js_handle_event(ngx_stream_se } +static njs_ret_t +ngx_stream_js_string(njs_vm_t *vm, const njs_value_t *value, nxt_str_t *str) +{ + if (!njs_value_is_null_or_undefined(value)) { + if (njs_vm_value_to_ext_string(vm, str, value, 0) == NJS_ERROR) { + return NJS_ERROR; + } + + } else { + str->start = NULL; + str->length = 0; + } + + return NJS_OK; +} + + static char * ngx_stream_js_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { From xeioex at nginx.com Tue Mar 26 12:53:47 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 26 Mar 2019 12:53:47 +0000 Subject: [njs] Modules: added js_path directive. Message-ID: details: https://hg.nginx.org/njs/rev/2e3ab9dc1328 branches: changeset: 845:2e3ab9dc1328 user: Dmitry Volyntsev date: Tue Mar 26 15:52:53 2019 +0300 description: Modules: added js_path directive. diffstat: nginx/ngx_http_js_module.c | 43 ++++++++++++++++++++++++++++++++++++++++- nginx/ngx_stream_js_module.c | 45 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 83 insertions(+), 5 deletions(-) diffs (173 lines): diff -r 4c7862cf1ba1 -r 2e3ab9dc1328 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Tue Mar 26 15:35:45 2019 +0300 +++ b/nginx/ngx_http_js_module.c Tue Mar 26 15:52:53 2019 +0300 @@ -14,6 +14,7 @@ typedef struct { njs_vm_t *vm; + ngx_array_t *paths; const njs_extern_t *req_proto; } ngx_http_js_main_conf_t; @@ -161,6 +162,13 @@ static ngx_command_t ngx_http_js_comman 0, NULL }, + { ngx_string("js_path"), + NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_array_slot, + NGX_HTTP_MAIN_CONF_OFFSET, + offsetof(ngx_http_js_main_conf_t, paths), + NULL }, + { ngx_string("js_set"), NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE2, ngx_http_js_set, @@ -2170,9 +2178,10 @@ ngx_http_js_include(ngx_conf_t *cf, ngx_ u_char *start, *end; ssize_t n; ngx_fd_t fd; - ngx_str_t *value, file; + ngx_str_t *m, *value, file; nxt_int_t rc; - nxt_str_t text; + nxt_str_t text, path; + ngx_uint_t i; njs_vm_opt_t options; ngx_file_info_t fi; ngx_pool_cleanup_t *cln; @@ -2259,6 +2268,34 @@ ngx_http_js_include(ngx_conf_t *cf, ngx_ cln->handler = ngx_http_js_cleanup_vm; cln->data = jmcf->vm; + path.start = ngx_cycle->prefix.data; + path.length = ngx_cycle->prefix.len; + + rc = njs_vm_add_path(jmcf->vm, &path); + if (rc != NXT_OK) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "failed to add path"); + return NGX_CONF_ERROR; + } + + if (jmcf->paths != NGX_CONF_UNSET_PTR) { + m = jmcf->paths->elts; + + for (i = 0; i < jmcf->paths->nelts; i++) { + if (ngx_conf_full_name(cf->cycle, &m[i], 0) != NGX_OK) { + return NGX_CONF_ERROR; + } + + path.start = m[i].data; + path.length = m[i].len; + + rc = njs_vm_add_path(jmcf->vm, &path); + if (rc != NXT_OK) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "failed to add path"); + return NGX_CONF_ERROR; + } + } + } + jmcf->req_proto = njs_vm_external_prototype(jmcf->vm, &ngx_http_js_externals[0]); if (jmcf->req_proto == NULL) { @@ -2363,6 +2400,8 @@ ngx_http_js_create_main_conf(ngx_conf_t * conf->req_proto = NULL; */ + conf->paths = NGX_CONF_UNSET_PTR; + return conf; } diff -r 4c7862cf1ba1 -r 2e3ab9dc1328 nginx/ngx_stream_js_module.c --- a/nginx/ngx_stream_js_module.c Tue Mar 26 15:35:45 2019 +0300 +++ b/nginx/ngx_stream_js_module.c Tue Mar 26 15:52:53 2019 +0300 @@ -15,6 +15,7 @@ typedef struct { njs_vm_t *vm; + ngx_array_t *paths; const njs_extern_t *proto; } ngx_stream_js_main_conf_t; @@ -132,6 +133,13 @@ static ngx_command_t ngx_stream_js_comm 0, NULL }, + { ngx_string("js_path"), + NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_array_slot, + NGX_STREAM_MAIN_CONF_OFFSET, + offsetof(ngx_stream_js_main_conf_t, paths), + NULL }, + { ngx_string("js_set"), NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE2, ngx_stream_js_set, @@ -1394,9 +1402,10 @@ ngx_stream_js_include(ngx_conf_t *cf, ng u_char *start, *end; ssize_t n; ngx_fd_t fd; - ngx_str_t *value, file; + ngx_str_t *m, *value, file; nxt_int_t rc; - nxt_str_t text; + nxt_str_t text, path; + ngx_uint_t i; njs_vm_opt_t options; ngx_file_info_t fi; ngx_pool_cleanup_t *cln; @@ -1483,6 +1492,34 @@ ngx_stream_js_include(ngx_conf_t *cf, ng cln->handler = ngx_stream_js_cleanup_vm; cln->data = jmcf->vm; + path.start = ngx_cycle->prefix.data; + path.length = ngx_cycle->prefix.len; + + rc = njs_vm_add_path(jmcf->vm, &path); + if (rc != NXT_OK) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "failed to add path"); + return NGX_CONF_ERROR; + } + + if (jmcf->paths != NGX_CONF_UNSET_PTR) { + m = jmcf->paths->elts; + + for (i = 0; i < jmcf->paths->nelts; i++) { + if (ngx_conf_full_name(cf->cycle, &m[i], 0) != NGX_OK) { + return NGX_CONF_ERROR; + } + + path.start = m[i].data; + path.length = m[i].len; + + rc = njs_vm_add_path(jmcf->vm, &path); + if (rc != NXT_OK) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "failed to add path"); + return NGX_CONF_ERROR; + } + } + } + jmcf->proto = njs_vm_external_prototype(jmcf->vm, &ngx_stream_js_externals[0]); @@ -1552,7 +1589,7 @@ ngx_stream_js_set(ngx_conf_t *cf, ngx_co static void * ngx_stream_js_create_main_conf(ngx_conf_t *cf) { - ngx_stream_js_srv_conf_t *conf; + ngx_stream_js_main_conf_t *conf; conf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_js_main_conf_t)); if (conf == NULL) { @@ -1566,6 +1603,8 @@ ngx_stream_js_create_main_conf(ngx_conf_ * conf->proto = NULL; */ + conf->paths = NGX_CONF_UNSET_PTR; + return conf; } From pluknet at nginx.com Tue Mar 26 13:50:23 2019 From: pluknet at nginx.com (Sergey Kandaurov) Date: Tue, 26 Mar 2019 16:50:23 +0300 Subject: [PATCH] Remove memory leak in ngx_event_openssl.c In-Reply-To: References: Message-ID: <4F3100E0-980B-444A-8949-B2ABA0CBCAE6@nginx.com> > On 26 Mar 2019, at 10:02, Nikolay Morozov wrote: > > # HG changeset patch > # User Nikolay Morozov > # Date 1553582037 -10800 > # Tue Mar 26 09:33:57 2019 +0300 > # Node ID e3d5aaa0f3df9e0d60e384e78e40f6fb7bd4524f > # Parent d9c3917c7f901ac2a0f4a483f3229a63b51840c5 > Remove memory leak in ngx_event_openssl.c > > If X509_get_issuer_name() or X509_get_subject_name() > return an error, certificate leaks. > > diff -r d9c3917c7f90 -r e3d5aaa0f3df src/event/ngx_event_openssl.c > --- a/src/event/ngx_event_openssl.c Wed Mar 06 20:46:09 2019 +0300 > +++ b/src/event/ngx_event_openssl.c Tue Mar 26 09:33:57 2019 +0300 > @@ -4622,6 +4622,7 @@ > > name = X509_get_subject_name(cert); > if (name == NULL) { > + X509_free(cert); > return NGX_ERROR; > } > > @@ -4673,6 +4674,7 @@ > > name = X509_get_issuer_name(cert); > if (name == NULL) { > + X509_free(cert); > return NGX_ERROR; > } > Hello. During an internal conversation in Nginx we came to the conclusion that such leaks are not possible in practice. Here is the commit log message I intend to proceed with. SSL: missing free calls in $ssl_client_s_dn and $ssl_client_i_dn. If X509_get_issuer_name() or X509_get_subject_name() returned NULL, this could lead to a certificate reference leak. It cannot happen in practice though, since each function returns an internal pointer to a mandatory subfield of the certificate successfully decoded by d2i_X509() during certificate message processing (closes #1751). > ????????? ? ?????????????????? > > ?????? ??????????? ?????? ? ????? ?????????? ? ???? ???????? ????????????????? ? ????????????? ????????????? ??? ????????. ???? ?? ?? ????????? ????????? ??????? ??????, ??????????, ????????? ?????????? ???????????, ?? ??????????? ?????????? ?????? ?????, ?? ??????????? ??? ? ?????-???? ?????, ?? ??????? ? ?? ????????? ?????????? ????? ????????. Please note that nginx-devel@ is the English speaking mailing list. Note that posting patches to a public mailing list with such a disclaimer might not be a good idea. If you cannot remove it, please make sure to add an explicit comment that you understand that you are posting to a public mailing list, and you've read the http://nginx.org/en/docs/contributing_changes.html article. In particular, that you agree with the "License" part. Thank you. -- Sergey Kandaurov From xeioex at nginx.com Tue Mar 26 13:58:53 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 26 Mar 2019 13:58:53 +0000 Subject: [njs] Version 0.3.0. Message-ID: details: https://hg.nginx.org/njs/rev/1935ab4643fd branches: changeset: 846:1935ab4643fd user: Dmitry Volyntsev date: Tue Mar 26 16:56:32 2019 +0300 description: Version 0.3.0. diffstat: CHANGES | 36 ++++++++++++++++++++++++++++++++++++ 1 files changed, 36 insertions(+), 0 deletions(-) diffs (43 lines): diff -r 2e3ab9dc1328 -r 1935ab4643fd CHANGES --- a/CHANGES Tue Mar 26 15:52:53 2019 +0300 +++ b/CHANGES Tue Mar 26 16:56:32 2019 +0300 @@ -1,3 +1,39 @@ + +Changes with njs 0.3.0 26 Mar 2019 + + nginx modules: + + *) Feature: added js_path directive. + + *) Change: returning undefined value instead of empty strings + for absent properties in the following objects: r.args, + r.headersIn, r.headersOut, r.variables, s.variables. + + *) Change: returning undefined value instead of throwing an + exception for r.requestBody when request body is unavailable. + + *) Bugfix: fixed crash while iterating over r.args when a value is + absent in a key-value pair. + + Core: + + *) Feature: added initial ES6 modules support. Default import and + default export statements are supported. + Thanks to ??? (Hong Zhi Dao). + + *) Feature: added Object.prototype.propertyIsEnumerable(). + + *) Feature: reporting file name and function name in disassembler + output. + + *) Bugfix: fixed function redeclarations in interactive shell. + Thanks to ??? (Hong Zhi Dao). + + *) Bugfix: fixed RegExp literals parsing. + + *) Bugfix: fixed setting length of UTF8 string in fs.readFileSync(). + + *) Bugfix: fixed nxt_file_dirname() for paths with no dir component. Changes with njs 0.2.8 26 Feb 2019 From xeioex at nginx.com Tue Mar 26 13:58:54 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 26 Mar 2019 13:58:54 +0000 Subject: [njs] Added tag 0.3.0 for changeset 1935ab4643fd Message-ID: details: https://hg.nginx.org/njs/rev/5dae5875b22e branches: changeset: 847:5dae5875b22e user: Dmitry Volyntsev date: Tue Mar 26 16:58:43 2019 +0300 description: Added tag 0.3.0 for changeset 1935ab4643fd diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff -r 1935ab4643fd -r 5dae5875b22e .hgtags --- a/.hgtags Tue Mar 26 16:56:32 2019 +0300 +++ b/.hgtags Tue Mar 26 16:58:43 2019 +0300 @@ -23,3 +23,4 @@ 3315f6aa6000ce6d2dbc74c73660becf4178a549 0709b8b4f11ebec95dd4f72d5bb38044682f77e6 0.2.6 4624ba4f6497a3d10fe1c0a6f45fb453579502f5 0.2.7 ee190d3ace005f8eb063d4763b578f44d3028c68 0.2.8 +1935ab4643fdaec5b4a8c36070f4d2cb8e3799d7 0.3.0 From mdounin at mdounin.ru Tue Mar 26 14:10:07 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 26 Mar 2019 14:10:07 +0000 Subject: [nginx] nginx-1.15.10-RELEASE Message-ID: details: https://hg.nginx.org/nginx/rev/75f5c7f62841 branches: changeset: 7481:75f5c7f62841 user: Maxim Dounin date: Tue Mar 26 17:06:54 2019 +0300 description: nginx-1.15.10-RELEASE diffstat: docs/xml/nginx/changes.xml | 60 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 60 insertions(+), 0 deletions(-) diffs (70 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,66 @@ + + + + +?????? ??? ????????????? ????? ????? ? ????????? listen +nginx ??????? listen-?????? ??? ???? ???????, +??????????????? ????? ????? +(????? ????????????? ?????? ?????? ?????). + + +when using a hostname in the "listen" directive +nginx now creates listening sockets +for all addresses the hostname resolves to +(previously, only the first address was used). + + + + + +????????? ?????? ? ????????? listen. + + +port ranges in the "listen" directive. + + + + + +??????????? ???????? SSL-???????????? ? ????????? ?????? ?? ??????????. + + +loading of SSL certificates and secret keys from variables. + + + + + +?????????? $ssl_server_name ????? ???? ?????? +??? ????????????? OpenSSL 1.1.1. + + +the $ssl_server_name variable might be empty +when using OpenSSL 1.1.1. + + + + + +nginx/Windows ?? ????????? ? Visual Studio 2015 ? ?????; +?????? ????????? ? 1.15.9. + + +nginx/Windows could not be built with Visual Studio 2015 or newer; +the bug had appeared in 1.15.9. + + + + + + From mdounin at mdounin.ru Tue Mar 26 14:10:09 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 26 Mar 2019 14:10:09 +0000 Subject: [nginx] release-1.15.10 tag Message-ID: details: https://hg.nginx.org/nginx/rev/44df73d0fa71 branches: changeset: 7482:44df73d0fa71 user: Maxim Dounin date: Tue Mar 26 17:06:55 2019 +0300 description: release-1.15.10 tag diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -435,3 +435,4 @@ 2351853ce6867b6166823bdf94333c0a76633c0a 051a039ce1c7e09144de4a4846669ec7116cecea release-1.15.7 ee551e3f6dba336c0d875e266d7d55385f379b42 release-1.15.8 d2fd76709909767fc727a5b4affcf1dc9ca488a7 release-1.15.9 +75f5c7f628411c79c7044102049f7ab4f7a246e7 release-1.15.10 From n.morozov at securitycode.ru Tue Mar 26 15:09:12 2019 From: n.morozov at securitycode.ru (Nikolay Morozov) Date: Tue, 26 Mar 2019 18:09:12 +0300 Subject: [PATCH] SSL: missing free calls in $ssl_client_s_dn and $ssl_client_i_dn Message-ID: <419a691bbd0601b0bba5.1553612952@localhost> # HG changeset patch # User Nikolay Morozov # Date 1553582037 -10800 # Tue Mar 26 09:33:57 2019 +0300 # Node ID 419a691bbd0601b0bba5068026b57d0b9a5c25e8 # Parent d9c3917c7f901ac2a0f4a483f3229a63b51840c5 SSL: missing free calls in $ssl_client_s_dn and $ssl_client_i_dn. If X509_get_issuer_name() or X509_get_subject_name() returned NULL, this could lead to a certificate reference leak. It cannot happen in practice though, since each function returns an internal pointer to a mandatory subfield of the certificate successfully decoded by d2i_X509() during certificate message processing (closes #1751). diff -r d9c3917c7f90 -r 419a691bbd06 src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Wed Mar 06 20:46:09 2019 +0300 +++ b/src/event/ngx_event_openssl.c Tue Mar 26 09:33:57 2019 +0300 @@ -4622,6 +4622,7 @@ name = X509_get_subject_name(cert); if (name == NULL) { + X509_free(cert); return NGX_ERROR; } @@ -4673,6 +4674,7 @@ name = X509_get_issuer_name(cert); if (name == NULL) { + X509_free(cert); return NGX_ERROR; } ????????? ? ?????????????????? ?????? ??????????? ?????? ? ????? ?????????? ? ???? ???????? ????????????????? ? ????????????? ????????????? ??? ????????. ???? ?? ?? ????????? ????????? ??????? ??????, ??????????, ????????? ?????????? ???????????, ?? ??????????? ?????????? ?????? ?????, ?? ??????????? ??? ? ?????-???? ?????, ?? ??????? ? ?? ????????? ?????????? ????? ????????. From pluknet at nginx.com Tue Mar 26 15:31:35 2019 From: pluknet at nginx.com (Sergey Kandaurov) Date: Tue, 26 Mar 2019 15:31:35 +0000 Subject: [nginx] Version bump. Message-ID: details: https://hg.nginx.org/nginx/rev/1144c122e370 branches: changeset: 7483:1144c122e370 user: Sergey Kandaurov date: Tue Mar 26 18:25:08 2019 +0300 description: Version bump. diffstat: src/core/nginx.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff -r 44df73d0fa71 -r 1144c122e370 src/core/nginx.h --- a/src/core/nginx.h Tue Mar 26 17:06:55 2019 +0300 +++ b/src/core/nginx.h Tue Mar 26 18:25:08 2019 +0300 @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1015010 -#define NGINX_VERSION "1.15.10" +#define nginx_version 1015011 +#define NGINX_VERSION "1.15.11" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD From pluknet at nginx.com Tue Mar 26 15:31:37 2019 From: pluknet at nginx.com (Sergey Kandaurov) Date: Tue, 26 Mar 2019 15:31:37 +0000 Subject: [nginx] SSL: missing free calls in $ssl_client_s_dn and $ssl_client_i_dn. Message-ID: details: https://hg.nginx.org/nginx/rev/65074e13f171 branches: changeset: 7484:65074e13f171 user: Nikolay Morozov date: Tue Mar 26 09:33:57 2019 +0300 description: SSL: missing free calls in $ssl_client_s_dn and $ssl_client_i_dn. If X509_get_issuer_name() or X509_get_subject_name() returned NULL, this could lead to a certificate reference leak. It cannot happen in practice though, since each function returns an internal pointer to a mandatory subfield of the certificate successfully decoded by d2i_X509() during certificate message processing (closes #1751). diffstat: src/event/ngx_event_openssl.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diffs (19 lines): diff -r 1144c122e370 -r 65074e13f171 src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Tue Mar 26 18:25:08 2019 +0300 +++ b/src/event/ngx_event_openssl.c Tue Mar 26 09:33:57 2019 +0300 @@ -4622,6 +4622,7 @@ ngx_ssl_get_subject_dn(ngx_connection_t name = X509_get_subject_name(cert); if (name == NULL) { + X509_free(cert); return NGX_ERROR; } @@ -4673,6 +4674,7 @@ ngx_ssl_get_issuer_dn(ngx_connection_t * name = X509_get_issuer_name(cert); if (name == NULL) { + X509_free(cert); return NGX_ERROR; } From xeioex at nginx.com Tue Mar 26 20:07:08 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 26 Mar 2019 20:07:08 +0000 Subject: [njs] Version bump. Message-ID: details: https://hg.nginx.org/njs/rev/f4a15ccf03c9 branches: changeset: 848:f4a15ccf03c9 user: Dmitry Volyntsev date: Tue Mar 26 23:06:46 2019 +0300 description: Version bump. diffstat: njs/njs.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 5dae5875b22e -r f4a15ccf03c9 njs/njs.h --- a/njs/njs.h Tue Mar 26 16:58:43 2019 +0300 +++ b/njs/njs.h Tue Mar 26 23:06:46 2019 +0300 @@ -11,7 +11,7 @@ #include -#define NJS_VERSION "0.3.0" +#define NJS_VERSION "0.3.1" #include From xeioex at nginx.com Tue Mar 26 20:07:09 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 26 Mar 2019 20:07:09 +0000 Subject: [njs] Added Object.getOwnPropertyNames(). Message-ID: details: https://hg.nginx.org/njs/rev/5ef3dbe30d2d branches: changeset: 849:5ef3dbe30d2d user: Artem S. Povalyukhin date: Tue Mar 26 08:04:02 2019 +0300 description: Added Object.getOwnPropertyNames(). This closes #4 issue on Github. diffstat: njs/njs_json.c | 4 +- njs/njs_object.c | 105 +++++++++++++++++++++++++++++++++++++++++++--- njs/njs_object.h | 4 +- njs/test/njs_unit_test.c | 35 +++++++++++++++ 4 files changed, 136 insertions(+), 12 deletions(-) diffs (309 lines): diff -r f4a15ccf03c9 -r 5ef3dbe30d2d njs/njs_json.c --- a/njs/njs_json.c Tue Mar 26 23:06:46 2019 +0300 +++ b/njs/njs_json.c Tue Mar 26 08:04:02 2019 +0300 @@ -1099,7 +1099,7 @@ njs_json_push_parse_state(njs_vm_t *vm, } else { state->type = NJS_JSON_OBJECT_START; state->prop_value = NULL; - state->keys = njs_object_enumerate(vm, value, NJS_ENUM_KEYS); + state->keys = njs_object_enumerate(vm, value, NJS_ENUM_KEYS, 0); if (state->keys == NULL) { return NULL; } @@ -1677,7 +1677,7 @@ njs_json_push_stringify_state(njs_vm_t * state->keys = njs_extern_keys_array(vm, value->external.proto); } else { - state->keys = njs_object_enumerate(vm, value, NJS_ENUM_KEYS); + state->keys = njs_object_enumerate(vm, value, NJS_ENUM_KEYS, 0); } if (state->keys == NULL) { diff -r f4a15ccf03c9 -r 5ef3dbe30d2d njs/njs_object.c --- a/njs/njs_object.c Tue Mar 26 23:06:46 2019 +0300 +++ b/njs/njs_object.c Tue Mar 26 08:04:02 2019 +0300 @@ -417,7 +417,7 @@ njs_object_property_query(njs_vm_t *vm, do { pq->prototype = proto; - /* length and other shared properties should be Own property */ + /* TODO: length should be Own property */ if (nxt_fast_path(!pq->own || proto == object)) { ret = nxt_lvlhsh_find(&proto->hash, &pq->lhq); @@ -879,7 +879,7 @@ njs_object_keys(njs_vm_t *vm, njs_value_ return NXT_ERROR; } - keys = njs_object_enumerate(vm, value, NJS_ENUM_KEYS); + keys = njs_object_enumerate(vm, value, NJS_ENUM_KEYS, 0); if (keys == NULL) { return NXT_ERROR; } @@ -908,7 +908,7 @@ njs_object_values(njs_vm_t *vm, njs_valu return NXT_ERROR; } - array = njs_object_enumerate(vm, value, NJS_ENUM_VALUES); + array = njs_object_enumerate(vm, value, NJS_ENUM_VALUES, 0); if (array == NULL) { return NXT_ERROR; } @@ -937,7 +937,7 @@ njs_object_entries(njs_vm_t *vm, njs_val return NXT_ERROR; } - array = njs_object_enumerate(vm, value, NJS_ENUM_BOTH); + array = njs_object_enumerate(vm, value, NJS_ENUM_BOTH, 0); if (array == NULL) { return NXT_ERROR; } @@ -952,8 +952,9 @@ njs_object_entries(njs_vm_t *vm, njs_val njs_array_t * njs_object_enumerate(njs_vm_t *vm, const njs_value_t *value, - njs_object_enum_t kind) + njs_object_enum_t kind, nxt_bool_t all) { + nxt_bool_t exotic_length; u_char *dst; uint32_t i, length, size, items_length, properties; njs_value_t *string, *item; @@ -964,6 +965,12 @@ njs_object_enumerate(njs_vm_t *vm, const njs_string_prop_t string_prop; nxt_lvlhsh_each_t lhe; + static const njs_value_t njs_string_length = njs_string("length"); + + /* TODO: "length" is in a shared_hash. */ + + exotic_length = 0; + array = NULL; length = 0; items_length = 0; @@ -979,6 +986,8 @@ njs_object_enumerate(njs_vm_t *vm, const } } + exotic_length = all; + break; case NJS_STRING: @@ -992,8 +1001,15 @@ njs_object_enumerate(njs_vm_t *vm, const length = njs_string_prop(&string_prop, string); items_length += length; + exotic_length = all; + break; + case NJS_FUNCTION: + exotic_length = all && (value->data.u.function->native == 0); + + /* Fall through. */ + default: break; } @@ -1013,7 +1029,22 @@ njs_object_enumerate(njs_vm_t *vm, const break; } - if (prop->type != NJS_WHITEOUT && prop->enumerable) { + if (prop->type != NJS_WHITEOUT && (prop->enumerable || all)) { + properties++; + } + } + + if (nxt_slow_path(all)) { + nxt_lvlhsh_each_init(&lhe, &njs_object_hash_proto); + hash = &value->data.u.object->shared_hash; + + for ( ;; ) { + prop = nxt_lvlhsh_each(hash, &lhe); + + if (prop == NULL) { + break; + } + properties++; } } @@ -1021,7 +1052,7 @@ njs_object_enumerate(njs_vm_t *vm, const items_length += properties; } - items = njs_array_alloc(vm, items_length, NJS_ARRAY_SPARE); + items = njs_array_alloc(vm, items_length + exotic_length, NJS_ARRAY_SPARE); if (nxt_slow_path(items == NULL)) { return NULL; } @@ -1179,12 +1210,17 @@ njs_object_enumerate(njs_vm_t *vm, const } } + if (nxt_slow_path(exotic_length != 0)) { + *item++ = njs_string_length; + } + if (nxt_fast_path(properties != 0)) { nxt_lvlhsh_each_init(&lhe, &njs_object_hash_proto); switch (kind) { case NJS_ENUM_KEYS: + hash = &value->data.u.object->hash; for ( ;; ) { prop = nxt_lvlhsh_each(hash, &lhe); @@ -1192,7 +1228,22 @@ njs_object_enumerate(njs_vm_t *vm, const break; } - if (prop->type != NJS_WHITEOUT && prop->enumerable) { + if (prop->type != NJS_WHITEOUT && (prop->enumerable || all)) { + njs_string_copy(item++, &prop->name); + } + } + + if (nxt_slow_path(all)) { + nxt_lvlhsh_each_init(&lhe, &njs_object_hash_proto); + hash = &value->data.u.object->shared_hash; + + for ( ;; ) { + prop = nxt_lvlhsh_each(hash, &lhe); + + if (prop == NULL) { + break; + } + njs_string_copy(item++, &prop->name); } } @@ -1200,6 +1251,7 @@ njs_object_enumerate(njs_vm_t *vm, const break; case NJS_ENUM_VALUES: + hash = &value->data.u.object->hash; for ( ;; ) { prop = nxt_lvlhsh_each(hash, &lhe); @@ -1721,6 +1773,35 @@ njs_object_get_own_property_descriptor(n static njs_ret_t +njs_object_get_own_property_names(njs_vm_t *vm, njs_value_t *args, + nxt_uint_t nargs, njs_index_t unused) +{ + njs_array_t *names; + const njs_value_t *value; + + value = njs_arg(args, nargs, 1); + + if (njs_is_null_or_undefined(value)) { + njs_type_error(vm, "cannot convert %s argument to object", + njs_type_string(value->type)); + + return NXT_ERROR; + } + + names = njs_object_enumerate(vm, value, NJS_ENUM_KEYS, 1); + if (names == NULL) { + return NXT_ERROR; + } + + vm->retval.data.u.array = names; + vm->retval.type = NJS_ARRAY; + vm->retval.data.truth = 1; + + return NXT_OK; +} + + +static njs_ret_t njs_object_get_prototype_of(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) { @@ -2152,6 +2233,14 @@ static const njs_object_prop_t njs_obje NJS_STRING_ARG), }, + /* Object.getOwnPropertyNames(). */ + { + .type = NJS_METHOD, + .name = njs_long_string("getOwnPropertyNames"), + .value = njs_native_function(njs_object_get_own_property_names, 0, + NJS_SKIP_ARG, NJS_OBJECT_ARG), + }, + /* Object.getPrototypeOf(). */ { .type = NJS_METHOD, diff -r f4a15ccf03c9 -r 5ef3dbe30d2d njs/njs_object.h --- a/njs/njs_object.h Tue Mar 26 23:06:46 2019 +0300 +++ b/njs/njs_object.h Tue Mar 26 08:04:02 2019 +0300 @@ -18,7 +18,7 @@ typedef enum { typedef enum { - NJS_ENUM_KEYS = 0, + NJS_ENUM_KEYS, NJS_ENUM_VALUES, NJS_ENUM_BOTH, } njs_object_enum_t; @@ -87,7 +87,7 @@ njs_object_t *njs_object_value_copy(njs_ njs_object_t *njs_object_value_alloc(njs_vm_t *vm, const njs_value_t *value, nxt_uint_t type); njs_array_t *njs_object_enumerate(njs_vm_t *vm, const njs_value_t *value, - njs_object_enum_t kind); + njs_object_enum_t kind, nxt_bool_t all); njs_ret_t njs_value_property(njs_vm_t *vm, njs_value_t *value, const njs_value_t *property, njs_value_t *retval); njs_object_prop_t *njs_object_property(njs_vm_t *vm, const njs_object_t *obj, diff -r f4a15ccf03c9 -r 5ef3dbe30d2d njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Tue Mar 26 23:06:46 2019 +0300 +++ b/njs/test/njs_unit_test.c Tue Mar 26 08:04:02 2019 +0300 @@ -8673,6 +8673,41 @@ static njs_unit_test_t njs_test[] = { nxt_string("var o = {}; o[void 0] = 'a'; Object.getOwnPropertyDescriptor(o, undefined).value"), nxt_string("a") }, + { nxt_string("Object.getOwnPropertyNames()"), + nxt_string("TypeError: cannot convert undefined argument to object") }, + + { nxt_string("Array.isArray(Object.getOwnPropertyNames({}))"), + nxt_string("true") }, + + { nxt_string("Object.getOwnPropertyNames({a:1, b:1, c:1})"), + nxt_string("a,b,c") }, + + { nxt_string("Object.getOwnPropertyNames(Object.defineProperty({a:1}, 'b', {}))"), + nxt_string("a,b") }, + + { nxt_string("Object.getOwnPropertyNames(Object.defineProperty([], 'b', {}))"), + nxt_string("length,b") }, + + { nxt_string("Object.getOwnPropertyNames(Object.defineProperty(new String(), 'b', {}))"), + nxt_string("length,b") }, + + { nxt_string("Object.getOwnPropertyNames([1,2,3])"), + nxt_string("0,1,2,length") }, + + { nxt_string("Object.getOwnPropertyNames('abc')"), + nxt_string("0,1,2,length") }, + + { nxt_string("Object.getOwnPropertyNames(function() {})"), + nxt_string("length,prototype") }, + + { nxt_string("Object.getOwnPropertyNames(Array)"), + nxt_string("name,length,prototype,isArray,of") }, + +#if 0 + { nxt_string("Object.getOwnPropertyNames(Array.isArray)"), + nxt_string("length") }, +#endif + { nxt_string("Object.defineProperty(Object.freeze({}), 'b', {})"), nxt_string("TypeError: object is not extensible") }, From xeioex at nginx.com Wed Mar 27 18:11:01 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 27 Mar 2019 18:11:01 +0000 Subject: [njs] Adding const qualifier njs_string_prop(). Message-ID: details: https://hg.nginx.org/njs/rev/4139cb5a7412 branches: changeset: 851:4139cb5a7412 user: Dmitry Volyntsev date: Wed Mar 27 21:00:18 2019 +0300 description: Adding const qualifier njs_string_prop(). diffstat: njs/njs_string.c | 6 +++--- njs/njs_string.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diffs (38 lines): diff -r ab2264c8f37f -r 4139cb5a7412 njs/njs_string.c --- a/njs/njs_string.c Mon Apr 16 19:28:07 2018 +0300 +++ b/njs/njs_string.c Wed Mar 27 21:00:18 2019 +0300 @@ -511,7 +511,7 @@ njs_string_validate(njs_vm_t *vm, njs_st nxt_noinline size_t -njs_string_prop(njs_string_prop_t *string, njs_value_t *value) +njs_string_prop(njs_string_prop_t *string, const njs_value_t *value) { size_t size; uintptr_t length; @@ -519,11 +519,11 @@ njs_string_prop(njs_string_prop_t *strin size = value->short_string.size; if (size != NJS_STRING_LONG) { - string->start = value->short_string.start; + string->start = (u_char *) value->short_string.start; length = value->short_string.length; } else { - string->start = value->long_string.data->start; + string->start = (u_char *) value->long_string.data->start; size = value->long_string.size; length = value->long_string.data->length; } diff -r ab2264c8f37f -r 4139cb5a7412 njs/njs_string.h --- a/njs/njs_string.h Mon Apr 16 19:28:07 2018 +0300 +++ b/njs/njs_string.h Wed Mar 27 21:00:18 2019 +0300 @@ -144,7 +144,7 @@ void njs_string_copy(njs_value_t *dst, n njs_ret_t njs_string_validate(njs_vm_t *vm, njs_string_prop_t *string, njs_value_t *value); nxt_noinline size_t njs_string_prop(njs_string_prop_t *string, - njs_value_t *value); + const njs_value_t *value); njs_ret_t njs_string_constructor(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); nxt_bool_t njs_string_eq(const njs_value_t *val1, const njs_value_t *val2); From xeioex at nginx.com Wed Mar 27 18:11:01 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 27 Mar 2019 18:11:01 +0000 Subject: [njs] Added njs_vm_value(). Message-ID: details: https://hg.nginx.org/njs/rev/ab2264c8f37f branches: changeset: 850:ab2264c8f37f user: Dmitry Volyntsev date: Mon Apr 16 19:28:07 2018 +0300 description: Added njs_vm_value(). diffstat: njs/njs.h | 3 ++- njs/njs_variable.c | 27 +++++++++++++++++++-------- 2 files changed, 21 insertions(+), 9 deletions(-) diffs (60 lines): diff -r 5ef3dbe30d2d -r ab2264c8f37f njs/njs.h --- a/njs/njs.h Tue Mar 26 08:04:02 2019 +0300 +++ b/njs/njs.h Mon Apr 16 19:28:07 2018 +0300 @@ -229,7 +229,8 @@ NXT_EXPORT njs_external_ptr_t njs_vm_ext NXT_EXPORT void njs_disassembler(njs_vm_t *vm); NXT_EXPORT nxt_array_t *njs_vm_completions(njs_vm_t *vm, nxt_str_t *expression); -NXT_EXPORT njs_function_t *njs_vm_function(njs_vm_t *vm, nxt_str_t *name); +NXT_EXPORT const njs_value_t *njs_vm_value(njs_vm_t *vm, const nxt_str_t *name); +NXT_EXPORT njs_function_t *njs_vm_function(njs_vm_t *vm, const nxt_str_t *name); 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); diff -r 5ef3dbe30d2d -r ab2264c8f37f njs/njs_variable.c --- a/njs/njs_variable.c Tue Mar 26 08:04:02 2019 +0300 +++ b/njs/njs_variable.c Mon Apr 16 19:28:07 2018 +0300 @@ -598,24 +598,35 @@ njs_name_copy(njs_vm_t *vm, nxt_str_t *d } -njs_function_t * -njs_vm_function(njs_vm_t *vm, nxt_str_t *name) +const njs_value_t * +njs_vm_value(njs_vm_t *vm, const nxt_str_t *name) { - njs_value_t *value; - njs_variable_t *var; nxt_lvlhsh_query_t lhq; lhq.key_hash = nxt_djb_hash(name->start, name->length); lhq.key = *name; lhq.proto = &njs_variables_hash_proto; - if (nxt_slow_path(nxt_lvlhsh_find(&vm->variables_hash, &lhq) != NXT_OK)) { - return NULL; + if (nxt_lvlhsh_find(&vm->variables_hash, &lhq) == NXT_OK) { + return njs_vmcode_operand(vm, ((njs_variable_t *) lhq.value)->index); + } + + lhq.proto = &njs_extern_value_hash_proto; + + if (nxt_lvlhsh_find(&vm->externals_hash, &lhq) == NXT_OK) { + return &((njs_extern_value_t *) lhq.value)->value; } - var = lhq.value; + return &njs_value_undefined; +} + - value = njs_global_variable_value(vm, var); +njs_function_t * +njs_vm_function(njs_vm_t *vm, const nxt_str_t *name) +{ + const njs_value_t *value; + + value = njs_vm_value(vm, name); if (njs_is_function(value)) { return value->data.u.function; From xeioex at nginx.com Wed Mar 27 18:11:01 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 27 Mar 2019 18:11:01 +0000 Subject: [njs] Improved working with arguments in JSON methods. Message-ID: details: https://hg.nginx.org/njs/rev/27347fbb3d0a branches: changeset: 852:27347fbb3d0a user: Dmitry Volyntsev date: Wed Mar 27 21:00:19 2019 +0300 description: Improved working with arguments in JSON methods. diffstat: njs/njs_json.c | 59 ++++++++++++++++++++++++++++++--------------------------- 1 files changed, 31 insertions(+), 28 deletions(-) diffs (167 lines): diff -r 4139cb5a7412 -r 27347fbb3d0a njs/njs_json.c --- a/njs/njs_json.c Wed Mar 27 21:00:18 2019 +0300 +++ b/njs/njs_json.c Wed Mar 27 21:00:19 2019 +0300 @@ -108,7 +108,7 @@ static const u_char *njs_json_skip_space const u_char *end); static njs_ret_t njs_json_parse_continuation(njs_vm_t *vm, - njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); + njs_value_t *args, nxt_uint_t unused, njs_index_t unused2); static njs_ret_t njs_json_parse_continuation_apply(njs_vm_t *vm, njs_json_parse_t *parse); static njs_json_state_t *njs_json_push_parse_state(njs_vm_t *vm, @@ -118,7 +118,7 @@ static void njs_json_parse_exception(njs 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); + njs_value_t *args, nxt_uint_t unused, njs_index_t unused2); static njs_function_t *njs_object_to_json_function(njs_vm_t *vm, njs_value_t *value); static njs_ret_t njs_json_stringify_to_json(njs_vm_t *vm, @@ -140,7 +140,7 @@ static nxt_int_t njs_json_append_string( static nxt_int_t njs_json_append_number(njs_json_stringify_t *stringify, const njs_value_t *value); -static njs_value_t *njs_json_wrap_value(njs_vm_t *vm, njs_value_t *value); +static njs_value_t *njs_json_wrap_value(njs_vm_t *vm, const njs_value_t *value); #define NJS_JSON_BUF_MIN_SIZE 128 @@ -163,7 +163,8 @@ static njs_ret_t njs_json_parse(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) { - njs_value_t arg, *value, *wrapper; + njs_value_t *value, *wrapper; + const njs_value_t *text, *reviver; const u_char *p, *end; njs_json_parse_t *parse; njs_string_prop_t string; @@ -175,13 +176,13 @@ njs_json_parse(njs_vm_t *vm, njs_value_t return NXT_ERROR; } - if (nargs < 2) { - arg = njs_string_undefined; - } else { - arg = args[1]; + text = njs_arg(args, nargs, 1); + + if (njs_is_undefined(text)) { + text = &njs_string_undefined; } - (void) njs_string_prop(&string, &arg); + (void) njs_string_prop(&string, text); p = string.start; end = p + string.size; @@ -209,7 +210,9 @@ njs_json_parse(njs_vm_t *vm, njs_value_t return NXT_ERROR; } - if (nargs >= 3 && njs_is_function(&args[2]) && njs_is_object(value)) { + reviver = njs_arg(args, nargs, 2); + + if (njs_is_function(reviver) && njs_is_object(value)) { wrapper = njs_json_wrap_value(vm, value); if (nxt_slow_path(wrapper == NULL)) { goto memory_error; @@ -217,7 +220,7 @@ njs_json_parse(njs_vm_t *vm, njs_value_t parse = njs_vm_continuation(vm); parse->u.cont.function = njs_json_parse_continuation; - parse->function = args[2].data.u.function; + parse->function = reviver->data.u.function; if (nxt_array_init(&parse->stack, NULL, 4, sizeof(njs_json_state_t), &njs_array_mem_proto, vm->mem_pool) @@ -253,13 +256,9 @@ njs_json_stringify(njs_vm_t *vm, njs_val nxt_int_t i; njs_ret_t ret; njs_value_t *wrapper; + const njs_value_t *replacer, *space; njs_json_stringify_t *stringify; - if (nargs < 2) { - vm->retval = njs_value_undefined; - return NXT_OK; - } - stringify = njs_vm_continuation(vm); stringify->vm = vm; stringify->pool = vm->mem_pool; @@ -267,9 +266,11 @@ njs_json_stringify(njs_vm_t *vm, njs_val stringify->nodes = NULL; stringify->last = NULL; - if (nargs >= 3 && (njs_is_function(&args[2]) || njs_is_array(&args[2]))) { - stringify->replacer = args[2]; - if (njs_is_array(&args[2])) { + replacer = njs_arg(args, nargs, 2); + + if (njs_is_function(replacer) || njs_is_array(replacer)) { + stringify->replacer = *replacer; + if (njs_is_array(replacer)) { ret = njs_json_stringify_array(vm, stringify); if (nxt_slow_path(ret != NXT_OK)) { goto memory_error; @@ -282,13 +283,15 @@ njs_json_stringify(njs_vm_t *vm, njs_val stringify->space.length = 0; - if (nargs >= 4 && (njs_is_string(&args[3]) || njs_is_number(&args[3]))) { - if (njs_is_string(&args[3])) { - njs_string_get(&args[3], &stringify->space); + space = njs_arg(args, nargs, 3); + + if (njs_is_string(space) || njs_is_number(space)) { + if (njs_is_string(space)) { + njs_string_get(space, &stringify->space); stringify->space.length = nxt_min(stringify->space.length, 10); } else { - num = args[3].data.u.number; + num = space->data.u.number; if (!isnan(num) && !isinf(num) && num > 0) { num = nxt_min(num, 10); @@ -313,7 +316,7 @@ njs_json_stringify(njs_vm_t *vm, njs_val goto memory_error; } - wrapper = njs_json_wrap_value(vm, &args[1]); + wrapper = njs_json_wrap_value(vm, njs_arg(args, nargs, 1)); if (nxt_slow_path(wrapper == NULL)) { goto memory_error; } @@ -910,8 +913,8 @@ njs_json_skip_space(const u_char *start, static njs_ret_t -njs_json_parse_continuation(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, - njs_index_t unused) +njs_json_parse_continuation(njs_vm_t *vm, njs_value_t *args, nxt_uint_t unused, + njs_index_t unused2) { nxt_int_t ret; njs_value_t *key, *value; @@ -1191,7 +1194,7 @@ njs_json_parse_exception(njs_json_parse_ static njs_ret_t njs_json_stringify_continuation(njs_vm_t *vm, njs_value_t *args, - nxt_uint_t nargs, njs_index_t unused) + nxt_uint_t unused, njs_index_t unused2) { u_char *start; size_t size; @@ -1884,7 +1887,7 @@ njs_json_append_number(njs_json_stringif * Wraps a value as '{"": }'. */ static njs_value_t * -njs_json_wrap_value(njs_vm_t *vm, njs_value_t *value) +njs_json_wrap_value(njs_vm_t *vm, const njs_value_t *value) { nxt_int_t ret; njs_value_t *wrapper; From xeioex at nginx.com Wed Mar 27 18:11:02 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 27 Mar 2019 18:11:02 +0000 Subject: [njs] Added nxt_dprintf() and nxt_printf(). Message-ID: details: https://hg.nginx.org/njs/rev/65ec3b20de81 branches: changeset: 853:65ec3b20de81 user: Dmitry Volyntsev date: Wed Mar 27 21:00:19 2019 +0300 description: Added nxt_dprintf() and nxt_printf(). diffstat: nxt/nxt_sprintf.c | 17 +++++++++++++++++ nxt/nxt_sprintf.h | 4 ++++ 2 files changed, 21 insertions(+), 0 deletions(-) diffs (40 lines): diff -r 27347fbb3d0a -r 65ec3b20de81 nxt/nxt_sprintf.c --- a/nxt/nxt_sprintf.c Wed Mar 27 21:00:19 2019 +0300 +++ b/nxt/nxt_sprintf.c Wed Mar 27 21:00:19 2019 +0300 @@ -64,6 +64,23 @@ nxt_sprintf(u_char *buf, u_char *end, co } +int +nxt_dprintf(int fd, const char *fmt, ...) +{ + size_t size; + u_char text[2048], *p; + va_list args; + + va_start(args, fmt); + p = nxt_vsprintf(text, text + sizeof(text), fmt, args); + va_end(args); + + size = p - text; + + return write(fd, text, size); +} + + /* * nxt_sprintf_t is used: * to pass several parameters of nxt_integer() via single pointer diff -r 27347fbb3d0a -r 65ec3b20de81 nxt/nxt_sprintf.h --- a/nxt/nxt_sprintf.h Wed Mar 27 21:00:19 2019 +0300 +++ b/nxt/nxt_sprintf.h Wed Mar 27 21:00:19 2019 +0300 @@ -12,5 +12,9 @@ NXT_EXPORT u_char *nxt_sprintf(u_char *b NXT_EXPORT u_char *nxt_vsprintf(u_char *buf, u_char *end, const char *fmt, va_list args); +NXT_EXPORT int nxt_dprintf(int fd, const char *fmt, ...); + +#define nxt_printf(fmt, ...) \ + nxt_dprintf(STDOUT_FILENO, fmt, ##__VA_ARGS__) #endif /* _NXT_SPRINTF_H_INCLUDED_ */ From xeioex at nginx.com Wed Mar 27 18:11:02 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 27 Mar 2019 18:11:02 +0000 Subject: [njs] Improved njs API tests. Message-ID: details: https://hg.nginx.org/njs/rev/b246cfaabd68 branches: changeset: 854:b246cfaabd68 user: Dmitry Volyntsev date: Wed Mar 27 21:00:19 2019 +0300 description: Improved njs API tests. diffstat: njs/test/njs_unit_test.c | 44 ++++++++++++++++++++++---------------------- 1 files changed, 22 insertions(+), 22 deletions(-) diffs (85 lines): diff -r 65ec3b20de81 -r b246cfaabd68 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Wed Mar 27 21:00:19 2019 +0300 +++ b/njs/test/njs_unit_test.c Wed Mar 27 21:00:19 2019 +0300 @@ -12424,8 +12424,8 @@ njs_vm_object_alloc_test(njs_vm_t * vm, return NXT_ERROR; } - ret = njs_vm_object_alloc(vm, &obj, &num_key, &args[0], &bool_key, &args[1], - NULL); + ret = njs_vm_object_alloc(vm, &obj, &num_key, &args[0], &bool_key, + &args[1], NULL); if (ret != NJS_OK) { return NXT_ERROR; } @@ -12525,22 +12525,18 @@ nxt_file_dirname_test(njs_vm_t * vm, nxt } -typedef struct { - nxt_int_t (*test)(njs_vm_t *, nxt_bool_t, nxt_bool_t); - nxt_str_t name; -} njs_api_test_t; - - static nxt_int_t njs_api_test(nxt_bool_t disassemble, nxt_bool_t verbose) { - njs_vm_t *vm; - nxt_int_t ret, rc; - nxt_uint_t i; - njs_vm_opt_t options; - njs_api_test_t *test; - - static njs_api_test_t njs_api_test[] = { + njs_vm_t *vm; + nxt_int_t ret, rc; + nxt_uint_t i; + njs_vm_opt_t options; + + static const struct { + nxt_int_t (*test)(njs_vm_t *, nxt_bool_t, nxt_bool_t); + nxt_str_t name; + } tests[] = { { njs_vm_object_alloc_test, nxt_string("njs_vm_object_alloc_test") }, { nxt_file_basename_test, @@ -12554,27 +12550,31 @@ njs_api_test(nxt_bool_t disassemble, nxt vm = NULL; nxt_memzero(&options, sizeof(njs_vm_opt_t)); - for (i = 0; i < nxt_nitems(njs_api_test); i++) { - test = &njs_api_test[i]; - + for (i = 0; i < nxt_nitems(tests); i++) { vm = njs_vm_create(&options); if (vm == NULL) { - printf("njs_vm_create() failed\n"); + nxt_printf("njs_vm_create() failed\n"); goto done; } - ret = test->test(vm, disassemble, verbose); + ret = tests[i].test(vm, disassemble, verbose); if (nxt_slow_path(ret != NXT_OK)) { - printf("njs_api_test: \"%.*s\" test failed\n", - (int) test->name.length, test->name.start); + nxt_printf("njs_api_test: \"%V\" test failed\n", &tests[i].name); goto done; } + + njs_vm_destroy(vm); + vm = NULL; } rc = NXT_OK; done: + if (rc == NXT_OK) { + nxt_printf("njs_api_test passed\n"); + } + if (vm != NULL) { njs_vm_destroy(vm); } From xeioex at nginx.com Wed Mar 27 18:11:02 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 27 Mar 2019 18:11:02 +0000 Subject: [njs] Added njs_vm_json_parse() and njs_vm_json_stringify(). Message-ID: details: https://hg.nginx.org/njs/rev/2f4101c9a608 branches: changeset: 855:2f4101c9a608 user: Dmitry Volyntsev date: Wed Mar 27 21:00:20 2019 +0300 description: Added njs_vm_json_parse() and njs_vm_json_stringify(). diffstat: njs/njs.h | 5 + njs/njs_json.c | 25 +++++++++ njs/test/njs_unit_test.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 159 insertions(+), 0 deletions(-) diffs (210 lines): diff -r b246cfaabd68 -r 2f4101c9a608 njs/njs.h --- a/njs/njs.h Wed Mar 27 21:00:19 2019 +0300 +++ b/njs/njs.h Wed Mar 27 21:00:20 2019 +0300 @@ -282,6 +282,11 @@ NXT_EXPORT njs_ret_t njs_vm_object_alloc NXT_EXPORT njs_value_t *njs_vm_object_prop(njs_vm_t *vm, const njs_value_t *value, const nxt_str_t *key); +NXT_EXPORT njs_ret_t njs_vm_json_parse(njs_vm_t *vm, njs_value_t *args, + nxt_uint_t nargs); +NXT_EXPORT njs_ret_t njs_vm_json_stringify(njs_vm_t *vm, njs_value_t *args, + nxt_uint_t nargs); + extern const nxt_mem_proto_t njs_vm_mp_proto; #endif /* _NJS_H_INCLUDED_ */ diff -r b246cfaabd68 -r 2f4101c9a608 njs/njs_json.c --- a/njs/njs_json.c Wed Mar 27 21:00:19 2019 +0300 +++ b/njs/njs_json.c Wed Mar 27 21:00:20 2019 +0300 @@ -159,6 +159,9 @@ static nxt_int_t njs_json_buf_pullup(njs nxt_str_t *str); +static const njs_object_prop_t njs_json_object_properties[]; + + static njs_ret_t njs_json_parse(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) @@ -248,6 +251,17 @@ memory_error: } +njs_ret_t +njs_vm_json_parse(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs) +{ + njs_function_t *parse; + + parse = njs_json_object_properties[0].value.data.u.function; + + return njs_vm_call(vm, parse, args, nargs); +} + + static njs_ret_t njs_json_stringify(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) @@ -335,6 +349,17 @@ memory_error: } +njs_ret_t +njs_vm_json_stringify(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs) +{ + njs_function_t *stringify; + + stringify = njs_json_object_properties[1].value.data.u.function; + + return njs_vm_call(vm, stringify, args, nargs); +} + + static const u_char * njs_json_parse_value(njs_json_parse_ctx_t *ctx, njs_value_t *value, const u_char *p) diff -r b246cfaabd68 -r 2f4101c9a608 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Wed Mar 27 21:00:19 2019 +0300 +++ b/njs/test/njs_unit_test.c Wed Mar 27 21:00:20 2019 +0300 @@ -12397,6 +12397,131 @@ done: static nxt_int_t +njs_vm_json_test(nxt_bool_t disassemble, nxt_bool_t verbose) +{ + njs_vm_t *vm; + nxt_int_t ret, rc; + nxt_str_t s, *script; + nxt_uint_t i; + nxt_bool_t success; + njs_value_t args[3]; + njs_vm_opt_t options; + + static const nxt_str_t fname = nxt_string("replacer"); + static const nxt_str_t iname = nxt_string("indent"); + + static njs_unit_test_t tests[] = { + { nxt_string("'[1, true, \"x\", {\"a\": {}}]'"), + nxt_string("[1,true,\"x\",{\"a\":{}}]") }, + { nxt_string("'{\"a\":{\"b\":1}}'"), + nxt_string("{\"a\":{\"b\":1}}") }, + { nxt_string("'[[[],{}]]'"), + nxt_string("[[[],{}]]") }, + { nxt_string("var indent = 1; '[]'"), + nxt_string("[\n \n]") }, + { nxt_string("function replacer(k, v) {return v}; '{\"a\":{\"b\":1}}'"), + nxt_string("{\"a\":{\"b\":1}}") }, + { nxt_string("function replacer(k, v) {" + " return (typeof v === 'string') ? undefined : v};" + "'{\"a\":1, \"b\":\"x\"}'"), + nxt_string("{\"a\":1}") }, + }; + + vm = NULL; + + rc = NXT_ERROR; + + for (i = 0; i < nxt_nitems(tests); i++) { + + memset(&options, 0, sizeof(njs_vm_opt_t)); + options.init = 1; + + vm = njs_vm_create(&options); + if (vm == NULL) { + nxt_printf("njs_vm_create() failed\n"); + goto done; + } + + script = &tests[i].script; + + ret = njs_vm_compile(vm, &script->start, + script->start + script->length); + + if (ret != NXT_OK) { + nxt_printf("njs_vm_compile() failed\n"); + goto done; + } + + ret = njs_vm_start(vm); + if (ret != NXT_OK) { + nxt_printf("njs_vm_run() failed\n"); + goto done; + } + + args[0] = *njs_vm_retval(vm); + + ret = njs_vm_json_parse(vm, args, 1); + if (ret != NXT_OK) { + nxt_printf("njs_vm_json_parse() failed\n"); + goto done; + } + + args[0] = vm->retval; + args[1] = *njs_vm_value(vm, &fname); + args[2] = *njs_vm_value(vm, &iname); + + ret = njs_vm_json_stringify(vm, args, 3); + if (ret != NXT_OK) { + nxt_printf("njs_vm_json_stringify() failed\n"); + goto done; + } + + if (njs_vm_retval_to_ext_string(vm, &s) != NXT_OK) { + nxt_printf("njs_vm_retval_to_ext_string() failed\n"); + goto done; + } + + success = nxt_strstr_eq(&tests[i].ret, &s); + + if (!success) { + nxt_printf("njs_vm_json_test(\"%V\")\n" + "expected: \"%V\"\n got: \"%V\"\n", script, + &tests[i].ret, &s); + + goto done; + } + + njs_vm_destroy(vm); + vm = NULL; + } + + rc = NXT_OK; + +done: + + if (rc == NXT_OK) { + nxt_printf("njs_vm_json_test passed\n"); + + } else { + if (njs_vm_retval_to_ext_string(vm, &s) != NXT_OK) { + nxt_printf("njs_vm_retval_to_ext_string() failed\n"); + + } else { + nxt_printf("%V\n", &s); + } + } + + if (vm != NULL) { + njs_vm_destroy(vm); + } + + return rc; +} + + + + +static nxt_int_t njs_vm_object_alloc_test(njs_vm_t * vm, nxt_bool_t disassemble, nxt_bool_t verbose) { @@ -12647,6 +12772,10 @@ main(int argc, char **argv) printf("njs timezone tests skipped, timezone is unavailable\n"); } + ret = njs_vm_json_test(disassemble, verbose); + if (ret != NXT_OK) { + return ret; + } return njs_api_test(disassemble, verbose); } From xeioex at nginx.com Thu Mar 28 16:59:51 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 28 Mar 2019 16:59:51 +0000 Subject: [njs] Using nxt_printf() everywhere. Message-ID: details: https://hg.nginx.org/njs/rev/6b8bb252ad06 branches: changeset: 856:6b8bb252ad06 user: Dmitry Volyntsev date: Thu Mar 28 19:45:58 2019 +0300 description: Using nxt_printf() everywhere. diffstat: auto/make | 2 +- njs/njs_builtin.c | 1 - njs/njs_crypto.c | 1 - njs/njs_date.c | 1 - njs/njs_disassembler.c | 145 +++++++++++++++++++-------------------- njs/njs_error.c | 1 - njs/njs_extern.c | 1 - njs/njs_fs.c | 1 - njs/njs_module.c | 1 - njs/njs_number.c | 1 - njs/njs_number.h | 1 - njs/njs_parser.c | 1 - njs/njs_regexp.c | 1 - njs/njs_shell.c | 88 ++++++++++++------------ njs/njs_time.c | 1 - njs/njs_vm.c | 1 - njs/test/njs_benchmark.c | 22 ++--- njs/test/njs_interactive_test.c | 17 +-- njs/test/njs_unit_test.c | 52 +++++-------- nxt/nxt_sprintf.h | 3 + nxt/nxt_trace.c | 1 - nxt/test/lvlhsh_unit_test.c | 32 ++++---- nxt/test/random_unit_test.c | 8 +- nxt/test/rbtree_unit_test.c | 19 ++-- nxt/test/utf8_unit_test.c | 19 ++-- 25 files changed, 197 insertions(+), 224 deletions(-) diffs (truncated from 1417 to 1000 lines): diff -r 2f4101c9a608 -r 6b8bb252ad06 auto/make --- a/auto/make Wed Mar 27 21:00:20 2019 +0300 +++ b/auto/make Thu Mar 28 19:45:58 2019 +0300 @@ -103,7 +103,7 @@ do \$(NXT_CC) -o $NXT_BUILD_DIR/$nxt_bin \$(NXT_CFLAGS) \\ \$(NXT_LIB_INCS) $nxt_dep_flags \\ $nxt_src $NXT_BUILD_DIR/libnxt.a \\ - $nxt_dep_post + $nxt_dep_post -lm -include $NXT_BUILD_DIR/$nxt_dep diff -r 2f4101c9a608 -r 6b8bb252ad06 njs/njs_builtin.c --- a/njs/njs_builtin.c Wed Mar 27 21:00:20 2019 +0300 +++ b/njs/njs_builtin.c Thu Mar 28 19:45:58 2019 +0300 @@ -15,7 +15,6 @@ #include #include #include -#include typedef struct { diff -r 2f4101c9a608 -r 6b8bb252ad06 njs/njs_crypto.c --- a/njs/njs_crypto.c Wed Mar 27 21:00:20 2019 +0300 +++ b/njs/njs_crypto.c Thu Mar 28 19:45:58 2019 +0300 @@ -9,7 +9,6 @@ #include #include #include -#include #include #include diff -r 2f4101c9a608 -r 6b8bb252ad06 njs/njs_date.c --- a/njs/njs_date.c Wed Mar 27 21:00:20 2019 +0300 +++ b/njs/njs_date.c Thu Mar 28 19:45:58 2019 +0300 @@ -6,7 +6,6 @@ #include #include -#include #include #include #include diff -r 2f4101c9a608 -r 6b8bb252ad06 njs/njs_disassembler.c --- a/njs/njs_disassembler.c Wed Mar 27 21:00:20 2019 +0300 +++ b/njs/njs_disassembler.c Thu Mar 28 19:45:58 2019 +0300 @@ -5,7 +5,6 @@ */ #include -#include static void njs_disassemble(u_char *start, u_char *end); @@ -139,8 +138,7 @@ njs_disassembler(njs_vm_t *vm) n = vm->code->items; while (n != 0) { - printf("%.*s:%.*s\n", (int) code->file.length, code->file.start, - (int) code->name.length, code->name.start); + nxt_printf("%V:%V\n", &code->file, &code->name); njs_disassemble(code->start, code->end); code++; n--; @@ -190,9 +188,9 @@ njs_disassemble(u_char *start, u_char *e if (operation == njs_vmcode_array) { array = (njs_vmcode_array_t *) p; - printf("%05zd ARRAY %04zX %zd%s\n", - p - start, (size_t) array->retval, (size_t) array->length, - array->code.ctor ? " INIT" : ""); + nxt_printf("%05uz ARRAY %04Xz %uz%s\n", + p - start, (size_t) array->retval, + (size_t) array->length, array->code.ctor ? " INIT" : ""); p += sizeof(njs_vmcode_array_t); @@ -203,9 +201,9 @@ njs_disassemble(u_char *start, u_char *e cond_jump = (njs_vmcode_cond_jump_t *) p; sign = (cond_jump->offset >= 0) ? "+" : ""; - printf("%05zd JUMP IF TRUE %04zX %s%zd\n", - p - start, (size_t) cond_jump->cond, sign, - (size_t) cond_jump->offset); + nxt_printf("%05uz JUMP IF TRUE %04Xz %s%uz\n", + p - start, (size_t) cond_jump->cond, sign, + (size_t) cond_jump->offset); p += sizeof(njs_vmcode_cond_jump_t); @@ -216,9 +214,9 @@ njs_disassemble(u_char *start, u_char *e cond_jump = (njs_vmcode_cond_jump_t *) p; sign = (cond_jump->offset >= 0) ? "+" : ""; - printf("%05zd JUMP IF FALSE %04zX %s%zd\n", - p - start, (size_t) cond_jump->cond, sign, - (size_t) cond_jump->offset); + nxt_printf("%05uz JUMP IF FALSE %04Xz %s%uz\n", + p - start, (size_t) cond_jump->cond, sign, + (size_t) cond_jump->offset); p += sizeof(njs_vmcode_cond_jump_t); @@ -229,8 +227,8 @@ njs_disassemble(u_char *start, u_char *e jump = (njs_vmcode_jump_t *) p; sign = (jump->offset >= 0) ? "+" : ""; - printf("%05zd JUMP %s%zd\n", - p - start, sign, (size_t) jump->offset); + nxt_printf("%05uz JUMP %s%uz\n", + p - start, sign, (size_t) jump->offset); p += sizeof(njs_vmcode_jump_t); @@ -240,9 +238,9 @@ njs_disassemble(u_char *start, u_char *e if (operation == njs_vmcode_if_equal_jump) { equal = (njs_vmcode_equal_jump_t *) p; - printf("%05zd JUMP IF EQUAL %04zX %04zX +%zd\n", - p - start, (size_t) equal->value1, (size_t) equal->value2, - (size_t) equal->offset); + nxt_printf("%05uz JUMP IF EQUAL %04Xz %04Xz +%uz\n", + p - start, (size_t) equal->value1, + (size_t) equal->value2, (size_t) equal->offset); p += sizeof(njs_vmcode_equal_jump_t); @@ -252,9 +250,9 @@ njs_disassemble(u_char *start, u_char *e if (operation == njs_vmcode_test_if_true) { test_jump = (njs_vmcode_test_jump_t *) p; - printf("%05zd TEST IF TRUE %04zX %04zX +%zd\n", - p - start, (size_t) test_jump->retval, - (size_t) test_jump->value, (size_t) test_jump->offset); + nxt_printf("%05uz TEST IF TRUE %04Xz %04Xz +%uz\n", + p - start, (size_t) test_jump->retval, + (size_t) test_jump->value, (size_t) test_jump->offset); p += sizeof(njs_vmcode_test_jump_t); @@ -264,9 +262,9 @@ njs_disassemble(u_char *start, u_char *e if (operation == njs_vmcode_test_if_false) { test_jump = (njs_vmcode_test_jump_t *) p; - printf("%05zd TEST IF FALSE %04zX %04zX +%zd\n", - p - start, (size_t) test_jump->retval, - (size_t) test_jump->value, (size_t) test_jump->offset); + nxt_printf("%05uz TEST IF FALSE %04Xz %04Xz +%uz\n", + p - start, (size_t) test_jump->retval, + (size_t) test_jump->value, (size_t) test_jump->offset); p += sizeof(njs_vmcode_test_jump_t); @@ -276,9 +274,9 @@ njs_disassemble(u_char *start, u_char *e if (operation == njs_vmcode_function_frame) { function = (njs_vmcode_function_frame_t *) p; - printf("%05zd FUNCTION FRAME %04zX %zd%s\n", - p - start, (size_t) function->name, function->nargs, - function->code.ctor ? " CTOR" : ""); + nxt_printf("%05uz FUNCTION FRAME %04Xz %uz%s\n", + p - start, (size_t) function->name, function->nargs, + function->code.ctor ? " CTOR" : ""); p += sizeof(njs_vmcode_function_frame_t); @@ -288,9 +286,10 @@ njs_disassemble(u_char *start, u_char *e if (operation == njs_vmcode_method_frame) { method = (njs_vmcode_method_frame_t *) p; - printf("%05zd METHOD FRAME %04zX %04zX %zd%s\n", - p - start, (size_t) method->object, (size_t) method->method, - method->nargs, method->code.ctor ? " CTOR" : ""); + nxt_printf("%05uz METHOD FRAME %04Xz %04Xz %uz%s\n", + p - start, (size_t) method->object, + (size_t) method->method, method->nargs, + method->code.ctor ? " CTOR" : ""); p += sizeof(njs_vmcode_method_frame_t); @@ -300,10 +299,10 @@ njs_disassemble(u_char *start, u_char *e if (operation == njs_vmcode_property_foreach) { prop_foreach = (njs_vmcode_prop_foreach_t *) p; - printf("%05zd PROPERTY FOREACH %04zX %04zX +%zd\n", - p - start, (size_t) prop_foreach->next, - (size_t) prop_foreach->object, - (size_t) prop_foreach->offset); + nxt_printf("%05uz PROPERTY FOREACH %04Xz %04Xz +%uz\n", + p - start, (size_t) prop_foreach->next, + (size_t) prop_foreach->object, + (size_t) prop_foreach->offset); p += sizeof(njs_vmcode_prop_foreach_t); @@ -313,10 +312,10 @@ njs_disassemble(u_char *start, u_char *e if (operation == njs_vmcode_property_next) { prop_next = (njs_vmcode_prop_next_t *) p; - printf("%05zd PROPERTY NEXT %04zX %04zX %04zX %zd\n", - p - start, (size_t) prop_next->retval, - (size_t) prop_next->object, (size_t) prop_next->next, - (size_t) prop_next->offset); + nxt_printf("%05uz PROPERTY NEXT %04Xz %04Xz %04Xz %uz\n", + p - start, (size_t) prop_next->retval, + (size_t) prop_next->object, (size_t) prop_next->next, + (size_t) prop_next->offset); p += sizeof(njs_vmcode_prop_next_t); @@ -326,10 +325,10 @@ njs_disassemble(u_char *start, u_char *e if (operation == njs_vmcode_try_start) { try_start = (njs_vmcode_try_start_t *) p; - printf("%05zd TRY START %04zX %04zX +%zd\n", - p - start, (size_t) try_start->exception_value, - (size_t) try_start->exit_value, - (size_t) try_start->offset); + nxt_printf("%05uz TRY START %04Xz %04Xz +%uz\n", + p - start, (size_t) try_start->exception_value, + (size_t) try_start->exit_value, + (size_t) try_start->offset); p += sizeof(njs_vmcode_try_start_t); @@ -339,9 +338,9 @@ njs_disassemble(u_char *start, u_char *e if (operation == njs_vmcode_try_break) { try_tramp = (njs_vmcode_try_trampoline_t *) p; - printf("%05zd TRY BREAK %04zX %zd\n", - p - start, (size_t) try_tramp->exit_value, - (size_t) try_tramp->offset); + nxt_printf("%05uz TRY BREAK %04Xz %uz\n", + p - start, (size_t) try_tramp->exit_value, + (size_t) try_tramp->offset); p += sizeof(njs_vmcode_try_trampoline_t); @@ -351,9 +350,9 @@ njs_disassemble(u_char *start, u_char *e if (operation == njs_vmcode_try_continue) { try_tramp = (njs_vmcode_try_trampoline_t *) p; - printf("%05zd TRY CONTINUE %04zX %zd\n", - p - start, (size_t) try_tramp->exit_value, - (size_t) try_tramp->offset); + nxt_printf("%05uz TRY CONTINUE %04Xz %uz\n", + p - start, (size_t) try_tramp->exit_value, + (size_t) try_tramp->offset); p += sizeof(njs_vmcode_try_trampoline_t); @@ -363,10 +362,10 @@ njs_disassemble(u_char *start, u_char *e if (operation == njs_vmcode_try_return) { try_return = (njs_vmcode_try_return_t *) p; - printf("%05zd TRY RETURN %04zX %04zX +%zd\n", - p - start, (size_t) try_return->save, - (size_t) try_return->retval, - (size_t) try_return->offset); + nxt_printf("%05uz TRY RETURN %04Xz %04Xz +%uz\n", + p - start, (size_t) try_return->save, + (size_t) try_return->retval, + (size_t) try_return->offset); p += sizeof(njs_vmcode_try_return_t); @@ -376,9 +375,9 @@ njs_disassemble(u_char *start, u_char *e if (operation == njs_vmcode_catch) { catch = (njs_vmcode_catch_t *) p; - printf("%05zd CATCH %04zX +%zd\n", - p - start, (size_t) catch->exception, - (size_t) catch->offset); + nxt_printf("%05uz CATCH %04Xz +%uz\n", + p - start, (size_t) catch->exception, + (size_t) catch->offset); p += sizeof(njs_vmcode_catch_t); @@ -388,8 +387,8 @@ njs_disassemble(u_char *start, u_char *e if (operation == njs_vmcode_try_end) { try_end = (njs_vmcode_try_end_t *) p; - printf("%05zd TRY END +%zd\n", - p - start, (size_t) try_end->offset); + nxt_printf("%05uz TRY END +%uz\n", + p - start, (size_t) try_end->offset); p += sizeof(njs_vmcode_try_end_t); @@ -399,11 +398,11 @@ njs_disassemble(u_char *start, u_char *e if (operation == njs_vmcode_finally) { finally = (njs_vmcode_finally_t *) p; - printf("%05zd TRY FINALLY %04zX %04zX +%zd +%zd\n", - p - start, (size_t) finally->retval, - (size_t) finally->exit_value, - (size_t) finally->continue_offset, - (size_t) finally->break_offset); + nxt_printf("%05uz TRY FINALLY %04Xz %04Xz +%uz +%uz\n", + p - start, (size_t) finally->retval, + (size_t) finally->exit_value, + (size_t) finally->continue_offset, + (size_t) finally->break_offset); p += sizeof(njs_vmcode_finally_t); @@ -420,24 +419,24 @@ njs_disassemble(u_char *start, u_char *e 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); + nxt_printf("%05uz %*s %04Xz %04Xz %04Xz\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; - printf("%05zd %*s %04zX %04zX\n", - p - start, (int) name->length, name->start, - (size_t) code2->dst, (size_t) code2->src); + nxt_printf("%05uz %*s %04Xz %04Xz\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; - printf("%05zd %*s %04zX\n", - p - start, (int) name->length, name->start, - (size_t) code1->index); + nxt_printf("%05uz %*s %04Xz\n", + p - start, (int) name->length, name->start, + (size_t) code1->index); } p += code_name->size; @@ -450,8 +449,8 @@ njs_disassemble(u_char *start, u_char *e } while (n != 0); - printf("%05zd UNKNOWN %04zX\n", - p - start, (size_t) (uintptr_t) operation); + nxt_printf("%05uz UNKNOWN %04Xz\n", + p - start, (size_t) (uintptr_t) operation); p += sizeof(njs_vmcode_operation_t); diff -r 2f4101c9a608 -r 6b8bb252ad06 njs/njs_error.c --- a/njs/njs_error.c Wed Mar 27 21:00:20 2019 +0300 +++ b/njs/njs_error.c Thu Mar 28 19:45:58 2019 +0300 @@ -5,7 +5,6 @@ */ #include -#include #include #include diff -r 2f4101c9a608 -r 6b8bb252ad06 njs/njs_extern.c --- a/njs/njs_extern.c Wed Mar 27 21:00:20 2019 +0300 +++ b/njs/njs_extern.c Thu Mar 28 19:45:58 2019 +0300 @@ -6,7 +6,6 @@ #include #include -#include typedef struct njs_extern_part_s njs_extern_part_t; diff -r 2f4101c9a608 -r 6b8bb252ad06 njs/njs_fs.c --- a/njs/njs_fs.c Wed Mar 27 21:00:20 2019 +0300 +++ b/njs/njs_fs.c Thu Mar 28 19:45:58 2019 +0300 @@ -10,7 +10,6 @@ #include #include #include -#include typedef struct { diff -r 2f4101c9a608 -r 6b8bb252ad06 njs/njs_module.c --- a/njs/njs_module.c Wed Mar 27 21:00:20 2019 +0300 +++ b/njs/njs_module.c Thu Mar 28 19:45:58 2019 +0300 @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include diff -r 2f4101c9a608 -r 6b8bb252ad06 njs/njs_number.c --- a/njs/njs_number.c Wed Mar 27 21:00:20 2019 +0300 +++ b/njs/njs_number.c Thu Mar 28 19:45:58 2019 +0300 @@ -7,7 +7,6 @@ #include #include #include -#include #include diff -r 2f4101c9a608 -r 6b8bb252ad06 njs/njs_number.h --- a/njs/njs_number.h Wed Mar 27 21:00:20 2019 +0300 +++ b/njs/njs_number.h Thu Mar 28 19:45:58 2019 +0300 @@ -9,7 +9,6 @@ #include -#include uint32_t njs_value_to_index(const njs_value_t *value); diff -r 2f4101c9a608 -r 6b8bb252ad06 njs/njs_parser.c --- a/njs/njs_parser.c Wed Mar 27 21:00:20 2019 +0300 +++ b/njs/njs_parser.c Thu Mar 28 19:45:58 2019 +0300 @@ -7,7 +7,6 @@ #include #include #include -#include static njs_ret_t njs_parser_scope_begin(njs_vm_t *vm, njs_parser_t *parser, diff -r 2f4101c9a608 -r 6b8bb252ad06 njs/njs_regexp.c --- a/njs/njs_regexp.c Wed Mar 27 21:00:20 2019 +0300 +++ b/njs/njs_regexp.c Thu Mar 28 19:45:58 2019 +0300 @@ -9,7 +9,6 @@ #include #include -#include static void *njs_regexp_malloc(size_t size, void *memory_data); diff -r 2f4101c9a608 -r 6b8bb252ad06 njs/njs_shell.c --- a/njs/njs_shell.c Wed Mar 27 21:00:20 2019 +0300 +++ b/njs/njs_shell.c Thu Mar 28 19:45:58 2019 +0300 @@ -10,13 +10,13 @@ #include #include #include -#include #include #include #include #include #include +#include #include @@ -214,7 +214,7 @@ main(int argc, char **argv) } if (opts.version != 0) { - printf("%s\n", NJS_VERSION); + nxt_printf("%s\n", NJS_VERSION); ret = NXT_OK; goto done; } @@ -225,7 +225,7 @@ main(int argc, char **argv) if (opts.file == NULL) { p = getcwd(path, sizeof(path)); if (p == NULL) { - fprintf(stderr, "getcwd() failed:%s\n", strerror(errno)); + nxt_error("getcwd() failed:%s\n", strerror(errno)); ret = NXT_ERROR; goto done; } @@ -316,7 +316,7 @@ njs_get_options(njs_opts_t *opts, int ar opts->n_paths++; paths = realloc(opts->paths, opts->n_paths * sizeof(char *)); if (paths == NULL) { - fprintf(stderr, "failed to add path\n"); + nxt_error("failed to add path\n"); return NXT_ERROR; } @@ -325,7 +325,7 @@ njs_get_options(njs_opts_t *opts, int ar break; } - fprintf(stderr, "option \"-p\" requires directory name\n"); + nxt_error("option \"-p\" requires directory name\n"); return NXT_ERROR; case 'v': @@ -334,8 +334,9 @@ njs_get_options(njs_opts_t *opts, int ar break; default: - fprintf(stderr, "Unknown argument: \"%s\" " - "try \"%s -h\" for available options\n", argv[i], argv[0]); + nxt_error("Unknown argument: \"%s\" " + "try \"%s -h\" for available options\n", argv[i], + argv[0]); return NXT_ERROR; } } @@ -374,7 +375,7 @@ njs_externals_init(njs_vm_t *vm, njs_con proto = njs_vm_external_prototype(vm, &njs_externals[0]); if (proto == NULL) { - fprintf(stderr, "failed to add console proto\n"); + nxt_error("failed to add console proto\n"); return NXT_ERROR; } @@ -409,7 +410,7 @@ njs_interactive_shell(njs_opts_t *opts, nxt_str_t line; if (njs_editline_init() != NXT_OK) { - fprintf(stderr, "failed to init completions\n"); + nxt_error("failed to init completions\n"); return NXT_ERROR; } @@ -419,10 +420,10 @@ njs_interactive_shell(njs_opts_t *opts, } if (!opts->quiet) { - printf("interactive njs %s\n\n", NJS_VERSION); + nxt_printf("interactive njs %s\n\n", NJS_VERSION); - printf("v. -> the properties and prototype methods of v.\n"); - printf("type console.help() for more information\n\n"); + nxt_printf("v. -> the properties and prototype methods of v.\n"); + nxt_printf("type console.help() for more information\n\n"); } for ( ;; ) { @@ -469,15 +470,15 @@ njs_process_file(njs_opts_t *opts, njs_v } else { fd = open(file, O_RDONLY); if (fd == -1) { - fprintf(stderr, "failed to open file: '%s' (%s)\n", - file, strerror(errno)); + nxt_error("failed to open file: '%s' (%s)\n", + file, strerror(errno)); return NXT_ERROR; } } if (fstat(fd, &sb) == -1) { - fprintf(stderr, "fstat(%d) failed while reading '%s' (%s)\n", - fd, file, strerror(errno)); + nxt_error("fstat(%d) failed while reading '%s' (%s)\n", + fd, file, strerror(errno)); ret = NXT_ERROR; goto close_fd; } @@ -491,7 +492,7 @@ njs_process_file(njs_opts_t *opts, njs_v script.length = 0; script.start = realloc(NULL, size); if (script.start == NULL) { - fprintf(stderr, "alloc failed while reading '%s'\n", file); + nxt_error("alloc failed while reading '%s'\n", file); ret = NXT_ERROR; goto done; } @@ -507,8 +508,8 @@ njs_process_file(njs_opts_t *opts, njs_v } if (n < 0) { - fprintf(stderr, "failed to read file: '%s' (%s)\n", - file, strerror(errno)); + nxt_error("failed to read file: '%s' (%s)\n", + file, strerror(errno)); ret = NXT_ERROR; goto done; } @@ -518,7 +519,7 @@ njs_process_file(njs_opts_t *opts, njs_v start = realloc(script.start, size); if (start == NULL) { - fprintf(stderr, "alloc failed while reading '%s'\n", file); + nxt_error("alloc failed while reading '%s'\n", file); ret = NXT_ERROR; goto done; } @@ -576,12 +577,12 @@ njs_create_vm(njs_opts_t *opts, njs_vm_o vm = njs_vm_create(vm_options); if (vm == NULL) { - fprintf(stderr, "failed to create vm\n"); + nxt_error("failed to create vm\n"); return NULL; } if (njs_externals_init(vm, vm_options->external) != NXT_OK) { - fprintf(stderr, "failed to add external protos\n"); + nxt_error("failed to add external protos\n"); return NULL; } @@ -591,7 +592,7 @@ njs_create_vm(njs_opts_t *opts, njs_vm_o ret = njs_vm_add_path(vm, &path); if (ret != NXT_OK) { - fprintf(stderr, "failed to add path\n"); + nxt_error("failed to add path\n"); return NULL; } } @@ -609,7 +610,7 @@ njs_create_vm(njs_opts_t *opts, njs_vm_o ret = njs_vm_add_path(vm, &path); if (ret != NXT_OK) { - fprintf(stderr, "failed to add path\n"); + nxt_error("failed to add path\n"); return NULL; } @@ -635,10 +636,10 @@ njs_output(njs_vm_t *vm, njs_opts_t *opt } if (ret != NJS_OK) { - fprintf(stderr, "%.*s\n", (int) out.length, out.start); + nxt_error("%V\n", &out); } else if (opts->interactive) { - printf("%.*s\n", (int) out.length, out.start); + nxt_printf("%V\n", &out); } } @@ -688,7 +689,7 @@ njs_process_script(njs_console_t *consol if (ret == NXT_OK) { if (opts->disassemble) { njs_disassembler(vm); - printf("\n"); + nxt_printf("\n"); } ret = njs_vm_start(vm); @@ -703,7 +704,7 @@ njs_process_script(njs_console_t *consol ret = njs_process_events(console, opts); if (nxt_slow_path(ret != NXT_OK)) { - fprintf(stderr, "njs_process_events() failed\n"); + nxt_error("njs_process_events() failed\n"); ret = NJS_ERROR; break; } @@ -711,8 +712,7 @@ njs_process_script(njs_console_t *consol if (njs_vm_waiting(vm) && !njs_vm_posted(vm)) { /*TODO: async events. */ - fprintf(stderr, "njs_process_script(): " - "async events unsupported\n"); + nxt_error("njs_process_script(): async events unsupported\n"); ret = NJS_ERROR; break; } @@ -913,13 +913,13 @@ njs_ext_console_log(njs_vm_t *vm, njs_va return NJS_ERROR; } - printf("%s%.*s", (n != 1) ? " " : "", (int) msg.length, msg.start); + nxt_printf("%s%V", (n != 1) ? " " : "", &msg); n++; } if (nargs > 1) { - printf("\n"); + nxt_printf("\n"); } vm->retval = njs_value_undefined; @@ -944,13 +944,13 @@ njs_ext_console_dump(njs_vm_t *vm, njs_v return NJS_ERROR; } - printf("%s%.*s", (n != 1) ? " " : "", (int) msg.length, msg.start); + nxt_printf("%s%V", (n != 1) ? " " : "", &msg); n++; } if (nargs > 1) { - printf("\n"); + nxt_printf("\n"); } vm->retval = njs_value_undefined; @@ -965,24 +965,24 @@ njs_ext_console_help(njs_vm_t *vm, njs_v { const njs_object_init_t *obj, **objpp; - printf("VM built-in objects:\n"); + nxt_printf("VM built-in objects:\n"); for (objpp = njs_constructor_init; *objpp != NULL; objpp++) { obj = *objpp; - printf(" %.*s\n", (int) obj->name.length, obj->name.start); + nxt_printf(" %V\n", &obj->name); } for (objpp = njs_object_init; *objpp != NULL; objpp++) { obj = *objpp; - printf(" %.*s\n", (int) obj->name.length, obj->name.start); + nxt_printf(" %V\n", &obj->name); } - printf("\nEmbedded objects:\n"); - printf(" console\n"); + nxt_printf("\nEmbedded objects:\n"); + nxt_printf(" console\n"); - printf("\n"); + nxt_printf("\n"); vm->retval = njs_value_undefined; @@ -1040,12 +1040,12 @@ njs_ext_console_time_end(njs_vm_t *vm, n ms = ns / 1000000; ns = ns % 1000000; - printf("default: %" PRIu64 ".%06" PRIu64 "ms\n", ms, ns); + nxt_printf("default: %uL.%06uLms\n", ms, ns); console->time = UINT64_MAX; } else { - printf("Timer \"default\" doesn?t exist.\n"); + nxt_printf("Timer \"default\" doesn?t exist.\n"); } vm->retval = njs_value_undefined; @@ -1065,7 +1065,7 @@ njs_console_set_timer(njs_external_ptr_t nxt_lvlhsh_query_t lhq; if (delay != 0) { - fprintf(stderr, "njs_console_set_timer(): async timers unsupported\n"); + nxt_error("njs_console_set_timer(): async timers unsupported\n"); return NULL; } @@ -1125,7 +1125,7 @@ njs_console_clear_timer(njs_external_ptr ret = nxt_lvlhsh_delete(&console->events, &lhq); if (ret != NXT_OK) { - fprintf(stderr, "nxt_lvlhsh_delete() failed\n"); + nxt_error("nxt_lvlhsh_delete() failed\n"); } nxt_mp_free(vm->mem_pool, ev); diff -r 2f4101c9a608 -r 6b8bb252ad06 njs/njs_time.c --- a/njs/njs_time.c Wed Mar 27 21:00:20 2019 +0300 +++ b/njs/njs_time.c Thu Mar 28 19:45:58 2019 +0300 @@ -7,7 +7,6 @@ #include #include #include -#include static njs_ret_t diff -r 2f4101c9a608 -r 6b8bb252ad06 njs/njs_vm.c --- a/njs/njs_vm.c Wed Mar 27 21:00:20 2019 +0300 +++ b/njs/njs_vm.c Thu Mar 28 19:45:58 2019 +0300 @@ -7,7 +7,6 @@ #include #include #include -#include diff -r 2f4101c9a608 -r 6b8bb252ad06 njs/test/njs_benchmark.c --- a/njs/test/njs_benchmark.c Wed Mar 27 21:00:20 2019 +0300 +++ b/njs/test/njs_benchmark.c Thu Mar 28 19:45:58 2019 +0300 @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include @@ -34,7 +34,7 @@ njs_unit_test_benchmark(nxt_str_t *scrip vm = njs_vm_create(&options); if (vm == NULL) { - printf("njs_vm_create() failed\n"); + nxt_printf("njs_vm_create() failed\n"); goto done; } @@ -42,7 +42,7 @@ njs_unit_test_benchmark(nxt_str_t *scrip ret = njs_vm_compile(vm, &start, start + script->length); if (ret != NXT_OK) { - printf("njs_vm_compile() failed\n"); + nxt_printf("njs_vm_compile() failed\n"); goto done; } @@ -50,23 +50,21 @@ njs_unit_test_benchmark(nxt_str_t *scrip nvm = njs_vm_clone(vm, NULL); if (nvm == NULL) { - printf("njs_vm_clone() failed\n"); + nxt_printf("njs_vm_clone() failed\n"); goto done; } (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"); + nxt_printf("njs_vm_retval_to_ext_string() failed\n"); goto done; } success = nxt_strstr_eq(result, &s); if (!success) { - printf("failed: \"%.*s\" vs \"%.*s\"\n", - (int) result->length, result->start, (int) s.length, - s.start); + nxt_printf("failed: \"%V\" vs \"%V\"\n", result, &s); goto done; } @@ -80,11 +78,11 @@ njs_unit_test_benchmark(nxt_str_t *scrip + usage.ru_stime.tv_sec * 1000000 + usage.ru_stime.tv_usec; if (n == 1) { - printf("%s: %.3fs\n", msg, (double) us / 1000000); + nxt_printf("%s: %.3fs\n", msg, (double) us / 1000000); } else { - printf("%s: %.3f?s, %d times/s\n", - msg, (double) us / n, (int) ((uint64_t) n * 1000000 / us)); + nxt_printf("%s: %.3f?s, %d times/s\n", + msg, (double) us / n, (int) ((uint64_t) n * 1000000 / us)); } rc = NXT_OK; @@ -170,6 +168,6 @@ main(int argc, char **argv) } } - printf("unknown agrument\n"); + nxt_printf("unknown agrument\n"); return EXIT_FAILURE; } diff -r 2f4101c9a608 -r 6b8bb252ad06 njs/test/njs_interactive_test.c --- a/njs/test/njs_interactive_test.c Wed Mar 27 21:00:20 2019 +0300 +++ b/njs/test/njs_interactive_test.c Thu Mar 28 19:45:58 2019 +0300 @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include @@ -273,8 +273,7 @@ njs_interactive_test(nxt_bool_t verbose) test = &njs_test[i]; if (verbose) { - printf("\"%.*s\"\n", (int) test->script.length, test->script.start); - fflush(stdout); + nxt_printf("\"%V\"\n", &test->script); } nxt_memzero(&options, sizeof(njs_vm_opt_t)); @@ -284,7 +283,7 @@ njs_interactive_test(nxt_bool_t verbose) vm = njs_vm_create(&options); if (vm == NULL) { - printf("njs_vm_create() failed\n"); + nxt_printf("njs_vm_create() failed\n"); goto done; } @@ -307,7 +306,7 @@ njs_interactive_test(nxt_bool_t verbose) } if (njs_vm_retval_to_ext_string(vm, &s) != NXT_OK) { - printf("njs_vm_retval_to_ext_string() failed\n"); + nxt_printf("njs_vm_retval_to_ext_string() failed\n"); goto done; } @@ -318,17 +317,15 @@ njs_interactive_test(nxt_bool_t verbose) continue; } - printf("njs_interactive(\"%.*s\") failed: \"%.*s\" vs \"%.*s\"\n", - (int) test->script.length, test->script.start, - (int) test->ret.length, test->ret.start, - (int) s.length, s.start); + nxt_printf("njs_interactive(\"%V\") failed: \"%V\" vs \"%V\"\n", + &test->script, &test->ret, &s); goto done; } ret = NXT_OK; - printf("njs interactive tests passed\n"); + nxt_printf("njs interactive tests passed\n"); done: diff -r 2f4101c9a608 -r 6b8bb252ad06 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Wed Mar 27 21:00:20 2019 +0300 +++ b/njs/test/njs_unit_test.c Thu Mar 28 19:45:58 2019 +0300 @@ -9,7 +9,6 @@ #include #include #include -#include #include #include @@ -12237,7 +12236,7 @@ njs_externals_init(njs_vm_t *vm) proto = njs_vm_external_prototype(vm, &nxt_test_external[0]); if (proto == NULL) { - printf("njs_vm_external_prototype() failed\n"); + nxt_printf("njs_vm_external_prototype() failed\n"); return NXT_ERROR; } @@ -12257,14 +12256,14 @@ njs_externals_init(njs_vm_t *vm) ret = njs_vm_external_create(vm, njs_value_arg(&requests[i].value), proto, &requests[i]); if (ret != NXT_OK) { - printf("njs_vm_external_create() failed\n"); + nxt_printf("njs_vm_external_create() failed\n"); return NXT_ERROR; } ret = njs_vm_external_bind(vm, &nxt_test_requests[i].name, njs_value_arg(&requests[i].value)); if (ret != NXT_OK) { - printf("njs_vm_external_bind() failed\n"); + nxt_printf("njs_vm_external_bind() failed\n"); return NXT_ERROR; } @@ -12274,13 +12273,13 @@ njs_externals_init(njs_vm_t *vm) &nxt_test_requests[i].props[j].value); if (prop == NULL) { - printf("lvlhsh_unit_test_alloc() failed\n"); + nxt_printf("lvlhsh_unit_test_alloc() failed\n"); return NXT_ERROR; } ret = lvlhsh_unit_test_add(&requests[i], prop); if (ret != NXT_OK) { - printf("lvlhsh_unit_test_add() failed\n"); + nxt_printf("lvlhsh_unit_test_add() failed\n"); return NXT_ERROR; } } @@ -12310,16 +12309,14 @@ njs_unit_test(njs_unit_test_t tests[], s for (i = 0; i < num; i++) { if (verbose) { - printf("\"%.*s\"\n", - (int) njs_test[i].script.length, njs_test[i].script.start); - fflush(stdout); + nxt_printf("\"%V\"\n", &njs_test[i].script); } nxt_memzero(&options, sizeof(njs_vm_opt_t)); vm = njs_vm_create(&options); if (vm == NULL) { - printf("njs_vm_create() failed\n"); + nxt_printf("njs_vm_create() failed\n"); goto done; } @@ -12335,25 +12332,24 @@ njs_unit_test(njs_unit_test_t tests[], s if (ret == NXT_OK) { if (disassemble) { njs_disassembler(vm); - fflush(stdout); From xeioex at nginx.com Thu Mar 28 17:40:05 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 28 Mar 2019 17:40:05 +0000 Subject: [njs] Avoiding strict check in export default value expressions. Message-ID: details: https://hg.nginx.org/njs/rev/913398656772 branches: changeset: 857:913398656772 user: Dmitry Volyntsev date: Thu Mar 28 20:31:20 2019 +0300 description: Avoiding strict check in export default value expressions. Previously, only object literals were allowed. diffstat: njs/njs_parser.c | 5 ----- njs/test/module/export_expression.js | 10 ++++++++++ njs/test/module/export_expression2.js | 5 +++++ njs/test/module/export_name.js | 6 ++++++ njs/test/njs_expect_test.exp | 12 ++++++++++++ 5 files changed, 33 insertions(+), 5 deletions(-) diffs (70 lines): diff -r 6b8bb252ad06 -r 913398656772 njs/njs_parser.c --- a/njs/njs_parser.c Thu Mar 28 19:45:58 2019 +0300 +++ b/njs/njs_parser.c Thu Mar 28 20:31:20 2019 +0300 @@ -2076,11 +2076,6 @@ njs_parser_export_statement(njs_vm_t *vm return token; } - if (parser->node->token != NJS_TOKEN_OBJECT) { - njs_parser_syntax_error(vm, parser, "Illegal export value"); - return NXT_ERROR; - } - node->right = parser->node; parser->node = node; diff -r 6b8bb252ad06 -r 913398656772 njs/test/module/export_expression.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/njs/test/module/export_expression.js Thu Mar 28 20:31:20 2019 +0300 @@ -0,0 +1,10 @@ +function gen_export() { + var _export = {}; + + _export.sum = function(a, b) { return a + b; } + _export.prod = function(a, b) { return a * b; } + + return _export; +} + +export default gen_export(); diff -r 6b8bb252ad06 -r 913398656772 njs/test/module/export_expression2.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/njs/test/module/export_expression2.js Thu Mar 28 20:31:20 2019 +0300 @@ -0,0 +1,5 @@ +var _export = {}; + +export default (_export.sum = function(a, b) { return a + b; }, + _export.prod = function(a, b) { return a * b; }, + _export); diff -r 6b8bb252ad06 -r 913398656772 njs/test/module/export_name.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/njs/test/module/export_name.js Thu Mar 28 20:31:20 2019 +0300 @@ -0,0 +1,6 @@ +var _export = {}; + +_export.sum = function(a, b) { return a + b; } +_export.prod = function(a, b) { return a * b; } + +export default _export; diff -r 6b8bb252ad06 -r 913398656772 njs/test/njs_expect_test.exp --- a/njs/test/njs_expect_test.exp Thu Mar 28 19:45:58 2019 +0300 +++ b/njs/test/njs_expect_test.exp Thu Mar 28 20:31:20 2019 +0300 @@ -685,6 +685,18 @@ njs_test { "Error: loading exception\r\n at module \\(loading_exception.js:1\\)"} {"import lib3 from 'lib1.js'\r\n" "undefined\r\n"} + {"import m from 'export_name.js'\r\n" + "undefined\r\n"} + {"m.prod(3,4)\r\n" + "12\r\n"} + {"import m from 'export_expression.js'\r\n" + "undefined\r\n"} + {"m.sum(3,4)\r\n" + "7\r\n"} + {"import m from 'export_expression2.js'\r\n" + "undefined\r\n"} + {"m.prod(3,4)\r\n" + "12\r\n"} } "-p njs/test/module/" njs_run "-p njs/test/module/libs/ -d ./njs/test/module/normal.js" \ From xeioex at nginx.com Thu Mar 28 18:27:14 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 28 Mar 2019 18:27:14 +0000 Subject: [njs] Introduced njs_object_property_descriptor(). Message-ID: details: https://hg.nginx.org/njs/rev/3033faf46265 branches: changeset: 859:3033faf46265 user: Artem S. Povalyukhin date: Wed Mar 27 20:45:39 2019 +0300 description: Introduced njs_object_property_descriptor(). diffstat: njs/njs_object.c | 44 +++++++++++++++++++++++++++----------------- 1 files changed, 27 insertions(+), 17 deletions(-) diffs (81 lines): diff -r 2251d61554ac -r 3033faf46265 njs/njs_object.c --- a/njs/njs_object.c Thu Mar 28 20:42:11 2019 +0300 +++ b/njs/njs_object.c Wed Mar 27 20:45:39 2019 +0300 @@ -1610,26 +1610,16 @@ static const njs_value_t njs_object_wri static njs_ret_t -njs_object_get_own_property_descriptor(njs_vm_t *vm, njs_value_t *args, - nxt_uint_t nargs, njs_index_t unused) +njs_object_property_descriptor(njs_vm_t *vm, njs_value_t *dest, + const njs_value_t *value, const njs_value_t *property) { nxt_int_t ret; njs_object_t *descriptor; njs_object_prop_t *pr, *prop; - const njs_value_t *value, *property, *setval; + const njs_value_t *setval; nxt_lvlhsh_query_t lhq; njs_property_query_t pq; - value = njs_arg(args, nargs, 1); - - if (njs_is_null_or_undefined(value)) { - njs_type_error(vm, "cannot convert %s argument to object", - njs_type_string(value->type)); - return NXT_ERROR; - } - - property = njs_arg(args, nargs, 2); - njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 1); ret = njs_property_query(vm, &pq, (njs_value_t *) value, property); @@ -1639,7 +1629,7 @@ njs_object_get_own_property_descriptor(n break; case NXT_DECLINED: - vm->retval = njs_value_undefined; + *dest = njs_value_undefined; return NXT_OK; case NJS_TRAP: @@ -1764,15 +1754,35 @@ njs_object_get_own_property_descriptor(n return NXT_ERROR; } - vm->retval.data.u.object = descriptor; - vm->retval.type = NJS_OBJECT; - vm->retval.data.truth = 1; + dest->data.u.object = descriptor; + dest->type = NJS_OBJECT; + dest->data.truth = 1; return NXT_OK; } static njs_ret_t +njs_object_get_own_property_descriptor(njs_vm_t *vm, njs_value_t *args, + nxt_uint_t nargs, njs_index_t unused) +{ + const njs_value_t *value, *property; + + value = njs_arg(args, nargs, 1); + + if (njs_is_null_or_undefined(value)) { + njs_type_error(vm, "cannot convert %s argument to object", + njs_type_string(value->type)); + return NXT_ERROR; + } + + property = njs_arg(args, nargs, 2); + + return njs_object_property_descriptor(vm, &vm->retval, value, property); +} + + +static njs_ret_t njs_object_get_own_property_names(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) { From xeioex at nginx.com Thu Mar 28 18:27:14 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 28 Mar 2019 18:27:14 +0000 Subject: [njs] Improved njs_object_enumerate(). Message-ID: details: https://hg.nginx.org/njs/rev/2251d61554ac branches: changeset: 858:2251d61554ac user: Dmitry Volyntsev date: Thu Mar 28 20:42:11 2019 +0300 description: Improved njs_object_enumerate(). diffstat: njs/njs_object.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (24 lines): diff -r 913398656772 -r 2251d61554ac njs/njs_object.c --- a/njs/njs_object.c Thu Mar 28 20:31:20 2019 +0300 +++ b/njs/njs_object.c Thu Mar 28 20:42:11 2019 +0300 @@ -1217,10 +1217,11 @@ njs_object_enumerate(njs_vm_t *vm, const if (nxt_fast_path(properties != 0)) { nxt_lvlhsh_each_init(&lhe, &njs_object_hash_proto); + hash = &value->data.u.object->hash; + switch (kind) { case NJS_ENUM_KEYS: - hash = &value->data.u.object->hash; for ( ;; ) { prop = nxt_lvlhsh_each(hash, &lhe); @@ -1251,7 +1252,6 @@ njs_object_enumerate(njs_vm_t *vm, const break; case NJS_ENUM_VALUES: - hash = &value->data.u.object->hash; for ( ;; ) { prop = nxt_lvlhsh_each(hash, &lhe); From xeioex at nginx.com Thu Mar 28 18:27:15 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 28 Mar 2019 18:27:15 +0000 Subject: [njs] Added Object.getOwnPropertyDescriptors(). Message-ID: details: https://hg.nginx.org/njs/rev/5f273795d8dc branches: changeset: 860:5f273795d8dc user: Artem S. Povalyukhin date: Wed Mar 27 20:49:03 2019 +0300 description: Added Object.getOwnPropertyDescriptors(). This closes #119 issue on Github. diffstat: njs/njs_object.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++ njs/test/njs_unit_test.c | 16 +++++++++ 2 files changed, 93 insertions(+), 0 deletions(-) diffs (120 lines): diff -r 3033faf46265 -r 5f273795d8dc njs/njs_object.c --- a/njs/njs_object.c Wed Mar 27 20:45:39 2019 +0300 +++ b/njs/njs_object.c Wed Mar 27 20:49:03 2019 +0300 @@ -1783,6 +1783,75 @@ njs_object_get_own_property_descriptor(n static njs_ret_t +njs_object_get_own_property_descriptors(njs_vm_t *vm, njs_value_t *args, + nxt_uint_t nargs, njs_index_t unused) +{ + njs_ret_t ret; + uint32_t i, length; + njs_array_t *names; + njs_value_t descriptor; + njs_object_t *descriptors; + const njs_value_t *value, *key; + njs_object_prop_t *pr; + nxt_lvlhsh_query_t lhq; + + value = njs_arg(args, nargs, 1); + + if (njs_is_null_or_undefined(value)) { + njs_type_error(vm, "cannot convert %s argument to object", + njs_type_string(value->type)); + + return NXT_ERROR; + } + + names = njs_object_enumerate(vm, value, NJS_ENUM_KEYS, 1); + if (nxt_slow_path(names == NULL)) { + return NXT_ERROR; + } + + length = names->length; + + descriptors = njs_object_alloc(vm); + if (nxt_slow_path(descriptors == NULL)) { + return NXT_ERROR; + } + + lhq.replace = 0; + lhq.pool = vm->mem_pool; + lhq.proto = &njs_object_hash_proto; + + for (i = 0; i < length; i++) { + key = &names->start[i]; + ret = njs_object_property_descriptor(vm, &descriptor, value, key); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } + + pr = njs_object_prop_alloc(vm, key, &descriptor, 1); + if (nxt_slow_path(pr == NULL)) { + return NXT_ERROR; + } + + njs_string_get(key, &lhq.key); + lhq.key_hash = nxt_djb_hash(lhq.key.start, lhq.key.length); + lhq.value = pr; + + ret = nxt_lvlhsh_insert(&descriptors->hash, &lhq); + if (nxt_slow_path(ret != NXT_OK)) { + njs_internal_error(vm, "lvlhsh insert failed"); + return NXT_ERROR; + } + } + + vm->retval.data.u.object = descriptors; + vm->retval.type = NJS_OBJECT; + vm->retval.data.truth = 1; + + return NXT_OK; +} + + +static njs_ret_t njs_object_get_own_property_names(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) { @@ -2243,6 +2312,14 @@ static const njs_object_prop_t njs_obje NJS_STRING_ARG), }, + /* Object.getOwnPropertyDescriptors(). */ + { + .type = NJS_METHOD, + .name = njs_long_string("getOwnPropertyDescriptors"), + .value = njs_native_function(njs_object_get_own_property_descriptors, 0, + NJS_SKIP_ARG, NJS_OBJECT_ARG), + }, + /* Object.getOwnPropertyNames(). */ { .type = NJS_METHOD, diff -r 3033faf46265 -r 5f273795d8dc njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Wed Mar 27 20:45:39 2019 +0300 +++ b/njs/test/njs_unit_test.c Wed Mar 27 20:49:03 2019 +0300 @@ -8672,6 +8672,22 @@ static njs_unit_test_t njs_test[] = { nxt_string("var o = {}; o[void 0] = 'a'; Object.getOwnPropertyDescriptor(o, undefined).value"), nxt_string("a") }, + { nxt_string("Object.getOwnPropertyDescriptors()"), + nxt_string("TypeError: cannot convert undefined argument to object") }, + + { nxt_string("typeof Object.getOwnPropertyDescriptors(1)"), + nxt_string("object") }, + + { nxt_string("Object.keys(Object.getOwnPropertyDescriptors([]))"), + nxt_string("length") }, + + { nxt_string("Object.getOwnPropertyDescriptors(function(a,b,c) {}).length.value"), + nxt_string("3") }, + + { nxt_string("Object.values(Object.getOwnPropertyDescriptors('abc'))" + ".reduce(function(a, x) { return a += x.value; }, '')"), + nxt_string("abc3") }, + { nxt_string("Object.getOwnPropertyNames()"), nxt_string("TypeError: cannot convert undefined argument to object") }, From auke-jan.h.kok at intel.com Fri Mar 29 18:13:09 2019 From: auke-jan.h.kok at intel.com (Auke Kok) Date: Fri, 29 Mar 2019 11:13:09 -0700 Subject: [PATCH] Enable HTTP/2 by default. Message-ID: <20190329181309.2035-1-auke-jan.h.kok@intel.com> Adds a `nohttp2` option to explicitly disable HTTP/2 support. --- contrib/vim/syntax/nginx.vim | 2 +- src/http/ngx_http_core_module.c | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/contrib/vim/syntax/nginx.vim b/contrib/vim/syntax/nginx.vim index 075b19a..8cff3e0 100644 --- a/contrib/vim/syntax/nginx.vim +++ b/contrib/vim/syntax/nginx.vim @@ -62,7 +62,7 @@ syn match ngxListenComment '#.*$' \ contained \ nextgroup=@ngxListenParams skipwhite skipempty syn keyword ngxListenOptions contained - \ default_server ssl http2 proxy_protocol + \ default_server ssl http2 nohttp2 proxy_protocol \ setfib fastopen backlog rcvbuf sndbuf accept_filter deferred bind \ ipv6only reuseport so_keepalive \ nextgroup=@ngxListenParams skipwhite skipempty diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 6b318dd..c7b5c72 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -3773,6 +3773,9 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) lsopt.backlog = NGX_LISTEN_BACKLOG; lsopt.rcvbuf = -1; lsopt.sndbuf = -1; +#if (NGX_HTTP_V2) + lsopt.http2 = 1; +#endif #if (NGX_HAVE_SETFIB) lsopt.setfib = -1; #endif @@ -3975,7 +3978,6 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) if (ngx_strcmp(value[n].data, "http2") == 0) { #if (NGX_HTTP_V2) - lsopt.http2 = 1; continue; #else ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, @@ -3985,6 +3987,11 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) #endif } + if (ngx_strcmp(value[n].data, "nohttp2") == 0) { + lsopt.http2 = 0; + continue; + } + if (ngx_strcmp(value[n].data, "spdy") == 0) { ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "invalid parameter \"spdy\": " -- 2.21.0 From mdounin at mdounin.ru Fri Mar 29 18:16:01 2019 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 29 Mar 2019 21:16:01 +0300 Subject: [PATCH] Enable HTTP/2 by default. In-Reply-To: <20190329181309.2035-1-auke-jan.h.kok@intel.com> References: <20190329181309.2035-1-auke-jan.h.kok@intel.com> Message-ID: <20190329181601.GO1877@mdounin.ru> Hello! On Fri, Mar 29, 2019 at 11:13:09AM -0700, Auke Kok wrote: > Adds a `nohttp2` option to explicitly disable HTTP/2 support. > --- > contrib/vim/syntax/nginx.vim | 2 +- > src/http/ngx_http_core_module.c | 9 ++++++++- > 2 files changed, 9 insertions(+), 2 deletions(-) > > diff --git a/contrib/vim/syntax/nginx.vim b/contrib/vim/syntax/nginx.vim > index 075b19a..8cff3e0 100644 > --- a/contrib/vim/syntax/nginx.vim > +++ b/contrib/vim/syntax/nginx.vim > @@ -62,7 +62,7 @@ syn match ngxListenComment '#.*$' > \ contained > \ nextgroup=@ngxListenParams skipwhite skipempty > syn keyword ngxListenOptions contained > - \ default_server ssl http2 proxy_protocol > + \ default_server ssl http2 nohttp2 proxy_protocol > \ setfib fastopen backlog rcvbuf sndbuf accept_filter deferred bind > \ ipv6only reuseport so_keepalive > \ nextgroup=@ngxListenParams skipwhite skipempty > diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c > index 6b318dd..c7b5c72 100644 > --- a/src/http/ngx_http_core_module.c > +++ b/src/http/ngx_http_core_module.c > @@ -3773,6 +3773,9 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) > lsopt.backlog = NGX_LISTEN_BACKLOG; > lsopt.rcvbuf = -1; > lsopt.sndbuf = -1; > +#if (NGX_HTTP_V2) > + lsopt.http2 = 1; > +#endif [...] Thank you for the patch. No, thanks. -- Maxim Dounin http://mdounin.ru/ From xeioex at nginx.com Sun Mar 31 17:53:58 2019 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Sun, 31 Mar 2019 17:53:58 +0000 Subject: [njs] Refactored out terminal tokens into njs_parser_terminal.c. Message-ID: details: https://hg.nginx.org/njs/rev/1bce636aed3d branches: changeset: 861:1bce636aed3d user: hongzhidao date: Sun Mar 31 22:59:04 2019 +0800 description: Refactored out terminal tokens into njs_parser_terminal.c. diffstat: auto/sources | 1 + njs/njs_parser.c | 901 +------------------------------------------- njs/njs_parser.h | 49 ++- njs/njs_parser_expression.c | 4 +- njs/njs_parser_terminal.c | 866 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 919 insertions(+), 902 deletions(-) diffs (truncated from 1937 to 1000 lines): diff -r 5f273795d8dc -r 1bce636aed3d auto/sources --- a/auto/sources Wed Mar 27 20:49:03 2019 +0300 +++ b/auto/sources Sun Mar 31 22:59:04 2019 +0800 @@ -53,6 +53,7 @@ NJS_LIB_SRCS=" \ njs/njs_lexer.c \ njs/njs_lexer_keyword.c \ njs/njs_parser.c \ + njs/njs_parser_terminal.c \ njs/njs_parser_expression.c \ njs/njs_generator.c \ njs/njs_disassembler.c \ diff -r 5f273795d8dc -r 1bce636aed3d njs/njs_parser.c --- a/njs/njs_parser.c Wed Mar 27 20:49:03 2019 +0300 +++ b/njs/njs_parser.c Sun Mar 31 22:59:04 2019 +0800 @@ -67,21 +67,6 @@ static nxt_int_t njs_parser_import_hoist static nxt_int_t njs_parser_export_sink(njs_vm_t *vm, njs_parser_t *parser); static njs_token_t njs_parser_grouping_expression(njs_vm_t *vm, njs_parser_t *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, - uint32_t token_line); -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, - 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, - njs_parser_t *parser, njs_token_t token); #define njs_parser_chain_current(parser) \ @@ -93,15 +78,6 @@ static njs_token_t njs_parser_unexpected #define njs_parser_chain_top_set(parser, node) \ (parser)->scope->top = node -#define njs_parser_key_hash(parser) \ - (parser)->lexer->lexer_token->key_hash - -#define njs_parser_number(parser) \ - (parser)->lexer->lexer_token->number - -#define njs_parser_token_line(parser) \ - (parser)->lexer->lexer_token->token_line - nxt_int_t njs_parser(njs_vm_t *vm, njs_parser_t *parser, njs_parser_t *prev) @@ -515,36 +491,6 @@ njs_parser_block(njs_vm_t *vm, njs_parse } -nxt_inline njs_token_t -njs_parser_match(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token, - njs_token_t match) -{ - if (nxt_fast_path(token == match)) { - return njs_parser_token(vm, parser); - } - - return njs_parser_unexpected_token(vm, parser, token); -} - - -nxt_inline njs_variable_t * -njs_parser_variable_add(njs_vm_t *vm, njs_parser_t *parser, - njs_variable_type_t type) -{ - return njs_variable_add(vm, parser->scope, njs_parser_text(parser), - njs_parser_key_hash(parser), type); -} - -nxt_inline njs_ret_t -njs_parser_variable_reference(njs_vm_t *vm, njs_parser_t *parser, - njs_parser_node_t *node, njs_reference_type_t type) -{ - return njs_variable_reference(vm, parser->scope, node, - njs_parser_text(parser), - njs_parser_key_hash(parser), type); -} - - static njs_token_t njs_parser_labelled_statement(njs_vm_t *vm, njs_parser_t *parser) { @@ -688,7 +634,7 @@ njs_parser_function_declaration(njs_vm_t } -static njs_token_t +njs_token_t njs_parser_function_expression(njs_vm_t *vm, njs_parser_t *parser) { njs_ret_t ret; @@ -2226,849 +2172,6 @@ njs_parser_property_token(njs_vm_t *vm, } -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_parser_node_t *node; - - if (token == NJS_TOKEN_OPEN_PARENTHESIS) { - - token = njs_parser_token(vm, parser); - if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { - return token; - } - - token = njs_parser_expression(vm, parser, token); - if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { - return token; - } - - return njs_parser_match(vm, parser, token, NJS_TOKEN_CLOSE_PARENTHESIS); - } - - if (token == NJS_TOKEN_FUNCTION) { - return njs_parser_function_expression(vm, parser); - } - - switch (token) { - - 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; - } - - parser->node = node; - - token = njs_parser_object(vm, parser, node); - - if (parser->node != node) { - /* The object is not empty. */ - node->left = parser->node; - parser->node = node; - } - - return token; - - case NJS_TOKEN_OPEN_BRACKET: - 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); - - if (parser->node != node) { - /* The array is not empty. */ - node->left = parser->node; - parser->node = node; - } - - 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'", njs_parser_text(parser)); - - break; - - case NJS_TOKEN_STRING: - nxt_thread_log_debug("JS: '%V'", njs_parser_text(parser)); - - 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; - } - - break; - - case NJS_TOKEN_ESCAPE_STRING: - nxt_thread_log_debug("JS: '%V'", njs_parser_text(parser)); - - 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)) { - return ret; - } - - break; - - case NJS_TOKEN_UNTERMINATED_STRING: - njs_parser_syntax_error(vm, parser, "Unterminated string \"%V\"", - njs_parser_text(parser)); - - return NJS_TOKEN_ILLEGAL; - - case NJS_TOKEN_NUMBER: - num = njs_parser_number(parser); - 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); - - break; - - case NJS_TOKEN_BOOLEAN: - num = njs_parser_number(parser); - nxt_thread_log_debug("JS: boolean: %V", njs_parser_text(parser)); - - node = njs_parser_node_new(vm, parser, NJS_TOKEN_BOOLEAN); - if (nxt_slow_path(node == NULL)) { - return NJS_TOKEN_ERROR; - } - - if (num == 0) { - node->u.value = njs_value_false; - - } else { - node->u.value = njs_value_true; - } - - break; - - default: - node = njs_parser_reference(vm, parser, token, - njs_parser_text(parser), - njs_parser_key_hash(parser), - njs_parser_token_line(parser)); - - if (nxt_slow_path(node == NULL)) { - return NJS_TOKEN_ERROR; - } - - break; - } - - parser->node = node; - - return njs_parser_token(vm, 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, uint32_t token_line) -{ - 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"); - - node->u.value = njs_value_null; - break; - - case NJS_TOKEN_UNDEFINED: - nxt_thread_log_debug("JS: undefined"); - - node->u.value = njs_value_undefined; - break; - - case NJS_TOKEN_THIS: - nxt_thread_log_debug("JS: this"); - - scope = parser->scope; - - while (scope->type != NJS_SCOPE_GLOBAL) { - if (scope->type == NJS_SCOPE_FUNCTION) { - node->index = NJS_INDEX_THIS; - break; - } - - scope = scope->parent; - } - - if (node->index == NJS_INDEX_THIS) { - break; - } - - node->token = NJS_TOKEN_GLOBAL_THIS; - - /* Fall through. */ - - case NJS_TOKEN_NJS: - case NJS_TOKEN_MATH: - case NJS_TOKEN_JSON: - 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", name); - - return NULL; - } - - parser->scope->arguments_object = 1; - - break; - - case NJS_TOKEN_OBJECT_CONSTRUCTOR: - node->index = NJS_INDEX_OBJECT; - break; - - case NJS_TOKEN_ARRAY_CONSTRUCTOR: - node->index = NJS_INDEX_ARRAY; - break; - - case NJS_TOKEN_BOOLEAN_CONSTRUCTOR: - node->index = NJS_INDEX_BOOLEAN; - break; - - case NJS_TOKEN_NUMBER_CONSTRUCTOR: - node->index = NJS_INDEX_NUMBER; - break; - - case NJS_TOKEN_STRING_CONSTRUCTOR: - node->index = NJS_INDEX_STRING; - break; - - case NJS_TOKEN_FUNCTION_CONSTRUCTOR: - node->index = NJS_INDEX_FUNCTION; - break; - - case NJS_TOKEN_REGEXP_CONSTRUCTOR: - node->index = NJS_INDEX_REGEXP; - break; - - case NJS_TOKEN_DATE_CONSTRUCTOR: - node->index = NJS_INDEX_DATE; - break; - - case NJS_TOKEN_ERROR_CONSTRUCTOR: - node->index = NJS_INDEX_OBJECT_ERROR; - break; - - case NJS_TOKEN_EVAL_ERROR_CONSTRUCTOR: - node->index = NJS_INDEX_OBJECT_EVAL_ERROR; - break; - - case NJS_TOKEN_INTERNAL_ERROR_CONSTRUCTOR: - node->index = NJS_INDEX_OBJECT_INTERNAL_ERROR; - break; - - case NJS_TOKEN_RANGE_ERROR_CONSTRUCTOR: - node->index = NJS_INDEX_OBJECT_RANGE_ERROR; - break; - - case NJS_TOKEN_REF_ERROR_CONSTRUCTOR: - node->index = NJS_INDEX_OBJECT_REF_ERROR; - break; - - case NJS_TOKEN_SYNTAX_ERROR_CONSTRUCTOR: - node->index = NJS_INDEX_OBJECT_SYNTAX_ERROR; - break; - - case NJS_TOKEN_TYPE_ERROR_CONSTRUCTOR: - node->index = NJS_INDEX_OBJECT_TYPE_ERROR; - break; - - case NJS_TOKEN_URI_ERROR_CONSTRUCTOR: - node->index = NJS_INDEX_OBJECT_URI_ERROR; - break; - - case NJS_TOKEN_MEMORY_ERROR_CONSTRUCTOR: - node->index = NJS_INDEX_OBJECT_MEMORY_ERROR; - break; - - case NJS_TOKEN_EVAL: - case NJS_TOKEN_TO_STRING: - case NJS_TOKEN_IS_NAN: - case NJS_TOKEN_IS_FINITE: - case NJS_TOKEN_PARSE_INT: - case NJS_TOKEN_PARSE_FLOAT: - case NJS_TOKEN_ENCODE_URI: - case NJS_TOKEN_ENCODE_URI_COMPONENT: - case NJS_TOKEN_DECODE_URI: - case NJS_TOKEN_DECODE_URI_COMPONENT: - case NJS_TOKEN_REQUIRE: - case NJS_TOKEN_SET_TIMEOUT: - case NJS_TOKEN_SET_IMMEDIATE: - case NJS_TOKEN_CLEAR_TIMEOUT: - 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); - - node->token_line = token_line; - - 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: - (void) njs_parser_unexpected_token(vm, parser, token); - return NULL; - } - - return 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) -{ - njs_ret_t ret; - nxt_uint_t index; - njs_variable_t *var; - njs_parser_scope_t *scope; - - scope = njs_parser_global_scope(vm); - - var = njs_variable_add(vm, scope, name, hash, NJS_VARIABLE_VAR); - if (nxt_slow_path(var == NULL)) { - return NXT_ERROR; - } - - /* TODO: once */ - 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 NXT_ERROR; - } - - return NXT_OK; -} - - -/* - * 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, token_line; - nxt_str_t name; - njs_token_t token; - 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; - token_line = 0; - - 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(vm, parser); - - name.start = NULL; - - switch (token) { - - case NJS_TOKEN_CLOSE_BRACE: - return njs_parser_token(vm, parser); - - case NJS_TOKEN_NAME: - name = *njs_parser_text(parser); - - hash = njs_parser_key_hash(parser); - token_line = njs_parser_token_line(parser); - - token = njs_parser_token(vm, parser); - break; - - 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; - } - - propref = njs_parser_node_new(vm, parser, NJS_TOKEN_PROPERTY); - if (nxt_slow_path(propref == NULL)) { - return NJS_TOKEN_ERROR; - } - - propref->left = object; - propref->right = parser->node; - - 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, token_line); - 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); - if (nxt_slow_path(assign == NULL)) { - return NJS_TOKEN_ERROR; - } - - assign->u.operation = njs_vmcode_move; - assign->left = propref; - assign->right = expression; - - stmt = njs_parser_node_new(vm, parser, NJS_TOKEN_STATEMENT); - if (nxt_slow_path(stmt == NULL)) { - return NJS_TOKEN_ERROR; - } - - stmt->left = left; - stmt->right = assign; - - parser->node = stmt; - - left = stmt; - - if (token == NJS_TOKEN_CLOSE_BRACE) { - return njs_parser_token(vm, parser); - } - - if (nxt_slow_path(token != NJS_TOKEN_COMMA)) { - return NJS_TOKEN_ILLEGAL; - } - } -} - - -static njs_token_t -njs_parser_array(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *obj) -{ - nxt_uint_t index; - njs_token_t token; - njs_parser_node_t *stmt, *assign, *object, *propref, *left, *node; - - index = 0; - left = NULL; - - for ( ;; ) { - token = njs_parser_token(vm, parser); - if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { - return token; - } - - if (token == NJS_TOKEN_CLOSE_BRACKET) { - break; - } - - if (token == NJS_TOKEN_COMMA) { - obj->ctor = 1; - index++; - continue; - } - - 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 = index; - node->u.value.type = NJS_NUMBER; - node->u.value.data.truth = (index != 0); - index++; - - 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; - } - - propref->left = object; - propref->right = node; - - token = njs_parser_assignment_expression(vm, parser, token); - if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { - return token; - } - - assign = njs_parser_node_new(vm, parser, NJS_TOKEN_ASSIGNMENT); - if (nxt_slow_path(assign == NULL)) { - return NJS_TOKEN_ERROR; - } - - assign->u.operation = njs_vmcode_move; - assign->left = propref; - assign->right = parser->node; - - stmt = njs_parser_node_new(vm, parser, NJS_TOKEN_STATEMENT); - if (nxt_slow_path(stmt == NULL)) { - return NJS_TOKEN_ERROR; - } - - stmt->left = left; - stmt->right = assign; - - parser->node = stmt; - left = stmt; - - obj->ctor = 0; - - if (token == NJS_TOKEN_CLOSE_BRACKET) { - break; - } - - if (nxt_slow_path(token != NJS_TOKEN_COMMA)) { - return NJS_TOKEN_ILLEGAL; - } - } - - obj->u.length = index; - - return njs_parser_token(vm, parser); -} - - -static nxt_int_t -njs_parser_string_create(njs_vm_t *vm, njs_value_t *value) -{ - u_char *p; - ssize_t length; - nxt_str_t *src; - - src = njs_parser_text(vm->parser); - - length = nxt_utf8_length(src->start, src->length); - - if (nxt_slow_path(length < 0)) { - length = 0; - } - - p = njs_string_alloc(vm, value, src->length, length); - - if (nxt_fast_path(p != NULL)) { - memcpy(p, src->start, src->length); - - if (length > NJS_STRING_MAP_STRIDE && (size_t) length != src->length) { - njs_string_offset_map_init(p, src->length); - } - - return NXT_OK; - } - - return NXT_ERROR; -} - - -static njs_token_t -njs_parser_escape_string_create(njs_vm_t *vm, njs_parser_t *parser, - njs_value_t *value) -{ - u_char c, *start, *dst; - size_t size,length, hex_length; - uint64_t u; - nxt_str_t *string; - const u_char *p, *src, *end, *hex_end; - - start = NULL; - dst = NULL; - - for ( ;; ) { - /* - * The loop runs twice: at the first step string size and - * UTF-8 length are evaluated. Then the string is allocated - * and at the second step string content is copied. - */ - size = 0; - length = 0; - - string = njs_parser_text(parser); - src = string->start; - end = src + string->length; - - while (src < end) { - c = *src++; - - if (c == '\\') { - /* - * Testing "src == end" is not required here - * since this has been already tested by lexer. - */ - c = *src++; - - switch (c) { - - case 'u': - hex_length = 4; - /* - * A character after "u" can be safely tested here - * because there is always a closing quote at the - * end of string: ...\u". - */ - if (*src != '{') { - goto hex_length_test; - } - - src++; - hex_length = 0; - hex_end = end; - - goto hex; - - case 'x': - hex_length = 2; - goto hex_length_test; - - case '0': - c = '\0'; - break; - - case 'b': - c = '\b'; - break; - - case 'f': - c = '\f'; - break; - - case 'n': - c = '\n'; - break; - - case 'r': - c = '\r'; - break; - - case 't': - c = '\t'; - break; - - case 'v': - c = '\v'; - break; - - case '\r': - /* - * A character after "\r" can be safely tested here - * because there is always a closing quote at the - * end of string: ...\\r". - */ - if (*src == '\n') { - src++; - } - - continue; - - case '\n': - continue; - - default: - break; - } - } - - size++; - length++; - - if (dst != NULL) { - *dst++ = c; - } - - continue; - - hex_length_test: - - hex_end = src + hex_length; - - if (hex_end > end) { - goto invalid; - } - - hex: - - p = src; - u = njs_number_hex_parse(&src, hex_end); - - if (hex_length != 0) { - if (src != hex_end) { - goto invalid; - } - - } else { - if (src == p || (src - p) > 6) { - goto invalid; - } - - if (src == end || *src++ != '}') { - goto invalid; - } - } - - size += nxt_utf8_size(u); - length++; - - if (dst != NULL) { - dst = nxt_utf8_encode(dst, (uint32_t) u); - if (dst == NULL) { - goto invalid; - } - } - } - - if (start != NULL) { - if (length > NJS_STRING_MAP_STRIDE && length != size) { - njs_string_offset_map_init(start, size); - } - - return NJS_TOKEN_STRING; - } - - start = njs_string_alloc(vm, value, size, length); - if (nxt_slow_path(start == NULL)) { - return NJS_TOKEN_ERROR; - } - - dst = start; - } - -invalid: - - njs_parser_syntax_error(vm, parser, "Invalid Unicode code point \"%V\"", - njs_parser_text(parser)); - - return NJS_TOKEN_ILLEGAL; -} - - nxt_bool_t njs_parser_has_side_effect(njs_parser_node_t *node) { @@ -3100,7 +2203,7 @@ njs_parser_has_side_effect(njs_parser_no } -static njs_token_t +njs_token_t njs_parser_unexpected_token(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) { diff -r 5f273795d8dc -r 1bce636aed3d njs/njs_parser.h --- a/njs/njs_parser.h Wed Mar 27 20:49:03 2019 +0300 +++ b/njs/njs_parser.h Sun Mar 31 22:59:04 2019 +0800 @@ -77,24 +77,26 @@ struct njs_parser_s { 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, - njs_parser_node_t *parent); njs_token_t njs_parser_expression(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token); njs_token_t njs_parser_var_expression(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token); njs_token_t njs_parser_assignment_expression(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token); +njs_token_t njs_parser_function_expression(njs_vm_t *vm, njs_parser_t *parser); njs_token_t njs_parser_module_lambda(njs_vm_t *vm, njs_parser_t *parser); njs_token_t njs_parser_terminal(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token); njs_token_t njs_parser_property_token(njs_vm_t *vm, njs_parser_t *parser); +nxt_int_t njs_parser_string_create(njs_vm_t *vm, njs_value_t *value); njs_token_t njs_parser_lambda_statements(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token); 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); nxt_bool_t njs_parser_has_side_effect(njs_parser_node_t *node); +njs_token_t njs_parser_unexpected_token(njs_vm_t *vm, njs_parser_t *parser, + njs_token_t token); u_char *njs_parser_trace_handler(nxt_trace_t *trace, nxt_trace_data_t *td, u_char *start); void njs_parser_lexer_error(njs_vm_t *vm, njs_parser_t *parser, @@ -115,6 +117,18 @@ void njs_parser_node_error(njs_vm_t *vm, &(parser)->lexer->lexer_token->text +#define njs_parser_key_hash(parser) \ + (parser)->lexer->lexer_token->key_hash + + +#define njs_parser_number(parser) \ + (parser)->lexer->lexer_token->number +