From ladislav.macoun at cdn77.com Fri Jan 3 11:03:59 2020 From: ladislav.macoun at cdn77.com (Ladislav Macoun) Date: Fri, 3 Jan 2020 12:03:59 +0100 Subject: NGINX does not update cache entry headers on 304 response Message-ID: <9554B4AB-AA33-43C8-BE30-8B848A28E8C8@cdn77.com> Hello list, NGINX currently does not update the Expires HTTP header during cache revalidation after receiving 304 response from the origin. This may lead to receiving a response from cache with invalid Expires header, and not loading content from the browser disk cache. It looks like this behaviour is intended as Maxim states this in the commit message ?As of now, no attempts are made to merge headers given in a 304 response during cache revalidation with headers previously stored in a cache item. Headers in a 304 response are only used to calculate new validity time of a cache item.?[1] This behaviour seems to present until now, the cache entry only updates the file cache header. And keeps the old response headers. This behaviour may violate the RFC for 304 Not Modified Response. If a cache uses a received 304 response to update a cache entry, the cache MUST update the entry to reflect any new field values given in the response. [2] As I understand this, the cache MUST update the entry fields, which in this case are only headers since origin does not resend the body. I would like to ask if this behaviour is correct and my interpretation of the RFC is wrong, or if this behaviour is really intended or there is a bug somewhere else. [1] https://github.com/nginx/nginx/commit/1ac2693a33bb65c6b0d777584ad8024aa743ee88 [2] https://tools.ietf.org/html/rfc2616#section-10.3.5 Yours faithfully, Ladislav Macoun From joe.konno at linux.intel.com Fri Jan 3 22:39:29 2020 From: joe.konno at linux.intel.com (=?utf-8?q?Joe_Konno?=) Date: Fri, 03 Jan 2020 14:39:29 -0800 Subject: [PATCH nginx v2] remove ngx_cpuinfo, use sysconf or define In-Reply-To: References: Message-ID: # HG changeset patch # User Joe Konno # Date 1578075036 28800 # Fri Jan 03 10:10:36 2020 -0800 # Node ID b66ee34cea2f539bb8ce4986d6bd332f75ee06b6 # Parent f1720934c45be1c6469841a55d1f31fe9a630c85 remove ngx_cpuinfo, use sysconf or define Function ngx_cpuinfo() is used to (sub-optimally) determine the value of ngx_cacheline_size on x86 hardware. On hardware running Linux, there may be a sysconf call that correctly reports the cache line size using architecturally appropriate methods-- for x86 hardware, the CPUID instruction. Therefore, ngx_cpuinfo is no longer needed. If said sysconf call is unavailable, set ngx_cachline_size to defined NGX_CPU_CACHE_LINE, the value of which is determined at configure time. Signed-off-by: Joe Konno diff -r f1720934c45b -r b66ee34cea2f auto/sources --- a/auto/sources Fri Dec 27 19:43:01 2019 +0300 +++ b/auto/sources Fri Jan 03 10:10:36 2020 -0800 @@ -71,7 +71,6 @@ src/core/ngx_cycle.c \ src/core/ngx_spinlock.c \ src/core/ngx_rwlock.c \ - src/core/ngx_cpuinfo.c \ src/core/ngx_conf_file.c \ src/core/ngx_module.c \ src/core/ngx_resolver.c \ diff -r f1720934c45b -r b66ee34cea2f src/core/ngx_core.h --- a/src/core/ngx_core.h Fri Dec 27 19:43:01 2019 +0300 +++ b/src/core/ngx_core.h Fri Jan 03 10:10:36 2020 -0800 @@ -102,7 +102,6 @@ #define ngx_max(val1, val2) ((val1 < val2) ? (val2) : (val1)) #define ngx_min(val1, val2) ((val1 > val2) ? (val2) : (val1)) -void ngx_cpuinfo(void); #if (NGX_HAVE_OPENAT) #define NGX_DISABLE_SYMLINKS_OFF 0 diff -r f1720934c45b -r b66ee34cea2f src/core/ngx_cpuinfo.c --- a/src/core/ngx_cpuinfo.c Fri Dec 27 19:43:01 2019 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,139 +0,0 @@ - -/* - * Copyright (C) Igor Sysoev - * Copyright (C) Nginx, Inc. - */ - - -#include -#include - - -#if (( __i386__ || __amd64__ ) && ( __GNUC__ || __INTEL_COMPILER )) - - -static ngx_inline void ngx_cpuid(uint32_t i, uint32_t *buf); - - -#if ( __i386__ ) - -static ngx_inline void -ngx_cpuid(uint32_t i, uint32_t *buf) -{ - - /* - * we could not use %ebx as output parameter if gcc builds PIC, - * and we could not save %ebx on stack, because %esp is used, - * when the -fomit-frame-pointer optimization is specified. - */ - - __asm__ ( - - " mov %%ebx, %%esi; " - - " cpuid; " - " mov %%eax, (%1); " - " mov %%ebx, 4(%1); " - " mov %%edx, 8(%1); " - " mov %%ecx, 12(%1); " - - " mov %%esi, %%ebx; " - - : : "a" (i), "D" (buf) : "ecx", "edx", "esi", "memory" ); -} - - -#else /* __amd64__ */ - - -static ngx_inline void -ngx_cpuid(uint32_t i, uint32_t *buf) -{ - uint32_t eax, ebx, ecx, edx; - - __asm__ ( - - "cpuid" - - : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (i) ); - - buf[0] = eax; - buf[1] = ebx; - buf[2] = edx; - buf[3] = ecx; -} - - -#endif - - -/* auto detect the L2 cache line size of modern and widespread CPUs */ - -void -ngx_cpuinfo(void) -{ - u_char *vendor; - uint32_t vbuf[5], cpu[4], model; - - vbuf[0] = 0; - vbuf[1] = 0; - vbuf[2] = 0; - vbuf[3] = 0; - vbuf[4] = 0; - - ngx_cpuid(0, vbuf); - - vendor = (u_char *) &vbuf[1]; - - if (vbuf[0] == 0) { - return; - } - - ngx_cpuid(1, cpu); - - if (ngx_strcmp(vendor, "GenuineIntel") == 0) { - - switch ((cpu[0] & 0xf00) >> 8) { - - /* Pentium */ - case 5: - ngx_cacheline_size = 32; - break; - - /* Pentium Pro, II, III */ - case 6: - ngx_cacheline_size = 32; - - model = ((cpu[0] & 0xf0000) >> 8) | (cpu[0] & 0xf0); - - if (model >= 0xd0) { - /* Intel Core, Core 2, Atom */ - ngx_cacheline_size = 64; - } - - break; - - /* - * Pentium 4, although its cache line size is 64 bytes, - * it prefetches up to two cache lines during memory read - */ - case 15: - ngx_cacheline_size = 128; - break; - } - - } else if (ngx_strcmp(vendor, "AuthenticAMD") == 0) { - ngx_cacheline_size = 64; - } -} - -#else - - -void -ngx_cpuinfo(void) -{ -} - - -#endif diff -r f1720934c45b -r b66ee34cea2f src/os/unix/ngx_posix_init.c --- a/src/os/unix/ngx_posix_init.c Fri Dec 27 19:43:01 2019 +0300 +++ b/src/os/unix/ngx_posix_init.c Fri Jan 03 10:10:36 2020 -0800 @@ -51,10 +51,20 @@ } ngx_pagesize = getpagesize(); - ngx_cacheline_size = NGX_CPU_CACHE_LINE; for (n = ngx_pagesize; n >>= 1; ngx_pagesize_shift++) { /* void */ } +#if (NGX_HAVE_LEVEL1_DCACHE_LINESIZE) + size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE); + if (size > 0) { + ngx_cacheline_size = size; + } else { + ngx_cacheline_size = NGX_CPU_CACHE_LINE; + } +#else + ngx_cacheline_size = NGX_CPU_CACHE_LINE; +#endif + #if (NGX_HAVE_SC_NPROCESSORS_ONLN) if (ngx_ncpu == 0) { ngx_ncpu = sysconf(_SC_NPROCESSORS_ONLN); @@ -65,15 +75,6 @@ ngx_ncpu = 1; } -#if (NGX_HAVE_LEVEL1_DCACHE_LINESIZE) - size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE); - if (size > 0) { - ngx_cacheline_size = size; - } -#endif - - ngx_cpuinfo(); - if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) { ngx_log_error(NGX_LOG_ALERT, log, errno, "getrlimit(RLIMIT_NOFILE) failed"); From mdounin at mdounin.ru Fri Jan 3 23:01:14 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 4 Jan 2020 02:01:14 +0300 Subject: NGINX does not update cache entry headers on 304 response In-Reply-To: <9554B4AB-AA33-43C8-BE30-8B848A28E8C8@cdn77.com> References: <9554B4AB-AA33-43C8-BE30-8B848A28E8C8@cdn77.com> Message-ID: <20200103230114.GU12894@mdounin.ru> Hello! On Fri, Jan 03, 2020 at 12:03:59PM +0100, Ladislav Macoun wrote: > NGINX currently does not update the Expires HTTP header during > cache revalidation after receiving 304 response from the origin. > This may lead to receiving a response from cache with invalid > Expires header, and not loading content from the browser disk > cache. > > It looks like this behaviour is intended as Maxim states this in > the commit message ?As of now, no attempts are made to merge > headers given in a 304 response during cache revalidation with > headers previously stored in a cache item. Headers in a 304 > response are only used to calculate new validity time of a cache > item.?[1] > > This behaviour seems to present until now, the cache entry only > updates the file cache header. And keeps the old response > headers. Yes. > This behaviour may violate the RFC for 304 Not Modified Response. Yes. If you want strictly RFC-complaint behaviour, you are free to keep the default value of the proxy_cache_revalidate directive, that is, keep it off. > If a cache uses a received 304 response to update a cache entry, > the cache MUST update the entry to reflect any new field values > given in the response. [2] > > As I understand this, the cache MUST update the entry fields, > which in this case are only headers since origin does not resend > the body. > > I would like to ask if this behaviour is correct and my > interpretation of the RFC is wrong, or if this behaviour is > really intended or there is a bug somewhere else. It is believed that handling of 304 responses as required by RFC is quite problematic for nginx cache storage model, and not needed in most cases. Given that, we intentionally ignore RFC requirements here, and keep the proxy_cache_revalidate directive switched off by default. -- Maxim Dounin http://mdounin.ru/ From rpaprocki at fearnothingproductions.net Sat Jan 4 03:59:58 2020 From: rpaprocki at fearnothingproductions.net (Robert Paprocki) Date: Fri, 3 Jan 2020 19:59:58 -0800 Subject: Dumping cyclic error_log memory Message-ID: Hello, http://nginx.org/en/docs/debugging_log.html and associated literature instruct to dump the contents of a ?memory? error_log target via gdb memory dump. How is it possible to do this for a given nginx worker process, when other worker processes are serving connections simultaneously and generating error logs to the shared memory zone (at least, I?m assuming it?s shared by all workers, since it?s allocated from the conf pool during configuration parsing). Is it possible other workers are memcpy() with a dst pointing to the buffer where a simultaneous gdb memory dump is executing? Wouldn?t this potentially cause corruption of the read data? The origin of my question was hacking on a routine that would dump the memory buffer to a file from within nginx directly, rather than probing into the process with gdb- at first it looks trivial to just write() the whole buffer, but since there?s no synchronization mechanism, I anticipate this would cause problems in a busy environment. Sent from my iPhone -------------- next part -------------- An HTML attachment was scrubbed... URL: From aaron.bedra at gmail.com Sun Jan 5 05:53:45 2020 From: aaron.bedra at gmail.com (Aaron Bedra) Date: Sat, 04 Jan 2020 23:53:45 -0600 Subject: nginx - get value of the header - x_forwarded_for in Nginx module (Naxsi) In-Reply-To: References: Message-ID: <5e072adcae602b28da5887d893e8f84ec9e25c29.camel@gmail.com> The repsheet module does some of what you are looking for. You can look at the XFF parsing at https://github.com/repsheet/repsheet-nginx/blob/master/ngx_http_repsheet_xff.c id="-x-evo-selection-start-marker"> On Mon, 2019-12-30 at 22:44 +0100, Marcin Kozlowski wrote: > OK, this helped: > > https://github.com/yakantosat/nginx-example/blob/master/ngx_hash_test.c > > Thanks, > > > > On Mon, Dec 30, 2019 at 4:47 PM Marcin Kozlowski > wrote: > > I don't work with NGINX and modules and C daily. > > > > Still struggling with it. Feel free to contact me via the list or > > to avoid spamming privately. Help will be greatly appreciated. > > > > Trying to add whitelisting of IP to NAXSI > > > > https://github.com/nbs-system/naxsi > > > > > > > > How can I add simply one entry being IP to headers_ar? > > > > > > > > headers_ar = ngx_array_create(cf->pool, 1, > > sizeof(ngx_hash_key_t)); > > > > ngx_array_t *headers_ar_c; > > headers_ar_c = ngx_array_push(headers_ar); > > > > hash_init.key = &ngx_hash_key_lc; > > hash_init.pool = cf->pool; > > hash_init.temp_pool = NULL; > > hash_init.max_size = 1024; > > hash_init.bucket_size = 512; > > > > > > dlc->passr_headers_hash = (ngx_hash_t*) ngx_pcalloc(cf->pool, > > sizeof(ngx_hash_t)); > > hash_init.hash = dlc->passr_headers_hash; > > hash_init.name = "passr_headers_hash"; > > > > if (ngx_hash_init(&hash_init, (ngx_hash_key_t*) headers_ar- > > >elts, > > headers_ar->nelts) != NGX_OK) { > > ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "$HEADERS hashtable > > init failed"); /* LCOV_EXCL_LINE */ > > return (NGX_ERROR); /* LCOV_EXCL_LINE */ > > } > > > > else { > > NX_LOG_DEBUG(_debug_whitelist, NGX_LOG_EMERG, cf, 0, > > "$HEADERS hashtable init successed %d !", > > dlc->passr_headers_hash->size); > > } > > > > > > > > return (NGX_OK); > > > > > > > > > > > > Later I have a function that looks for it in hash > > > > Find in hash function: > > > > ngx_http_pass_rule_t * > > nx_find_pass_in_hash( > > ngx_http_request_t *req, > > ngx_str_t *mstr, > > ngx_http_dummy_loc_conf_t *cf, > > enum DUMMY_MATCH_ZONE zone) > > { > > ngx_http_pass_rule_t *b = NULL; > > > > ngx_uint_t key; > > > > ngx_str_t scratch = {.data = mstr->data, .len = mstr->len}; > > > > ngx_str_t k1 = ngx_string("key1"); > > key = ngx_hash_key(scratch.data, scratch.len); > > > > b = (ngx_http_pass_rule_t*) ngx_hash_find(cf->passr_headers_hash, > > key, k1.data, k1.len); > > if (b == NULL) { > > /* key not found */ > > NX_DEBUG(_debug_custom_score, NGX_LOG_DEBUG_HTTP, req- > > >connection->log, 0, > > "find hash 1"); > > > > }else{ > > NX_DEBUG(_debug_custom_score, NGX_LOG_DEBUG_HTTP, req- > > >connection->log, 0, > > "find hash 2"); > > > > > > } > > > > return b; > > > > } > > Thanks, > > > > > > > > > > On Sun, Dec 29, 2019 at 3:27 AM Hung Nguyen < > > hungnv at opensource.com.vn> wrote: > > > Hello, > > > I suggest you to read nginx development guide which is available > > > on nginx.org. > > > > > > About getting x forward for headers, if you take a look at some > > > built in module there?s already exist implementation which takes > > > the headers and returns an array. > > > > > > --H?ng > > > > On Dec 29, 2019, at 03:49, Robert Paprocki < > > > > rpaprocki at fearnothingproductions.net> wrote: > > > > > > > > ?The array has 0 nelts because you haven?t added anything to > > > > do. nelts is the number of elements in the array, not the size > > > > of the array. > > > > Add an element to the array with ngx_array_push(). > > > > > > > > > On Dec 28, 2019, at 11:35, Marcin Kozlowski < > > > > > marcinguy at gmail.com> wrote: > > > > > > > > > > ?Still have few questions. Help would be great > > > > > > > > > > Beginner in writing NGINX modules > > > > > > > > > > Have this question > > > > > > > > > > 1) How do I create array, add element to it and than create a > > > > > hashtable from it. > > > > > > > > > > Below I try to achieve it: > > > > > > > > > > NX_LOG_DEBUG(_debug_whitelist_heavy, > > > > > NGX_LOG_EMERG, cf, 0, > > > > > "finalizing hashtables array %i", dlc- > > > > > >pass_rules->nelts); > > > > > > > > > > headers_ar = ngx_array_create(cf->pool, dlc->pass_rules- > > > > > >nelts, sizeof(ngx_hash_key_t)); > > > > > > > > > > > > > > > > > > > > if (headers_ar) { > > > > > NX_LOG_DEBUG(_debug_readconf, NGX_LOG_EMERG, cf, 0, > > > > > "headers array %i",headers_ar->nelts); > > > > > > > > > > 2) Why headers_ar has 0 elemets > > > > > > > > > > nginx: [emerg] finalizing hashtables array 6 in > > > > > /etc/nginx/nginx.conf:124 > > > > > nginx: [emerg] headers array 0 in /etc/nginx/nginx.conf:124 > > > > > > > > > > > > > > > > > > > > 3) I later want to build hashtable based on this array: > > > > > > > > > > dlc->passr_headers_hash = (ngx_hash_t*) ngx_pcalloc(cf- > > > > > >pool, sizeof(ngx_hash_t)); > > > > > hash_init.hash = dlc->passr_headers_hash; > > > > > hash_init.name = "passr_headers_hash"; > > > > > > > > > > > > > > > > > > > > if (ngx_hash_init(&hash_init, (ngx_hash_key_t*) > > > > > headers_ar->elts, > > > > > headers_ar->nelts) != NGX_OK) { > > > > > ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "$HEADERS > > > > > hashtable init failed"); /* LCOV_EXCL_LINE */ > > > > > return (NGX_ERROR); /* LCOV_EXCL_LINE */ > > > > > } > > > > > > > > > > else { > > > > > NX_LOG_DEBUG(_debug_whitelist, NGX_LOG_EMERG, cf, 0, > > > > > "$HEADERS hashtable init successed %d !", > > > > > dlc->passr_headers_hash->size); > > > > > } > > > > > > > > > > > > > > > > > > > > 4) Can somebody post simple code that > > > > > > > > > > a) creates array > > > > > b) pushes one IP > > > > > c) create hashtable from it > > > > > > > > > > Thanks, > > > > > > > > > > > > > > > > > > > > On Sat, Dec 28, 2019 at 3:36 PM Marcin Kozlowski < > > > > > marcinguy at gmail.com> wrote: > > > > > > Ignore my last post. > > > > > > > > > > > > My error. > > > > > > > > > > > > Thanks, > > > > > > > > > > > > On Fri, Dec 27, 2019 at 11:42 PM Marcin Kozlowski < > > > > > > marcinguy at gmail.com> wrote: > > > > > > > Thanks. Almost got my modifications to NAXSI ready. > > > > > > > > > > > > > > But currently have a blocker with getting just the X- > > > > > > > Forwarded-for IP > > > > > > > > > > > > > > The code below: > > > > > > > > > > > > > > ngx_uint_t n; > > > > > > > ngx_table_elt_t **h; > > > > > > > > > > > > > > ngx_array_t a; > > > > > > > > > > > > > > a = req->headers_in.x_forwarded_for; > > > > > > > > > > > > > > n = a.nelts; > > > > > > > > > > > > > > h = a.elts; > > > > > > > > > > > > > > > > > > > > > > > > > > > > for (i = 0; i > > > > > > > > > > > > > ngx_log_error(NGX_LOG_ERR, req->connection->log, > > > > > > > > > > > > > > 0, "x_forwarded_for: %s", h[i]- > > > > > > > >value.data); > > > > > > > } > > > > > > > > > > > > > > > > > > > > > gets a String with several IP (i.e client, server, > > > > > > > request etc) > > > > > > > > > > > > > > > > > > > > > > > > > > > > Tried to parse the string using strtok(), interating > > > > > > > through it .... but it segfaults. I guess I am missing > > > > > > > some NGINX module knowledge. > > > > > > > > > > > > > > > > > > > > > > > > > > > > How to properly get first string up to first "," from > > > > > > > the h[i]->value.data using NGINX functions/types or > > > > > > > other correct way to do it. > > > > > > > > > > > > > > > > > > > > > > > > > > > > Thanks, > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > On Wed, Dec 25, 2019 at 12:17 PM Ruslan Ermilov < > > > > > > > ru at nginx.com> wrote: > > > > > > > > On Tue, Dec 24, 2019 at 08:00:26PM +0100, Marcin > > > > > > > > Kozlowski wrote: > > > > > > > > > > > > > > > > > Thanks. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Works. For the reference, this is the code I used: > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > ngx_uint_t n; > > > > > > > > > > > > > > > > > ngx_table_elt_t **h; > > > > > > > > > > > > > > > > > ngx_array_t a; > > > > > > > > > > > > > > > > > a = req->headers_in.x_forwarded_for; > > > > > > > > > > > > > > > > > n = a.nelts; > > > > > > > > > > > > > > > > > h = a.elts; > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > for (i = 0; i > > > > > > > > > > > > > > > > ngx_log_error(NGX_LOG_ERR, req->connection->log, > > > > > > > > > > > > > > > > > 0, "x_forwarded_for: %s", h[i]- > > > > > > > > >value.data); > > > > > > > > > > > > > > > > > } > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > BTW What would be the best practice in NGINX NASIX > > > > > > > > module or any other > > > > > > > > > > > > > > > > > module to load a file with hundreds entries of IPs > > > > > > > > (hashmap, or what > > > > > > > > > > > > > > > > > structure would be best?) which should be whitelisted > > > > > > > > later for comparison > > > > > > > > > > > > > > > > > in NASIX module logic. Those IP should never be > > > > > > > > blocked by NAXSI. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > When should I load this file in memory, in which > > > > > > > > component > > > > > > > > > > > > > > > > > /module/function/step? > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Links to some guides/sample code would be also > > > > > > > > appreciated. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Thanks, > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > http://nginx.org/en/docs/http/ngx_http_geo_module.html > > > > > > > > > > > > > > > > _______________________________________________ > > > > > > > > > > > > > > > > nginx-devel mailing list > > > > > > > > > > > > > > > > nginx-devel at nginx.org > > > > > > > > > > > > > > > > http://mailman.nginx.org/mailman/listinfo/nginx-devel > > > > > > > > > > > > > > > > > > _______________________________________________ > > > > > nginx-devel mailing list > > > > > nginx-devel at nginx.org > > > > > http://mailman.nginx.org/mailman/listinfo/nginx-devel > > > > > > > > _______________________________________________ > > > > nginx-devel mailing list > > > > nginx-devel at nginx.org > > > > http://mailman.nginx.org/mailman/listinfo/nginx-devel > > > > > > _______________________________________________ > > > > > > nginx-devel mailing list > > > > > > nginx-devel at nginx.org > > > > > > http://mailman.nginx.org/mailman/listinfo/nginx-devel > > _______________________________________________nginx-devel mailing > listnginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: From grandmaster at al2klimov.de Sun Jan 5 12:10:27 2020 From: grandmaster at al2klimov.de (Alexander A. Klimov) Date: Sun, 5 Jan 2020 13:10:27 +0100 Subject: Patch: Add application/wasm to conf/mime.types In-Reply-To: <20191218150414.GV12894@mdounin.ru> References: <20191218150414.GV12894@mdounin.ru> Message-ID: <1b9a4f0e-70a4-4d06-e7fe-41ce52a2f2d0@al2klimov.de> Hello! Am 18.12.19 um 16:04 schrieb Maxim Dounin: > Hello! > > On Wed, Dec 18, 2019 at 08:22:00AM +0100, Alexander A. Klimov wrote: > > >> # HG changeset patch >> # User Alexander A. Klimov >> # Date 1576652721 -3600 >> # Wed Dec 18 08:05:21 2019 +0100 >> # Node ID 2bcc6c4df1bfd50912bcda85c22201c0f7f6a4c3 >> # Parent 3939483cd1b56b202a99b1db344d9568b0958e67 >> Add application/wasm to conf/mime.types >> >> diff -r 3939483cd1b5 -r 2bcc6c4df1bf conf/mime.types >> --- a/conf/mime.types Thu Dec 05 19:38:06 2019 +0300 >> +++ b/conf/mime.types Wed Dec 18 08:05:21 2019 +0100 >> @@ -51,6 +51,7 @@ >> application/vnd.openxmlformats-officedocument.wordprocessingml.document >> docx; >> application/vnd.wap.wmlc wmlc; >> + application/wasm wasm; >> application/x-7z-compressed 7z; >> application/x-cocoa cco; >> application/x-java-archive-diff jardiff; > > This was already discussed more than once. Please see the > following ticket for some details: > > https://trac.nginx.org/nginx/ticket/1606 > > In particular, I would prefer to wait at least till there is an > official registration of the type. > Is [1] (see below) official enough? It links to [2] which links to [3] which says: > If the Response (...) does not match the `application/wasm` MIME type, the returned promise will be rejected (...). Best, AK [1]: https://www.w3.org/2019/12/pressrelease-wasm-rec.html.en [2]: https://www.w3.org/TR/wasm-core-1/ [3]: https://www.w3.org/TR/wasm-web-api/ From datong.sun at konghq.com Thu Jan 9 00:50:23 2020 From: datong.sun at konghq.com (Datong Sun) Date: Wed, 8 Jan 2020 16:50:23 -0800 Subject: Dumping cyclic error_log memory In-Reply-To: References: Message-ID: Hello Robert, My impression is that the cyclic memory buffer is not shared across workers. The memory is allocated using ngx_pnalloc and that is not the shared memory zone. After fork each worker would have their own buffer instead. Which probably explains why this is only suitable for debugging, as you have to know the worker you are trying to debug in order to access the logs this way. Thanks, Datong On Fri, Jan 3, 2020 at 8:00 PM Robert Paprocki < rpaprocki at fearnothingproductions.net> wrote: > Hello, > > http://nginx.org/en/docs/debugging_log.html and associated literature > instruct to dump the contents of a ?memory? error_log target via gdb memory > dump. How is it possible to do this for a given nginx worker process, when > other worker processes are serving connections simultaneously and > generating error logs to the shared memory zone (at least, I?m assuming > it?s shared by all workers, since it?s allocated from the conf pool during > configuration parsing). Is it possible other workers are memcpy() with a > dst pointing to the buffer where a simultaneous gdb memory dump is > executing? Wouldn?t this potentially cause corruption of the read data? > > The origin of my question was hacking on a routine that would dump the > memory buffer to a file from within nginx directly, rather than probing > into the process with gdb- at first it looks trivial to just write() the > whole buffer, but since there?s no synchronization mechanism, I anticipate > this would cause problems in a busy environment. > > Sent from my iPhone > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -- Datong Sun Systems Engineer @ Kong 150 Spear Street, Suite 1600 San Francisco, CA 94105 -------------- next part -------------- An HTML attachment was scrubbed... URL: From rpaprocki at fearnothingproductions.net Thu Jan 9 02:08:59 2020 From: rpaprocki at fearnothingproductions.net (Robert Paprocki) Date: Wed, 8 Jan 2020 18:08:59 -0800 Subject: Dumping cyclic error_log memory In-Reply-To: References: Message-ID: Whups, thanks :) A curious point then, why ngx_atomic_fetch_add is used to advance the buffer position, if an atomic operation isn?t necessary since the buffer isn?t shared. Is it a style choice? Sent from my iPhone > On Jan 8, 2020, at 16:50, Datong Sun wrote: > > ? > Hello Robert, > > My impression is that the cyclic memory buffer is not shared across workers. The memory is allocated using ngx_pnalloc and that is not the shared memory zone. After fork each worker would have their own buffer instead. > > Which probably explains why this is only suitable for debugging, as you have to know the worker you are trying to debug in order to access the logs this way. > > Thanks, > Datong > >> On Fri, Jan 3, 2020 at 8:00 PM Robert Paprocki wrote: >> Hello, >> >> http://nginx.org/en/docs/debugging_log.html and associated literature instruct to dump the contents of a ?memory? error_log target via gdb memory dump. How is it possible to do this for a given nginx worker process, when other worker processes are serving connections simultaneously and generating error logs to the shared memory zone (at least, I?m assuming it?s shared by all workers, since it?s allocated from the conf pool during configuration parsing). Is it possible other workers are memcpy() with a dst pointing to the buffer where a simultaneous gdb memory dump is executing? Wouldn?t this potentially cause corruption of the read data? >> >> The origin of my question was hacking on a routine that would dump the memory buffer to a file from within nginx directly, rather than probing into the process with gdb- at first it looks trivial to just write() the whole buffer, but since there?s no synchronization mechanism, I anticipate this would cause problems in a busy environment. >> >> Sent from my iPhone >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel > > > -- > > Datong Sun > > Systems Engineer @ Kong > > 150 Spear Street, Suite 1600 > San Francisco, CA 94105 > > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Thu Jan 9 11:45:56 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 9 Jan 2020 14:45:56 +0300 Subject: Dumping cyclic error_log memory In-Reply-To: References: Message-ID: <20200109114556.GW12894@mdounin.ru> Hello! On Wed, Jan 08, 2020 at 06:08:59PM -0800, Robert Paprocki wrote: > A curious point then, why ngx_atomic_fetch_add is used to > advance the buffer position, if an atomic operation isn?t > necessary since the buffer isn?t shared. Is it a style choice? It is to make debug logging work in threads. -- Maxim Dounin http://mdounin.ru/ From alexander.borisov at nginx.com Thu Jan 9 12:21:41 2020 From: alexander.borisov at nginx.com (Alexander Borisov) Date: Thu, 09 Jan 2020 12:21:41 +0000 Subject: [njs] Fixed typo introduced in 61bf7a31e685. Message-ID: details: https://hg.nginx.org/njs/rev/5cd098c6c4de branches: changeset: 1294:5cd098c6c4de user: Alexander Borisov date: Thu Jan 09 15:21:08 2020 +0300 description: Fixed typo introduced in 61bf7a31e685. Found by Coverity (CIDs 1457370, 1457369). diffstat: src/njs_promise.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 74d2b2074ec0 -r 5cd098c6c4de src/njs_promise.c --- a/src/njs_promise.c Fri Dec 27 19:17:26 2019 +0300 +++ b/src/njs_promise.c Thu Jan 09 15:21:08 2020 +0300 @@ -836,7 +836,7 @@ njs_promise_perform_then(njs_vm_t *vm, n rejected_reaction = njs_mp_alloc(vm->mem_pool, sizeof(njs_promise_reaction_t)); - if (njs_slow_path(fulfilled_reaction == NULL)) { + if (njs_slow_path(rejected_reaction == NULL)) { njs_memory_error(vm); return NJS_ERROR; } From xeioex at nginx.com Thu Jan 9 12:55:24 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 09 Jan 2020 12:55:24 +0000 Subject: [njs] Removed dead code in njs_typed_array_get() after 1c3c593cc3fd. Message-ID: details: https://hg.nginx.org/njs/rev/4e3c2f9e4eee branches: changeset: 1295:4e3c2f9e4eee user: Dmitry Volyntsev date: Thu Jan 09 15:54:16 2020 +0300 description: Removed dead code in njs_typed_array_get() after 1c3c593cc3fd. Found by Coverity (CID 1457372). diffstat: src/njs_typed_array.h | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-) diffs (12 lines): diff -r 5cd098c6c4de -r 4e3c2f9e4eee src/njs_typed_array.h --- a/src/njs_typed_array.h Thu Jan 09 15:21:08 2020 +0300 +++ b/src/njs_typed_array.h Thu Jan 09 15:54:16 2020 +0300 @@ -86,8 +86,6 @@ njs_typed_array_get(const njs_typed_arra return buffer->u.f64[index]; } - - return NAN; } From xeioex at nginx.com Thu Jan 9 12:55:26 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 09 Jan 2020 12:55:26 +0000 Subject: [njs] Fixed integer overflow in njs_typed_array_constructor(). Message-ID: details: https://hg.nginx.org/njs/rev/aa9a42bfc727 branches: changeset: 1296:aa9a42bfc727 user: Dmitry Volyntsev date: Thu Jan 09 15:54:52 2020 +0300 description: Fixed integer overflow in njs_typed_array_constructor(). Found by Coverity (CID 1457371). diffstat: src/njs_typed_array.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 4e3c2f9e4eee -r aa9a42bfc727 src/njs_typed_array.c --- a/src/njs_typed_array.c Thu Jan 09 15:54:16 2020 +0300 +++ b/src/njs_typed_array.c Thu Jan 09 15:54:52 2020 +0300 @@ -85,7 +85,7 @@ njs_typed_array_constructor(njs_vm_t *vm } else if (njs_is_typed_array(value)) { src_tarray = njs_typed_array(value); - size = njs_typed_array_length(src_tarray) * element_size; + size = (uint64_t) njs_typed_array_length(src_tarray) * element_size; } else if (njs_is_object(value)) { if (njs_is_array(value) && njs_object_hash_is_empty(value)) { From xeioex at nginx.com Thu Jan 9 12:55:28 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 09 Jan 2020 12:55:28 +0000 Subject: [njs] Removed dead store assignments. Message-ID: details: https://hg.nginx.org/njs/rev/16e786db8720 branches: changeset: 1297:16e786db8720 user: Dmitry Volyntsev date: Thu Jan 09 15:55:05 2020 +0300 description: Removed dead store assignments. Found by Clang static analyzer. diffstat: src/njs_chb.c | 1 - src/njs_number.c | 2 +- 2 files changed, 1 insertions(+), 2 deletions(-) diffs (23 lines): diff -r aa9a42bfc727 -r 16e786db8720 src/njs_chb.c --- a/src/njs_chb.c Thu Jan 09 15:54:52 2020 +0300 +++ b/src/njs_chb.c Thu Jan 09 15:55:05 2020 +0300 @@ -203,7 +203,6 @@ njs_chb_join(njs_chb_t *chain, njs_str_t return NJS_ERROR; } - n = chain->nodes; str->length = size; str->start = start; diff -r aa9a42bfc727 -r 16e786db8720 src/njs_number.c --- a/src/njs_number.c Thu Jan 09 15:54:52 2020 +0300 +++ b/src/njs_number.c Thu Jan 09 15:55:05 2020 +0300 @@ -695,7 +695,7 @@ njs_number_prototype_to_fixed(njs_vm_t * if (frac > 0) { *p++ = '.'; - p = njs_cpymem(p, &buf2[point], frac); + memcpy(p, &buf2[point], frac); } return NJS_OK; From mdounin at mdounin.ru Thu Jan 9 14:20:29 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 9 Jan 2020 17:20:29 +0300 Subject: Patch: Add application/wasm to conf/mime.types In-Reply-To: <1b9a4f0e-70a4-4d06-e7fe-41ce52a2f2d0@al2klimov.de> References: <20191218150414.GV12894@mdounin.ru> <1b9a4f0e-70a4-4d06-e7fe-41ce52a2f2d0@al2klimov.de> Message-ID: <20200109142029.GY12894@mdounin.ru> Hello! On Sun, Jan 05, 2020 at 01:10:27PM +0100, Alexander A. Klimov wrote: > Hello! > > Am 18.12.19 um 16:04 schrieb Maxim Dounin: > > Hello! > > > > On Wed, Dec 18, 2019 at 08:22:00AM +0100, Alexander A. Klimov wrote: > > > > > >> # HG changeset patch > >> # User Alexander A. Klimov > >> # Date 1576652721 -3600 > >> # Wed Dec 18 08:05:21 2019 +0100 > >> # Node ID 2bcc6c4df1bfd50912bcda85c22201c0f7f6a4c3 > >> # Parent 3939483cd1b56b202a99b1db344d9568b0958e67 > >> Add application/wasm to conf/mime.types > >> > >> diff -r 3939483cd1b5 -r 2bcc6c4df1bf conf/mime.types > >> --- a/conf/mime.types Thu Dec 05 19:38:06 2019 +0300 > >> +++ b/conf/mime.types Wed Dec 18 08:05:21 2019 +0100 > >> @@ -51,6 +51,7 @@ > >> application/vnd.openxmlformats-officedocument.wordprocessingml.document > >> docx; > >> application/vnd.wap.wmlc wmlc; > >> + application/wasm wasm; > >> application/x-7z-compressed 7z; > >> application/x-cocoa cco; > >> application/x-java-archive-diff jardiff; > > > > This was already discussed more than once. Please see the > > following ticket for some details: > > > > https://trac.nginx.org/nginx/ticket/1606 > > > > In particular, I would prefer to wait at least till there is an > > official registration of the type. > > > > Is [1] (see below) official enough? > It links to [2] which links to [3] which says: > > > If the Response (...) does not match the `application/wasm` MIME > type, the returned promise will be rejected (...). Official registrations are tracked by IANA, the ticket in question (comment #1) links to the appropriate page: https://www.iana.org/assignments/media-types As of now, there is no official registration, only provisional one. -- Maxim Dounin http://mdounin.ru/ From yar at nginx.com Thu Jan 9 18:25:28 2020 From: yar at nginx.com (Yaroslav Zhuravlev) Date: Thu, 9 Jan 2020 21:25:28 +0300 Subject: [PATCH] Grammar fixes In-Reply-To: References: Message-ID: <7E818CA3-4C94-4A29-AE59-E41EDA742D80@nginx.com> Hello Ville, > On 25 Dec 2019, at 10:29, Ville Skytt? wrote: > > # HG changeset patch > # User Ville Skytt? > # Date 1577258677 -7200 > # Wed Dec 25 09:24:37 2019 +0200 > # Node ID f4b83914e4009fb9c528f0318287a76aa0c7326f > # Parent e99e9b0a8c51d59c7ee665489949d8556565adff > Grammar fixes. Thank you for the patch. I've added some minor changes to it (e.g. articles in error messages), please see if the updated patch looks good to you: # HG changeset patch # User Ville Skytt? # Date 1577258677 -7200 # Wed Dec 25 09:24:37 2019 +0200 # Node ID 1e5567e2acf9357c9218216cb3a8b1c83978d7e4 # Parent f1720934c45be1c6469841a55d1f31fe9a630c85 Grammar fixes. diff -r f1720934c45b -r 1e5567e2acf9 docs/xml/nginx/changes.xml --- a/docs/xml/nginx/changes.xml Fri Dec 27 19:43:01 2019 +0300 +++ b/docs/xml/nginx/changes.xml Wed Dec 25 09:24:37 2019 +0200 @@ -14571,7 +14571,7 @@ a segmentation fault might occur in worker process, -if an "debug_connection" directive was used; +if a "debug_connection" directive was used; the bug had appeared in 0.7.54. @@ -15333,7 +15333,7 @@ ?????? ???????????? ?????? 403 ?????? 500. -now if a file specified in a "auth_basic_user_file" directive is absent, +now if a file specified in an "auth_basic_user_file" directive is absent, then the 403 error is returned instead of the 500 one. @@ -15990,7 +15990,7 @@ ?????? ????????? add_header ?? ????????? ?????? ????????. -now a "add_header" directive does not add an empty value. +now an "add_header" directive does not add an empty value. @@ -17769,7 +17769,7 @@ a segmentation fault occurred in worker process, -if big value was used in a "expires" directive.
+if big value was used in an "expires" directive.
Thanks to Joaquin Cuenca Abela.
@@ -18443,7 +18443,7 @@ ?????? ????????? ? 0.6.11. -if the "?" character was in a "error_page" directive, then it was escaped +if the "?" character was in an "error_page" directive, then it was escaped in a proxied request; the bug had appeared in 0.6.11. @@ -20715,7 +20715,7 @@ ????????? post_action ????? ?? ???????? ????? ?????????? ?????????? ???????. -the "post_action" directive might not run after a unsuccessful completion +the "post_action" directive might not run after unsuccessful completion of a request. diff -r f1720934c45b -r 1e5567e2acf9 src/core/ngx_string.c --- a/src/core/ngx_string.c Fri Dec 27 19:43:01 2019 +0300 +++ b/src/core/ngx_string.c Wed Dec 25 09:24:37 2019 +0200 @@ -519,7 +519,7 @@ * The glibc counterpart is about 150 lines of the code. * * For 32-bit numbers and some divisors gcc and icc use - * a inlined multiplication and shifts. For example, + * inlined multiplication and shifts. For example, * unsigned "i32 / 10" is compiled to * * (i32 * 0xCCCCCCCD) >> 35 diff -r f1720934c45b -r 1e5567e2acf9 src/event/modules/ngx_devpoll_module.c --- a/src/event/modules/ngx_devpoll_module.c Fri Dec 27 19:43:01 2019 +0300 +++ b/src/event/modules/ngx_devpoll_module.c Wed Dec 25 09:24:37 2019 +0200 @@ -88,8 +88,8 @@ ngx_devpoll_del_event, /* delete an event */ ngx_devpoll_add_event, /* enable an event */ ngx_devpoll_del_event, /* disable an event */ - NULL, /* add an connection */ - NULL, /* delete an connection */ + NULL, /* add a connection */ + NULL, /* delete a connection */ NULL, /* trigger a notify */ ngx_devpoll_process_events, /* process the events */ ngx_devpoll_init, /* init the events */ diff -r f1720934c45b -r 1e5567e2acf9 src/event/modules/ngx_epoll_module.c --- a/src/event/modules/ngx_epoll_module.c Fri Dec 27 19:43:01 2019 +0300 +++ b/src/event/modules/ngx_epoll_module.c Wed Dec 25 09:24:37 2019 +0200 @@ -186,8 +186,8 @@ ngx_epoll_del_event, /* delete an event */ ngx_epoll_add_event, /* enable an event */ ngx_epoll_del_event, /* disable an event */ - ngx_epoll_add_connection, /* add an connection */ - ngx_epoll_del_connection, /* delete an connection */ + ngx_epoll_add_connection, /* add a connection */ + ngx_epoll_del_connection, /* delete a connection */ #if (NGX_HAVE_EVENTFD) ngx_epoll_notify, /* trigger a notify */ #else diff -r f1720934c45b -r 1e5567e2acf9 src/event/modules/ngx_eventport_module.c --- a/src/event/modules/ngx_eventport_module.c Fri Dec 27 19:43:01 2019 +0300 +++ b/src/event/modules/ngx_eventport_module.c Wed Dec 25 09:24:37 2019 +0200 @@ -181,8 +181,8 @@ ngx_eventport_del_event, /* delete an event */ ngx_eventport_add_event, /* enable an event */ ngx_eventport_del_event, /* disable an event */ - NULL, /* add an connection */ - NULL, /* delete an connection */ + NULL, /* add a connection */ + NULL, /* delete a connection */ ngx_eventport_notify, /* trigger a notify */ ngx_eventport_process_events, /* process the events */ ngx_eventport_init, /* init the events */ diff -r f1720934c45b -r 1e5567e2acf9 src/event/modules/ngx_iocp_module.c --- a/src/event/modules/ngx_iocp_module.c Fri Dec 27 19:43:01 2019 +0300 +++ b/src/event/modules/ngx_iocp_module.c Wed Dec 25 09:24:37 2019 +0200 @@ -62,8 +62,8 @@ NULL, /* delete an event */ NULL, /* enable an event */ NULL, /* disable an event */ - NULL, /* add an connection */ - ngx_iocp_del_connection, /* delete an connection */ + NULL, /* add a connection */ + ngx_iocp_del_connection, /* delete a connection */ NULL, /* trigger a notify */ ngx_iocp_process_events, /* process the events */ ngx_iocp_init, /* init the events */ diff -r f1720934c45b -r 1e5567e2acf9 src/event/modules/ngx_kqueue_module.c --- a/src/event/modules/ngx_kqueue_module.c Fri Dec 27 19:43:01 2019 +0300 +++ b/src/event/modules/ngx_kqueue_module.c Wed Dec 25 09:24:37 2019 +0200 @@ -83,8 +83,8 @@ ngx_kqueue_del_event, /* delete an event */ ngx_kqueue_add_event, /* enable an event */ ngx_kqueue_del_event, /* disable an event */ - NULL, /* add an connection */ - NULL, /* delete an connection */ + NULL, /* add a connection */ + NULL, /* delete a connection */ #ifdef EVFILT_USER ngx_kqueue_notify, /* trigger a notify */ #else diff -r f1720934c45b -r 1e5567e2acf9 src/event/modules/ngx_poll_module.c --- a/src/event/modules/ngx_poll_module.c Fri Dec 27 19:43:01 2019 +0300 +++ b/src/event/modules/ngx_poll_module.c Wed Dec 25 09:24:37 2019 +0200 @@ -37,8 +37,8 @@ ngx_poll_del_event, /* delete an event */ ngx_poll_add_event, /* enable an event */ ngx_poll_del_event, /* disable an event */ - NULL, /* add an connection */ - NULL, /* delete an connection */ + NULL, /* add a connection */ + NULL, /* delete a connection */ NULL, /* trigger a notify */ ngx_poll_process_events, /* process the events */ ngx_poll_init, /* init the events */ diff -r f1720934c45b -r 1e5567e2acf9 src/event/modules/ngx_select_module.c --- a/src/event/modules/ngx_select_module.c Fri Dec 27 19:43:01 2019 +0300 +++ b/src/event/modules/ngx_select_module.c Wed Dec 25 09:24:37 2019 +0200 @@ -45,8 +45,8 @@ ngx_select_del_event, /* delete an event */ ngx_select_add_event, /* enable an event */ ngx_select_del_event, /* disable an event */ - NULL, /* add an connection */ - NULL, /* delete an connection */ + NULL, /* add a connection */ + NULL, /* delete a connection */ NULL, /* trigger a notify */ ngx_select_process_events, /* process the events */ ngx_select_init, /* init the events */ diff -r f1720934c45b -r 1e5567e2acf9 src/event/modules/ngx_win32_poll_module.c --- a/src/event/modules/ngx_win32_poll_module.c Fri Dec 27 19:43:01 2019 +0300 +++ b/src/event/modules/ngx_win32_poll_module.c Wed Dec 25 09:24:37 2019 +0200 @@ -39,8 +39,8 @@ ngx_poll_del_event, /* delete an event */ ngx_poll_add_event, /* enable an event */ ngx_poll_del_event, /* disable an event */ - NULL, /* add an connection */ - NULL, /* delete an connection */ + NULL, /* add a connection */ + NULL, /* delete a connection */ NULL, /* trigger a notify */ ngx_poll_process_events, /* process the events */ ngx_poll_init, /* init the events */ diff -r f1720934c45b -r 1e5567e2acf9 src/event/modules/ngx_win32_select_module.c --- a/src/event/modules/ngx_win32_select_module.c Fri Dec 27 19:43:01 2019 +0300 +++ b/src/event/modules/ngx_win32_select_module.c Wed Dec 25 09:24:37 2019 +0200 @@ -47,8 +47,8 @@ ngx_select_del_event, /* delete an event */ ngx_select_add_event, /* enable an event */ ngx_select_del_event, /* disable an event */ - NULL, /* add an connection */ - NULL, /* delete an connection */ + NULL, /* add a connection */ + NULL, /* delete a connection */ NULL, /* trigger a notify */ ngx_select_process_events, /* process the events */ ngx_select_init, /* init the events */ diff -r f1720934c45b -r 1e5567e2acf9 src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c Fri Dec 27 19:43:01 2019 +0300 +++ b/src/http/ngx_http_core_module.c Wed Dec 25 09:24:37 2019 +0200 @@ -1258,7 +1258,7 @@ & NGX_HTTP_KEEPALIVE_DISABLE_MSIE6)) { /* - * MSIE may wait for some time if an response for + * MSIE may wait for some time if a response for * a POST request was sent over a keepalive connection */ r->keepalive = 0; diff -r f1720934c45b -r 1e5567e2acf9 src/http/ngx_http_parse.c --- a/src/http/ngx_http_parse.c Fri Dec 27 19:43:01 2019 +0300 +++ b/src/http/ngx_http_parse.c Wed Dec 25 09:24:37 2019 +0200 @@ -98,7 +98,7 @@ #endif -/* gcc, icc, msvc and others compile these switches as an jump table */ +/* gcc, icc, msvc and others compile these switches as a jump table */ ngx_int_t ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) diff -r f1720934c45b -r 1e5567e2acf9 src/http/ngx_http_special_response.c --- a/src/http/ngx_http_special_response.c Fri Dec 27 19:43:01 2019 +0300 +++ b/src/http/ngx_http_special_response.c Wed Dec 25 09:24:37 2019 +0200 @@ -253,11 +253,11 @@ static char ngx_http_error_495_page[] = "" CRLF -"400 The SSL certificate error" +"400 SSL certificate error" CRLF "" CRLF "

400 Bad Request

" CRLF -"
The SSL certificate error
" CRLF +"
SSL certificate error
" CRLF ; @@ -273,11 +273,11 @@ static char ngx_http_error_497_page[] = "" CRLF -"400 The plain HTTP request was sent to HTTPS port" +"400 Plain HTTP request was sent to HTTPS port" CRLF "" CRLF "

400 Bad Request

" CRLF -"
The plain HTTP request was sent to HTTPS port
" CRLF +"
Plain HTTP request was sent to HTTPS port
" CRLF ; diff -r f1720934c45b -r 1e5567e2acf9 src/os/unix/ngx_darwin_sendfile_chain.c --- a/src/os/unix/ngx_darwin_sendfile_chain.c Fri Dec 27 19:43:01 2019 +0300 +++ b/src/os/unix/ngx_darwin_sendfile_chain.c Wed Dec 25 09:24:37 2019 +0200 @@ -54,7 +54,7 @@ if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT) && wev->pending_eof) { (void) ngx_connection_error(c, wev->kq_errno, - "kevent() reported about an closed connection"); + "kevent() reported about a closed connection"); wev->error = 1; return NGX_CHAIN_ERROR; } diff -r f1720934c45b -r 1e5567e2acf9 src/os/unix/ngx_freebsd_sendfile_chain.c --- a/src/os/unix/ngx_freebsd_sendfile_chain.c Fri Dec 27 19:43:01 2019 +0300 +++ b/src/os/unix/ngx_freebsd_sendfile_chain.c Wed Dec 25 09:24:37 2019 +0200 @@ -60,7 +60,7 @@ if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT) && wev->pending_eof) { (void) ngx_connection_error(c, wev->kq_errno, - "kevent() reported about an closed connection"); + "kevent() reported about a closed connection"); wev->error = 1; return NGX_CHAIN_ERROR; } diff -r f1720934c45b -r 1e5567e2acf9 src/os/unix/ngx_readv_chain.c --- a/src/os/unix/ngx_readv_chain.c Fri Dec 27 19:43:01 2019 +0300 +++ b/src/os/unix/ngx_readv_chain.c Wed Dec 25 09:24:37 2019 +0200 @@ -35,7 +35,7 @@ rev->eof = 1; ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno, - "kevent() reported about an closed connection"); + "kevent() reported about a closed connection"); if (rev->kq_errno) { rev->error = 1; diff -r f1720934c45b -r 1e5567e2acf9 src/os/unix/ngx_recv.c --- a/src/os/unix/ngx_recv.c Fri Dec 27 19:43:01 2019 +0300 +++ b/src/os/unix/ngx_recv.c Wed Dec 25 09:24:37 2019 +0200 @@ -36,7 +36,7 @@ ngx_set_socket_errno(rev->kq_errno); return ngx_connection_error(c, rev->kq_errno, - "kevent() reported about an closed connection"); + "kevent() reported about a closed connection"); } return 0; diff -r f1720934c45b -r 1e5567e2acf9 src/os/unix/ngx_send.c --- a/src/os/unix/ngx_send.c Fri Dec 27 19:43:01 2019 +0300 +++ b/src/os/unix/ngx_send.c Wed Dec 25 09:24:37 2019 +0200 @@ -23,7 +23,7 @@ if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT) && wev->pending_eof) { (void) ngx_connection_error(c, wev->kq_errno, - "kevent() reported about an closed connection"); + "kevent() reported about a closed connection"); wev->error = 1; return NGX_ERROR; } diff -r f1720934c45b -r 1e5567e2acf9 src/os/unix/ngx_udp_sendmsg_chain.c --- a/src/os/unix/ngx_udp_sendmsg_chain.c Fri Dec 27 19:43:01 2019 +0300 +++ b/src/os/unix/ngx_udp_sendmsg_chain.c Wed Dec 25 09:24:37 2019 +0200 @@ -35,7 +35,7 @@ if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT) && wev->pending_eof) { (void) ngx_connection_error(c, wev->kq_errno, - "kevent() reported about an closed connection"); + "kevent() reported about a closed connection"); wev->error = 1; return NGX_CHAIN_ERROR; } diff -r f1720934c45b -r 1e5567e2acf9 src/os/unix/ngx_writev_chain.c --- a/src/os/unix/ngx_writev_chain.c Fri Dec 27 19:43:01 2019 +0300 +++ b/src/os/unix/ngx_writev_chain.c Wed Dec 25 09:24:37 2019 +0200 @@ -30,7 +30,7 @@ if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT) && wev->pending_eof) { (void) ngx_connection_error(c, wev->kq_errno, - "kevent() reported about an closed connection"); + "kevent() reported about a closed connection"); wev->error = 1; return NGX_CHAIN_ERROR; } [?] Best regards, yar From xeioex at nginx.com Mon Jan 13 18:42:58 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 13 Jan 2020 18:42:58 +0000 Subject: [njs] Refactored njs_benchmark. Message-ID: details: https://hg.nginx.org/njs/rev/6ff44c2312ac branches: changeset: 1298:6ff44c2312ac user: Dmitry Volyntsev date: Mon Jan 13 21:35:15 2020 +0300 description: Refactored njs_benchmark. diffstat: auto/make | 2 +- src/test/njs_benchmark.c | 447 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 331 insertions(+), 118 deletions(-) diffs (535 lines): diff -r 16e786db8720 -r 6ff44c2312ac auto/make --- a/auto/make Thu Jan 09 15:55:05 2020 +0300 +++ b/auto/make Mon Jan 13 21:35:15 2020 +0300 @@ -237,7 +237,7 @@ test: expect_test unit_test benchmark: $NJS_BUILD_DIR/njs_auto_config.h \\ $NJS_BUILD_DIR/njs_benchmark - $NJS_BUILD_DIR/njs_benchmark v + $NJS_BUILD_DIR/njs_benchmark dist: NJS_VER=`grep NJS_VERSION src/njs.h | sed -e 's/.*"\(.*\)".*/\1/'`; \\ diff -r 16e786db8720 -r 6ff44c2312ac src/test/njs_benchmark.c --- a/src/test/njs_benchmark.c Thu Jan 09 15:55:05 2020 +0300 +++ b/src/test/njs_benchmark.c Mon Jan 13 21:35:15 2020 +0300 @@ -4,7 +4,7 @@ * Copyright (C) NGINX, Inc. */ -#include +#include #include #include @@ -12,19 +12,38 @@ #include +typedef struct { + const char *name; + njs_str_t script; + njs_str_t result; + njs_uint_t repeat; +} njs_benchmark_test_t; + + +typedef struct { + uint8_t dump_report; + const char *prefix; + const char *previous; +} njs_opts_t; + + static njs_int_t -njs_unit_test_benchmark(njs_str_t *script, njs_str_t *result, const char *msg, - njs_uint_t n) +njs_benchmark_test(njs_vm_t *parent, njs_opts_t *opts, njs_value_t *report, + njs_benchmark_test_t *test) { - u_char *start; - njs_vm_t *vm, *nvm; - uint64_t us; - njs_int_t ret; - njs_str_t s; - njs_uint_t i; - njs_bool_t success; - njs_vm_opt_t options; - struct rusage usage; + u_char *start; + njs_vm_t *vm, *nvm; + uint64_t us; + njs_int_t ret; + njs_str_t s, *expected; + njs_uint_t i, n; + njs_bool_t success; + njs_value_t *result, name, usec, times; + njs_vm_opt_t options; + + static const njs_value_t name_key = njs_string("name"); + static const njs_value_t usec_key = njs_string("usec"); + static const njs_value_t times_key = njs_string("times"); njs_memzero(&options, sizeof(njs_vm_opt_t)); @@ -38,14 +57,19 @@ njs_unit_test_benchmark(njs_str_t *scrip goto done; } - start = script->start; + start = test->script.start; - ret = njs_vm_compile(vm, &start, start + script->length); + ret = njs_vm_compile(vm, &start, start + test->script.length); if (ret != NJS_OK) { njs_printf("njs_vm_compile() failed\n"); goto done; } + n = test->repeat; + expected = &test->result; + + us = njs_time() / 1000; + for (i = 0; i < n; i++) { nvm = njs_vm_clone(vm, NULL); @@ -61,10 +85,10 @@ njs_unit_test_benchmark(njs_str_t *scrip goto done; } - success = njs_strstr_eq(result, &s); + success = njs_strstr_eq(expected, &s); if (!success) { - njs_printf("failed: \"%V\" vs \"%V\"\n", result, &s); + njs_printf("failed: \"%V\" vs \"%V\"\n", expected, &s); goto done; } @@ -72,17 +96,42 @@ njs_unit_test_benchmark(njs_str_t *scrip nvm = NULL; } - getrusage(RUSAGE_SELF, &usage); + us = njs_time() / 1000 - us; + + if (!opts->dump_report) { + if (n == 1) { + njs_printf("%s%s: %.3fs\n", opts->previous ? " " : "", + test->name, (double) us / 1000000); - us = usage.ru_utime.tv_sec * 1000000 + usage.ru_utime.tv_usec - + usage.ru_stime.tv_sec * 1000000 + usage.ru_stime.tv_usec; + } else { + njs_printf("%s%s: %.3f?s, %d times/s\n", + opts->previous ? " " : "", + test->name, (double) us / n, + (int) ((uint64_t) n * 1000000 / us)); + } + } - if (n == 1) { - njs_printf("%s: %.3fs\n", msg, (double) us / 1000000); + result = njs_vm_array_push(parent, report); + if (result == NULL) { + njs_printf("njs_vm_array_push() failed\n"); + goto done; + } - } else { - njs_printf("%s: %.3f?s, %d times/s\n", - msg, (double) us / n, (int) ((uint64_t) n * 1000000 / us)); + ret = njs_vm_value_string_set(parent, &name, (u_char *) test->name, + njs_strlen(test->name)); + if (ret != NJS_OK) { + njs_printf("njs_vm_value_string_set() failed\n"); + goto done; + } + + njs_value_number_set(&usec, us); + njs_value_number_set(×, n); + + ret = njs_vm_object_alloc(parent, result, &name_key, &name, + &usec_key, &usec, ×_key, ×, NULL); + if (ret != NJS_OK) { + njs_printf("njs_vm_object_alloc() failed\n"); + goto done; } ret = NJS_OK; @@ -100,117 +149,281 @@ done: return ret; } +static njs_benchmark_test_t njs_test[] = +{ + { "nJSVM clone/destroy", + njs_str("null"), + njs_str("null"), + 1000000 }, + + { "JSON.parse", + njs_str("JSON.parse('{\"a\":123, \"XXX\":[3,4,null]}').a"), + njs_str("123"), + 1000000 }, + + { "for loop 100M", + njs_str("var i; for (i = 0; i < 100000000; i++); i"), + njs_str("100000000"), + 1 }, + + { "while loop 100M", + njs_str("var i = 0; while (i < 100000000) { i++ }; i"), + njs_str("100000000"), + 1 }, + + { "fibobench numbers", + njs_str("function fibo(n) {" + " if (n > 1)" + " return fibo(n - 1) + fibo(n - 2);" + " return 1" + "}" + "fibo(32)"), + njs_str("3524578"), + 1 }, + + { "fibobench ascii strings", + njs_str("function fibo(n) {" + " if (n > 1)" + " return fibo(n - 1) + fibo(n - 2);" + " return '.'" + "}" + "fibo(32).length"), + njs_str("3524578"), + 1 }, + + { "fibobench byte strings", + njs_str("var a = '\\x80'.toBytes();" + "function fibo(n) {" + " if (n > 1)" + " return fibo(n - 1) + fibo(n - 2);" + " return 'a'" + "}" + "fibo(32).length"), + njs_str("3524578"), + 1 }, + + { "fibobench utf8 strings", + njs_str("function fibo(n) {" + " if (n > 1)" + " return fibo(n - 1) + fibo(n - 2);" + " return '?'" + "}" + "fibo(32).length"), + njs_str("3524578"), + 1 }, + + { "array 10M", + njs_str("var arr = new Array(10000000);" + "var count = 0, length = arr.length;" + "arr.fill(2);" + "for (var i = 0; i < length; i++) { count += arr[i]; }" + "count"), + njs_str("20000000"), + 1 }, + + { "typed array 10M", + njs_str("var arr = new Uint8Array(10000000);" + "var count = 0, length = arr.length;" + "arr.fill(2);" + "for (var i = 0; i < length; i++) { count += arr[i]; }" + "count"), + njs_str("20000000"), + 1 }, +}; + + +static njs_str_t code = njs_str( + "import fs from 'fs';" + "" + "function compare(prev_fn, current) {" + " var prev_report = JSON.parse(fs.readFileSync(prev_fn));" + " var test, prev, diff, result = [`Diff with ${prev_fn}:`];" + " for (var t in current) {" + " test = current[t];" + " prev = find(prev_report, test.name);" + " diff = (test.usec - prev.usec) / prev.usec * 100;" + " result.push(` ${test.name}: ${diff.toFixed(2)}%`);" + " }" + " return result.join('\\n') + '\\n';" + "}" + "" + "function find(report, name) {" + " for (var t in report) {" + " if (report[t].name == name) { return report[t];}" + " }" + "}"); + int njs_cdecl main(int argc, char **argv) { - static njs_str_t script = njs_str("null"); - static njs_str_t result = njs_str("null"); - - static njs_str_t fibo_number = njs_str( - "function fibo(n) {" - " if (n > 1)" - " return fibo(n - 1) + fibo(n - 2);" - " return 1" - "}" - "fibo(32)"); - - static njs_str_t fibo_ascii = njs_str( - "function fibo(n) {" - " if (n > 1)" - " return fibo(n - 1) + fibo(n - 2);" - " return '.'" - "}" - "fibo(32).length"); - - static njs_str_t fibo_bytes = njs_str( - "var a = '\\x80'.toBytes();" - "function fibo(n) {" - " if (n > 1)" - " return fibo(n - 1) + fibo(n - 2);" - " return a" - "}" - "fibo(32).length"); - - static njs_str_t fibo_utf8 = njs_str( - "function fibo(n) {" - " if (n > 1)" - " return fibo(n - 1) + fibo(n - 2);" - " return '?'" - "}" - "fibo(32).length"); - - static njs_str_t json = njs_str( - "JSON.parse('{\"a\":123, \"XXX\":[3,4,null]}').a"); - - static njs_str_t for_loop = njs_str( - "var i; for (i = 0; i < 100000000; i++); i"); + char *p; + u_char *start; + njs_vm_t *vm; + njs_int_t ret, k; + njs_str_t out; + njs_uint_t i; + njs_opts_t opts; + njs_value_t args[2], report; + njs_vm_opt_t options; + njs_benchmark_test_t *test; - static njs_str_t while_loop = njs_str( - "var i = 0; while (i < 100000000) { i++ }; i"); - - static njs_str_t typed_array_10M = njs_str( - "var arr = new Uint8Array(10000000); var count = 0, length = arr.length;" - "arr.fill(2);" - "for (var i = 0; i < length; i++) { count += arr[i]; } count"); + static const char help[] = + "njs benchmark.\n" + "\n" + "njs_benchmark [OPTIONS]" + "\n" + "Options:\n" + " -b specify the benchmarks to execute.\n" + " -d dump report as a JSON file.\n" + " -c compare with previous report.\n" + " -h this help.\n"; - static njs_str_t array_10M = njs_str( - "var arr = new Array(10000000); var count = 0, length = arr.length;" - "arr.fill(2);" - "for (var i = 0; i < length; i++) { count += arr[i]; } count"); - - static njs_str_t fibo_result = njs_str("3524578"); - static njs_str_t json_result = njs_str("123"); - static njs_str_t loop_result = njs_str("100000000"); - static njs_str_t sum_result = njs_str("20000000"); - - - if (argc > 1) { - switch (argv[1][0]) { + static const njs_str_t compare = njs_str("compare"); - case 'v': - return njs_unit_test_benchmark(&script, &result, - "nJSVM clone/destroy", 1000000); + njs_memzero(&opts, sizeof(njs_opts_t)); + opts.prefix = ""; - case 'j': - return njs_unit_test_benchmark(&json, &json_result, - "JSON.parse", 1000000); - - case 'f': - return njs_unit_test_benchmark(&for_loop, &loop_result, - "for loop 100M", 1); + for (k = 1; k < argc; k++) { + p = argv[k]; - case 'w': - return njs_unit_test_benchmark(&while_loop, &loop_result, - "while loop 100M", 1); + if (p[0] != '-') { + goto invalid_options; + } + + p++; - case 'n': - return njs_unit_test_benchmark(&fibo_number, &fibo_result, - "fibobench numbers", 1); - - case 'a': - return njs_unit_test_benchmark(&fibo_ascii, &fibo_result, - "fibobench ascii strings", 1); + switch (*p) { + case '?': + case 'h': + njs_print(help, njs_length(help)); + return EXIT_SUCCESS; case 'b': - return njs_unit_test_benchmark(&fibo_bytes, &fibo_result, - "fibobench byte strings", 1); + if (++k < argc) { + opts.prefix = argv[k]; + break; + } - case 'u': - return njs_unit_test_benchmark(&fibo_utf8, &fibo_result, - "fibobench utf8 strings", 1); + njs_stderror("option \"-b\" requires argument\n"); + return EXIT_FAILURE; - case 't': - return njs_unit_test_benchmark(&typed_array_10M, &sum_result, - "typed_array_10M", 1); + case 'c': + if (++k < argc) { + opts.previous = argv[k]; + break; + } - case 'A': - return njs_unit_test_benchmark(&array_10M, &sum_result, - "array_10M", 1); + njs_stderror("option \"-c\" requires argument\n"); + return EXIT_FAILURE; + + case 'd': + opts.dump_report = 1; + break; + + default: + goto invalid_options; } } - njs_printf("unknown agrument\n"); + njs_memzero(&options, sizeof(njs_vm_opt_t)); + options.init = 1; + options.argv = argv; + options.argc = argc; + + vm = njs_vm_create(&options); + if (vm == NULL) { + njs_printf("njs_vm_create() failed\n"); + return EXIT_FAILURE; + } + + start = code.start; + ret = njs_vm_compile(vm, &start, start + code.length); + if (ret != NJS_OK) { + njs_printf("njs_vm_compile() failed\n"); + goto done; + } + + njs_vm_start(vm); + + ret = EXIT_FAILURE; + + ret = njs_vm_array_alloc(vm, &report, 8); + if (ret != NJS_OK) { + njs_printf("njs_vm_array_alloc() failed\n"); + goto done; + } + + if (opts.previous) { + njs_printf("Current:\n"); + } + + for (i = 0; i < njs_nitems(njs_test); i++) { + test = &njs_test[i]; + + if (strncmp(test->name, opts.prefix, + njs_min(strlen(test->name), strlen(opts.prefix))) == 0) + { + ret = njs_benchmark_test(vm, &opts, &report, test); + + if (ret != NJS_OK) { + goto done; + } + } + } + + if (opts.previous) { + ret = njs_vm_value_string_set(vm, &args[0], (u_char *) opts.previous, + njs_strlen(opts.previous)); + if (ret != NJS_OK) { + njs_printf("njs_vm_value_string_set() failed\n"); + goto done; + } + + args[1] = report; + + njs_vm_call(vm, njs_vm_function(vm, &compare), njs_value_arg(&args), 2); + + ret = njs_vm_value_dump(vm, &out, njs_vm_retval(vm), 1, 1); + if (ret != NJS_OK) { + njs_printf("njs_vm_retval_dump() failed\n"); + goto done; + } + + njs_print(out.start, out.length); + + return EXIT_SUCCESS; + } + + if (opts.dump_report) { + ret = njs_vm_json_stringify(vm, &report, 1); + if (ret != NJS_OK) { + njs_printf("njs_vm_json_stringify() failed\n"); + goto done; + } + + ret = njs_vm_value_dump(vm, &out, njs_vm_retval(vm), 1, 1); + if (ret != NJS_OK) { + njs_printf("njs_vm_retval_dump() failed\n"); + goto done; + } + + njs_print(out.start, out.length); + } + + ret = EXIT_SUCCESS; + +done: + + njs_vm_destroy(vm); + + return ret; + +invalid_options: + + njs_stderror("Unknown argument: \"%s\" " + "try \"%s -h\" for available options\n", argv[k], + argv[0]); return EXIT_FAILURE; } From support at tratimo.su Mon Jan 13 18:43:37 2020 From: support at tratimo.su (Tratimo.su) Date: Mon, 13 Jan 2020 18:43:37 +0000 Subject: [njs] Refactored njs_benchmark. Message-ID: An HTML attachment was scrubbed... URL: From ru at nginx.com Tue Jan 14 11:21:41 2020 From: ru at nginx.com (Ruslan Ermilov) Date: Tue, 14 Jan 2020 11:21:41 +0000 Subject: =?UTF-8?B?W25naW54XSBIVFRQLzI6wqByZW1vdmVkIG5neF9kZWJ1Z19wb2ludCgpIGNhbGwu?= Message-ID: details: https://hg.nginx.org/nginx/rev/8a7b59347401 branches: changeset: 7618:8a7b59347401 user: Daniil Bondarev date: Tue Jan 14 14:20:08 2020 +0300 description: HTTP/2:?removed ngx_debug_point() call. ?? ? With the recent change to prevent frames flood in d4448892a294, nginx will finalize the connection with NGX_HTTP_V2_INTERNAL_ERROR whenever flood is detected, causing nginx aborting or stopping if the debug_points directive is used in nginx config. diffstat: src/http/v2/ngx_http_v2.c | 4 ---- 1 files changed, 0 insertions(+), 4 deletions(-) diffs (14 lines): diff -r f1720934c45b -r 8a7b59347401 src/http/v2/ngx_http_v2.c --- a/src/http/v2/ngx_http_v2.c Fri Dec 27 19:43:01 2019 +0300 +++ b/src/http/v2/ngx_http_v2.c Tue Jan 14 14:20:08 2020 +0300 @@ -2466,10 +2466,6 @@ ngx_http_v2_connection_error(ngx_http_v2 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, "http2 state connection error"); - if (err == NGX_HTTP_V2_INTERNAL_ERROR) { - ngx_debug_point(); - } - ngx_http_v2_finalize_connection(h2c, err); return NULL; From xeioex at nginx.com Tue Jan 14 13:53:55 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 14 Jan 2020 13:53:55 +0000 Subject: [njs] Introduced "global" and "globalThis" aliases to the global object. Message-ID: details: https://hg.nginx.org/njs/rev/b840b7af946e branches: changeset: 1299:b840b7af946e user: Dmitry Volyntsev date: Tue Jan 14 16:52:42 2020 +0300 description: Introduced "global" and "globalThis" aliases to the global object. diffstat: src/njs_builtin.c | 62 ++++++++++++++++++++++++++++++++++++++ src/njs_json.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++- src/njs_object.c | 75 +++++++++++++++++++++++++++++++++++++++++----- src/njs_object_hash.h | 24 ++++++++++++++ src/test/njs_unit_test.c | 21 ++++++------ 5 files changed, 238 insertions(+), 21 deletions(-) diffs (399 lines): diff -r 6ff44c2312ac -r b840b7af946e src/njs_builtin.c --- a/src/njs_builtin.c Mon Jan 13 21:35:15 2020 +0300 +++ b/src/njs_builtin.c Tue Jan 14 16:52:42 2020 +0300 @@ -837,6 +837,47 @@ njs_dump_value(njs_vm_t *vm, njs_value_t static njs_int_t +njs_global_this_object(njs_vm_t *vm, njs_object_prop_t *self, + njs_value_t *global, njs_value_t *setval, njs_value_t *retval) +{ + njs_int_t ret; + njs_object_prop_t *prop; + njs_lvlhsh_query_t lhq; + + *retval = *global; + + if (njs_slow_path(setval != NULL)) { + *retval = *setval; + } + + prop = njs_object_prop_alloc(vm, &self->name, retval, 1); + if (njs_slow_path(prop == NULL)) { + return NJS_ERROR; + } + + /* GC */ + + prop->value = *retval; + prop->enumerable = self->enumerable; + + lhq.value = prop; + njs_string_get(&self->name, &lhq.key); + lhq.key_hash = self->value.data.magic32; + lhq.replace = 1; + lhq.pool = vm->mem_pool; + lhq.proto = &njs_object_hash_proto; + + ret = njs_lvlhsh_insert(njs_object_hash(global), &lhq); + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "lvlhsh insert/replace failed"); + return NJS_ERROR; + } + + return NJS_OK; +} + + +static njs_int_t njs_top_level_object(njs_vm_t *vm, njs_object_prop_t *self, njs_value_t *global, njs_value_t *setval, njs_value_t *retval) { @@ -938,6 +979,27 @@ static const njs_object_prop_t njs_glob .configurable = 1, }, + /* Global aliases. */ + + { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("global"), + .value = njs_prop_handler2(njs_global_this_object, 0, NJS_GLOBAL_HASH), + .writable = 1, + .enumerable = 1, + .configurable = 1, + }, + + { + .type = NJS_PROPERTY_HANDLER, + .name = njs_string("globalThis"), + .value = njs_prop_handler2(njs_global_this_object, 0, + NJS_GLOBAL_THIS_HASH), + .writable = 1, + .enumerable = 0, + .configurable = 1, + }, + /* Global constants. */ { diff -r 6ff44c2312ac -r b840b7af946e src/njs_json.c --- a/src/njs_json.c Mon Jan 13 21:35:15 2020 +0300 +++ b/src/njs_json.c Tue Jan 14 16:52:42 2020 +0300 @@ -1934,6 +1934,49 @@ njs_dump_is_recursive(const njs_value_t } +njs_inline njs_int_t +njs_dump_visit(njs_arr_t *list, const njs_value_t *value) +{ + njs_object_t **p; + + if (njs_is_object(value)) { + p = njs_arr_add(list); + if (njs_slow_path(p == NULL)) { + return NJS_ERROR; + } + + *p = njs_object(value); + } + + return NJS_OK; +} + + +njs_inline njs_int_t +njs_dump_visited(njs_arr_t *list, const njs_value_t *value) +{ + njs_uint_t items, n; + njs_object_t **start, *obj; + + if (!njs_is_object(value)) { + /* External. */ + return 0; + } + + start = list->start; + items = list->items; + obj = njs_object(value); + + for (n = 0; n < items; n++) { + if (start[n] == obj) { + return 1; + } + } + + return 0; +} + + static const njs_value_t string_get = njs_string("[Getter]"); static const njs_value_t string_set = njs_string("[Setter]"); static const njs_value_t string_get_set = njs_long_string("[Getter/Setter]"); @@ -1943,11 +1986,12 @@ njs_int_t njs_vm_value_dump(njs_vm_t *vm, njs_str_t *retval, njs_value_t *value, njs_uint_t console, njs_uint_t indent) { - njs_int_t i; - njs_int_t ret; + njs_int_t i, ret; njs_chb_t chain; njs_str_t str; + njs_arr_t visited; njs_value_t *key, *val, tag; + njs_object_t **start; njs_json_state_t *state; njs_string_prop_t string; njs_object_prop_t *prop; @@ -1983,6 +2027,13 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_ goto memory_error; } + start = njs_arr_init(vm->mem_pool, &visited, NULL, 8, sizeof(void *)); + if (njs_slow_path(start == NULL)) { + goto memory_error; + } + + (void) njs_dump_visit(&visited, value); + for ( ;; ) { switch (state->type) { case NJS_JSON_OBJECT: @@ -2076,6 +2127,16 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_ } if (njs_dump_is_recursive(val)) { + if (njs_slow_path(njs_dump_visited(&visited, val))) { + njs_chb_append_literal(&chain, "[Circular]"); + break; + } + + ret = njs_dump_visit(&visited, val); + if (njs_slow_path(ret != NJS_OK)) { + goto memory_error; + } + state = njs_json_push_stringify_state(vm, stringify, val); if (njs_slow_path(state == NULL)) { goto exception; @@ -2132,6 +2193,16 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_ val = &njs_array_start(&state->value)[state->index++]; if (njs_dump_is_recursive(val)) { + if (njs_slow_path(njs_dump_visited(&visited, val))) { + njs_chb_append_literal(&chain, "[Circular]"); + break; + } + + ret = njs_dump_visit(&visited, val); + if (njs_slow_path(ret != NJS_OK)) { + goto memory_error; + } + state = njs_json_push_stringify_state(vm, stringify, val); if (njs_slow_path(state == NULL)) { goto exception; @@ -2155,6 +2226,8 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_ } } + njs_arr_destroy(&visited); + done: ret = njs_chb_join(&chain, &str); diff -r 6ff44c2312ac -r b840b7af946e src/njs_object.c --- a/src/njs_object.c Mon Jan 13 21:35:15 2020 +0300 +++ b/src/njs_object.c Tue Jan 14 16:52:42 2020 +0300 @@ -1215,18 +1215,61 @@ njs_object_own_enumerate_object(njs_vm_t } +njs_inline njs_int_t +njs_traverse_visit(njs_arr_t *list, const njs_value_t *value) +{ + njs_object_t **p; + + if (njs_is_object(value)) { + p = njs_arr_add(list); + if (njs_slow_path(p == NULL)) { + return NJS_ERROR; + } + + *p = njs_object(value); + } + + return NJS_OK; +} + + +njs_inline njs_int_t +njs_traverse_visited(njs_arr_t *list, const njs_value_t *value) +{ + njs_uint_t items, n; + njs_object_t **start, *obj; + + if (!njs_is_object(value)) { + /* External. */ + return 0; + } + + start = list->start; + items = list->items; + obj = njs_object(value); + + for (n = 0; n < items; n++) { + if (start[n] == obj) { + return 1; + } + } + + return 0; +} + + njs_int_t njs_object_traverse(njs_vm_t *vm, njs_object_t *object, void *ctx, njs_object_traverse_cb_t cb) { njs_int_t depth, ret; njs_str_t name; + njs_arr_t visited; + njs_object_t **start; njs_value_t value, obj; njs_object_prop_t *prop; njs_traverse_t state[NJS_TRAVERSE_MAX_DEPTH]; - static const njs_str_t constructor_key = njs_str("constructor"); - depth = 0; state[depth].prop = NULL; @@ -1235,6 +1278,14 @@ njs_object_traverse(njs_vm_t *vm, njs_ob state[depth].hash = &object->shared_hash; njs_lvlhsh_each_init(&state[depth].lhe, &njs_object_hash_proto); + start = njs_arr_init(vm->mem_pool, &visited, NULL, 8, sizeof(void *)); + if (njs_slow_path(start == NULL)) { + return NJS_ERROR; + } + + njs_set_object(&value, object); + (void) njs_traverse_visit(&visited, &value); + for ( ;; ) { prop = njs_lvlhsh_each(state[depth].hash, &state[depth].lhe); @@ -1246,7 +1297,7 @@ njs_object_traverse(njs_vm_t *vm, njs_ob } if (depth == 0) { - return NJS_OK; + goto done; } depth--; @@ -1273,12 +1324,12 @@ njs_object_traverse(njs_vm_t *vm, njs_ob njs_string_get(&prop->name, &name); - /* - * "constructor" properties make loops in object hierarchies. - * Object.prototype.constructor -> Object. - */ - - if (njs_is_object(&value) && !njs_strstr_eq(&name, &constructor_key)) { + if (njs_is_object(&value) && !njs_traverse_visited(&visited, &value)) { + ret = njs_traverse_visit(&visited, &value); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + if (++depth > (NJS_TRAVERSE_MAX_DEPTH - 1)) { njs_type_error(vm, "njs_object_traverse() recursion limit:%d", depth); @@ -1293,6 +1344,12 @@ njs_object_traverse(njs_vm_t *vm, njs_ob } } + +done: + + njs_arr_destroy(&visited); + + return NJS_OK; } diff -r 6ff44c2312ac -r b840b7af946e src/njs_object_hash.h --- a/src/njs_object_hash.h Mon Jan 13 21:35:15 2020 +0300 +++ b/src/njs_object_hash.h Tue Jan 14 16:52:42 2020 +0300 @@ -178,6 +178,30 @@ 'g'), 'e'), 't') +#define NJS_GLOBAL_HASH \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add(NJS_DJB_HASH_INIT, \ + 'g'), 'l'), 'o'), 'b'), 'a'), 'l') + + +#define NJS_GLOBAL_THIS_HASH \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add( \ + njs_djb_hash_add(NJS_DJB_HASH_INIT, \ + 'g'), 'l'), 'o'), 'b'), 'a'), 'l'), 'T'), 'h'), 'i'), 's') + + #define NJS_FUNCTION_HASH \ njs_djb_hash_add( \ njs_djb_hash_add( \ diff -r 6ff44c2312ac -r b840b7af946e src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Mon Jan 13 21:35:15 2020 +0300 +++ b/src/test/njs_unit_test.c Tue Jan 14 16:52:42 2020 +0300 @@ -10012,16 +10012,11 @@ static njs_unit_test_t njs_test[] = njs_str("true") }, { njs_str("Object.keys(this).sort()"), - njs_str("$r,$r2,$r3,njs,process") }, - - { njs_str("var r = njs.dump(this); " - "['$r', 'global', njs.version].every(v=>r.includes(v))"), - njs_str("true") }, - - { njs_str("var r = JSON.stringify(this); " - "['$r', njs.version].every(v=>r.includes(v))"), - njs_str("true") }, - + njs_str("$r,$r2,$r3,global,njs,process") }, + + { njs_str("[this, global, globalThis]" + ".every(v=> { var r = njs.dump(v); return ['$r', 'global', njs.version].every(v=>r.includes(v))})"), + njs_str("true") }, { njs_str("this.a = 1; this.a"), njs_str("1") }, @@ -15414,6 +15409,12 @@ static njs_unit_test_t njs_test[] = { njs_str("njs.dump(njs) == `njs {version:'${njs.version}'}`"), njs_str("true") }, + { njs_str("var a = []; a[0] = a; njs.dump(a)"), + njs_str("[[Circular]]") }, + + { njs_str("var a = [], b = [a]; a[0] = b; njs.dump(a)"), + njs_str("[[[Circular]]]") }, + { njs_str("njs.dump(-0)"), njs_str("-0") }, From mrumph68 at gmail.com Tue Jan 14 18:29:22 2020 From: mrumph68 at gmail.com (Mike Rumph) Date: Tue, 14 Jan 2020 10:29:22 -0800 Subject: Any plans for adding Travis CI testing? Message-ID: The Apache HTTP Server project recently added Travis CI testing. Are there any plans to do the same for NGINX? -------------- next part -------------- An HTML attachment was scrubbed... URL: From support at tratimo.su Tue Jan 14 18:31:39 2020 From: support at tratimo.su (Tratimo.su) Date: Tue, 14 Jan 2020 18:31:39 +0000 Subject: Any plans for adding Travis CI testing? Message-ID: An HTML attachment was scrubbed... URL: From sampsonsprojects at gmail.com Wed Jan 15 20:51:34 2020 From: sampsonsprojects at gmail.com (sampsonsprojects at gmail.com) Date: Wed, 15 Jan 2020 13:51:34 -0700 Subject: [PATCH] Add "compliant" option to ssl_verify_client for CORS support Message-ID: <4ba211814386f2e4adcd.1579121494@samps-dus> # HG changeset patch # User Sampson Crowley # Date 1579118065 25200 # Wed Jan 15 12:54:25 2020 -0700 # Node ID 4ba211814386f2e4adcd855b27d7d2534a5036a7 # Parent 8a7b59347401bba7b018c7292409ab095ce83466 Add "compliant" option to ssl_verify_client for CORS support The CORS Spec specifically prohibits any form of credentials during preflight checks. Because "on" fails ALL requests if a certificate is not provided, it becomes impossible to use "ssl_verify_client on;" with spec compliant browsers and CORS, namely Firefox. I didnt want to break any configs that rely on or prefer that failure to occur, so I added an additional option to allow only OPTIONS requests to bypass the client certificate validation. diff -r 8a7b59347401 -r 4ba211814386 src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c Tue Jan 14 14:20:08 2020 +0300 +++ b/src/http/modules/ngx_http_ssl_module.c Wed Jan 15 12:54:25 2020 -0700 @@ -70,6 +70,7 @@ { ngx_string("on"), 1 }, { ngx_string("optional"), 2 }, { ngx_string("optional_no_ca"), 3 }, + { ngx_string("compliant"), 4 }, { ngx_null_string, 0 } }; diff -r 8a7b59347401 -r 4ba211814386 src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c Tue Jan 14 14:20:08 2020 +0300 +++ b/src/http/ngx_http_request.c Wed Jan 15 12:54:25 2020 -0700 @@ -2016,10 +2016,12 @@ return; } - if (sscf->verify == 1) { + if (sscf->verify == 1 || sscf->verify == 4) { cert = SSL_get_peer_certificate(c->ssl->connection); - if (cert == NULL) { + if (cert == NULL + && (sscf->verify != 4 || r->method != NGX_HTTP_OPTIONS)) + { ngx_log_error(NGX_LOG_INFO, c->log, 0, "client sent no required SSL certificate"); @@ -2030,7 +2032,9 @@ return; } - X509_free(cert); + if(cert != NULL) { + X509_free(cert); + } } } } diff -r 8a7b59347401 -r 4ba211814386 src/mail/ngx_mail_ssl_module.c --- a/src/mail/ngx_mail_ssl_module.c Tue Jan 14 14:20:08 2020 +0300 +++ b/src/mail/ngx_mail_ssl_module.c Wed Jan 15 12:54:25 2020 -0700 @@ -52,6 +52,7 @@ { ngx_string("on"), 1 }, { ngx_string("optional"), 2 }, { ngx_string("optional_no_ca"), 3 }, + { ngx_string("compliant"), 1 }, { ngx_null_string, 0 } }; diff -r 8a7b59347401 -r 4ba211814386 src/stream/ngx_stream_ssl_module.c --- a/src/stream/ngx_stream_ssl_module.c Tue Jan 14 14:20:08 2020 +0300 +++ b/src/stream/ngx_stream_ssl_module.c Wed Jan 15 12:54:25 2020 -0700 @@ -64,6 +64,7 @@ { ngx_string("on"), 1 }, { ngx_string("optional"), 2 }, { ngx_string("optional_no_ca"), 3 }, + { ngx_string("compliant"), 1 }, { ngx_null_string, 0 } }; From mdounin at mdounin.ru Thu Jan 16 12:08:58 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 16 Jan 2020 15:08:58 +0300 Subject: [PATCH] Add "compliant" option to ssl_verify_client for CORS support In-Reply-To: <4ba211814386f2e4adcd.1579121494@samps-dus> References: <4ba211814386f2e4adcd.1579121494@samps-dus> Message-ID: <20200116120858.GL12894@mdounin.ru> Hello! On Wed, Jan 15, 2020 at 01:51:34PM -0700, sampsonsprojects at gmail.com wrote: > # HG changeset patch > # User Sampson Crowley > # Date 1579118065 25200 > # Wed Jan 15 12:54:25 2020 -0700 > # Node ID 4ba211814386f2e4adcd855b27d7d2534a5036a7 > # Parent 8a7b59347401bba7b018c7292409ab095ce83466 > Add "compliant" option to ssl_verify_client for CORS support > > The CORS Spec specifically prohibits any form of credentials > during preflight checks. Because "on" fails ALL requests if > a certificate is not provided, it becomes impossible to use > "ssl_verify_client on;" with spec compliant browsers and CORS, > namely Firefox. I didnt want to break any configs that rely on > or prefer that failure to occur, so I added an additional option > to allow only OPTIONS requests to bypass the client certificate > validation. Thanks for the patch. In no particular order: - The argument name suggested looks wrong and misleading, it says nothing about what the particular setting is expected to do. - The behaviour you are implementing can be configured without any additional arguments, by using "ssl_verify_client optional;" and appropriate checks during request processing. For example: ssl_verify_client optional; set $allow 0; if ($ssl_client_verify = OK) { set $allow 1; } if ($method = OPTIONS) { set $allow 1; } if (!$allow) { return 496; } While the currently required configuration might be a bit too complex for typical tasks, using CORS with SSL certificate verification is probably rare enough to don't care. On the other hand, if we nevertheless want to simplify it, a better solution might be to do this with a simplier checks during request processing, instead of introduction of a CORS-specific argument to an SSL-level configuration directive. -- Maxim Dounin http://mdounin.ru/ From xeioex at nginx.com Thu Jan 16 12:15:42 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 16 Jan 2020 12:15:42 +0000 Subject: [njs] Added support for typed-arrays in String.bytesFrom(). Message-ID: details: https://hg.nginx.org/njs/rev/cb4f1052954f branches: changeset: 1300:cb4f1052954f user: Dmitry Volyntsev date: Thu Jan 16 15:14:38 2020 +0300 description: Added support for typed-arrays in String.bytesFrom(). diffstat: src/njs_string.c | 146 +++++++++++++++++++++++++++++++--------------- src/test/njs_unit_test.c | 20 +++++- 2 files changed, 117 insertions(+), 49 deletions(-) diffs (239 lines): diff -r b840b7af946e -r cb4f1052954f src/njs_string.c --- a/src/njs_string.c Tue Jan 14 16:52:42 2020 +0300 +++ b/src/njs_string.c Thu Jan 16 15:14:38 2020 +0300 @@ -64,10 +64,10 @@ static njs_int_t njs_string_from_code_po njs_uint_t nargs, njs_index_t unused); static njs_int_t njs_string_bytes_from(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused); -static njs_int_t njs_string_bytes_from_array(njs_vm_t *vm, - const njs_value_t *value); +static njs_int_t njs_string_bytes_from_array_like(njs_vm_t *vm, + njs_value_t *value); static njs_int_t njs_string_bytes_from_string(njs_vm_t *vm, - const njs_value_t *args, njs_uint_t nargs); + const njs_value_t *string, const njs_value_t *encoding); static njs_int_t njs_string_starts_or_ends_with(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_bool_t starts); static njs_int_t njs_string_trim(njs_vm_t *vm, njs_value_t *value, @@ -1603,8 +1603,8 @@ done: /* - * String.bytesFrom(array). - * Converts an array containing octets into a byte string. + * String.bytesFrom(array-like). + * Converts an array-like object containing octets into a byte string. * * String.bytesFrom(string[, encoding]). * Converts a string using provided encoding: hex, base64, base64url to @@ -1619,38 +1619,63 @@ njs_string_bytes_from(njs_vm_t *vm, njs_ value = njs_arg(args, nargs, 1); - if (njs_is_string(value)) { - return njs_string_bytes_from_string(vm, args, nargs); - } - - if (njs_is_array(value)) { - return njs_string_bytes_from_array(vm, njs_arg(args, nargs, 1)); - } - - njs_type_error(vm, "value must be a string or array"); + switch (value->type) { + case NJS_OBJECT_STRING: + value = njs_object_value(value); + + /* Fall through. */ + + case NJS_STRING: + return njs_string_bytes_from_string(vm, value, njs_arg(args, nargs, 2)); + + default: + if (njs_is_object(value)) { + return njs_string_bytes_from_array_like(vm, value); + } + } + + njs_type_error(vm, "value must be a string or array-like object"); return NJS_ERROR; } static njs_int_t -njs_string_bytes_from_array(njs_vm_t *vm, const njs_value_t *value) +njs_string_bytes_from_array_like(njs_vm_t *vm, njs_value_t *value) { - u_char *p; - uint32_t i, length; - njs_int_t ret; - njs_array_t *array; - njs_value_t *octet; - - array = njs_array(value); - length = array->length; - - for (i = 0; i < length; i++) { - if (!njs_is_numeric(&array->start[i])) { - ret = njs_value_to_numeric(vm, &array->start[i], &array->start[i]); - if (ret != NJS_OK) { - return ret; - } + u_char *p; + uint32_t u32, length; + njs_int_t ret; + njs_array_t *array; + njs_value_t *octet, index, prop; + njs_array_buffer_t *buffer; + + array = NULL; + buffer = NULL; + + switch (value->type) { + case NJS_ARRAY: + array = njs_array(value); + length = array->length; + break; + + case NJS_ARRAY_BUFFER: + case NJS_TYPED_ARRAY: + + if (njs_is_typed_array(value)) { + buffer = njs_typed_array(value)->buffer; + + } else { + buffer = njs_array_buffer(value); + } + + length = buffer->size; + break; + + default: + ret = njs_object_length(vm, value, &length); + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; } } @@ -1659,12 +1684,42 @@ njs_string_bytes_from_array(njs_vm_t *vm return NJS_ERROR; } - octet = array->start; - - while (length != 0) { - *p++ = (u_char) njs_number_to_uint32(njs_number(octet)); - octet++; - length--; + if (array != NULL) { + octet = array->start; + + while (length != 0) { + ret = njs_value_to_uint32(vm, octet, &u32); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + *p++ = (u_char) u32; + octet++; + length--; + } + + } else if (buffer != NULL) { + memcpy(p, buffer->u.u8, length); + + } else { + p += length - 1; + + while (length != 0) { + njs_uint32_to_string(&index, length - 1); + + ret = njs_value_property(vm, value, &index, &prop); + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } + + ret = njs_value_to_uint32(vm, &prop, &u32); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + *p-- = (u_char) u32; + length--; + } } return NJS_OK; @@ -1672,21 +1727,18 @@ njs_string_bytes_from_array(njs_vm_t *vm static njs_int_t -njs_string_bytes_from_string(njs_vm_t *vm, const njs_value_t *args, - njs_uint_t nargs) +njs_string_bytes_from_string(njs_vm_t *vm, const njs_value_t *string, + const njs_value_t *encoding) { - njs_str_t enc, str; - njs_value_t *enc_val; - - enc_val = njs_arg(args, nargs, 2); - - if (njs_slow_path(nargs > 1 && !njs_is_string(enc_val))) { - njs_type_error(vm, "encoding must be a string"); + njs_str_t enc, str; + + if (!njs_is_string(encoding)) { + njs_type_error(vm, "\"encoding\" must be a string"); return NJS_ERROR; } - njs_string_get(enc_val, &enc); - njs_string_get(&args[1], &str); + njs_string_get(encoding, &enc); + njs_string_get(string, &str); if (enc.length == 3 && memcmp(enc.start, "hex", 3) == 0) { return njs_string_decode_hex(vm, &vm->retval, &str); diff -r b840b7af946e -r cb4f1052954f src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Tue Jan 14 16:52:42 2020 +0300 +++ b/src/test/njs_unit_test.c Thu Jan 16 15:14:38 2020 +0300 @@ -7635,8 +7635,15 @@ static njs_unit_test_t njs_test[] = { njs_str("'abc'.padEnd(10, Symbol())"), njs_str("TypeError: Cannot convert a Symbol value to a string") }, - { njs_str("String.bytesFrom({})"), - njs_str("TypeError: value must be a string or array") }, + { njs_str("[undefined, null, Symbol()]" + ".every(v=> { try {String.bytesFrom(v);} catch(e) {return e.name == 'TypeError'} })"), + njs_str("true") }, + + { njs_str("String.bytesFrom({}).length"), + njs_str("0") }, + + { njs_str("String.bytesFrom({length:5, 0:'A'.charCodeAt(0), 2:'X', 3:NaN,4:0xfd}).toString('hex')"), + njs_str("41000000fd") }, { njs_str("String.bytesFrom([1, 2, 0.23, '5', 'A']).toString('hex')"), njs_str("0102000500") }, @@ -7644,12 +7651,21 @@ static njs_unit_test_t njs_test[] = { njs_str("String.bytesFrom([NaN, Infinity]).toString('hex')"), njs_str("0000") }, + { njs_str("String.bytesFrom(new Uint8Array([0xff,0xde,0xba])).toString('hex')"), + njs_str("ffdeba") }, + + { njs_str("String.bytesFrom((new Uint8Array([0xff,0xde,0xba])).buffer).toString('hex')"), + njs_str("ffdeba") }, + { njs_str("String.bytesFrom('', 'hex')"), njs_str("") }, { njs_str("String.bytesFrom('00aabbcc', 'hex').toString('hex')"), njs_str("00aabbcc") }, + { njs_str("String.bytesFrom(new String('00aabbcc'), 'hex').toString('hex')"), + njs_str("00aabbcc") }, + { njs_str("String.bytesFrom('deadBEEF##', 'hex').toString('hex')"), njs_str("deadbeef") }, From vl at nginx.com Thu Jan 16 14:43:09 2020 From: vl at nginx.com (Vladimir Homutov) Date: Thu, 16 Jan 2020 17:43:09 +0300 Subject: [PATCH nginx v2] remove ngx_cpuinfo, use sysconf or define In-Reply-To: References: Message-ID: <20200116144309.GA2627064@vlpc> On Fri, Jan 03, 2020 at 02:39:29PM -0800, Joe Konno wrote: > # HG changeset patch > # User Joe Konno > # Date 1578075036 28800 > # Fri Jan 03 10:10:36 2020 -0800 > # Node ID b66ee34cea2f539bb8ce4986d6bd332f75ee06b6 > # Parent f1720934c45be1c6469841a55d1f31fe9a630c85 > remove ngx_cpuinfo, use sysconf or define > > Function ngx_cpuinfo() is used to (sub-optimally) determine the value of > ngx_cacheline_size on x86 hardware. On hardware running Linux, there may be a > sysconf call that correctly reports the cache line size using architecturally > appropriate methods-- for x86 hardware, the CPUID instruction. > > Therefore, ngx_cpuinfo is no longer needed. If said sysconf call is > unavailable, set ngx_cachline_size to defined NGX_CPU_CACHE_LINE, the value of > which is determined at configure time. > > Signed-off-by: Joe Konno > > diff -r f1720934c45b -r b66ee34cea2f auto/sources > --- a/auto/sources Fri Dec 27 19:43:01 2019 +0300 > +++ b/auto/sources Fri Jan 03 10:10:36 2020 -0800 > @@ -71,7 +71,6 @@ > src/core/ngx_cycle.c \ > src/core/ngx_spinlock.c \ > src/core/ngx_rwlock.c \ > - src/core/ngx_cpuinfo.c \ > src/core/ngx_conf_file.c \ > src/core/ngx_module.c \ > src/core/ngx_resolver.c \ > diff -r f1720934c45b -r b66ee34cea2f src/core/ngx_core.h > --- a/src/core/ngx_core.h Fri Dec 27 19:43:01 2019 +0300 > +++ b/src/core/ngx_core.h Fri Jan 03 10:10:36 2020 -0800 > @@ -102,7 +102,6 @@ > #define ngx_max(val1, val2) ((val1 < val2) ? (val2) : (val1)) > #define ngx_min(val1, val2) ((val1 > val2) ? (val2) : (val1)) > > -void ngx_cpuinfo(void); > > #if (NGX_HAVE_OPENAT) > #define NGX_DISABLE_SYMLINKS_OFF 0 > diff -r f1720934c45b -r b66ee34cea2f src/core/ngx_cpuinfo.c > --- a/src/core/ngx_cpuinfo.c Fri Dec 27 19:43:01 2019 +0300 > +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 > @@ -1,139 +0,0 @@ > - > -/* > - * Copyright (C) Igor Sysoev > - * Copyright (C) Nginx, Inc. > - */ > - > - > -#include > -#include > - > - > -#if (( __i386__ || __amd64__ ) && ( __GNUC__ || __INTEL_COMPILER )) > - > - > -static ngx_inline void ngx_cpuid(uint32_t i, uint32_t *buf); > - > - > -#if ( __i386__ ) > - > -static ngx_inline void > -ngx_cpuid(uint32_t i, uint32_t *buf) > -{ > - > - /* > - * we could not use %ebx as output parameter if gcc builds PIC, > - * and we could not save %ebx on stack, because %esp is used, > - * when the -fomit-frame-pointer optimization is specified. > - */ > - > - __asm__ ( > - > - " mov %%ebx, %%esi; " > - > - " cpuid; " > - " mov %%eax, (%1); " > - " mov %%ebx, 4(%1); " > - " mov %%edx, 8(%1); " > - " mov %%ecx, 12(%1); " > - > - " mov %%esi, %%ebx; " > - > - : : "a" (i), "D" (buf) : "ecx", "edx", "esi", "memory" ); > -} > - > - > -#else /* __amd64__ */ > - > - > -static ngx_inline void > -ngx_cpuid(uint32_t i, uint32_t *buf) > -{ > - uint32_t eax, ebx, ecx, edx; > - > - __asm__ ( > - > - "cpuid" > - > - : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (i) ); > - > - buf[0] = eax; > - buf[1] = ebx; > - buf[2] = edx; > - buf[3] = ecx; > -} > - > - > -#endif > - > - > -/* auto detect the L2 cache line size of modern and widespread CPUs */ > - > -void > -ngx_cpuinfo(void) > -{ > - u_char *vendor; > - uint32_t vbuf[5], cpu[4], model; > - > - vbuf[0] = 0; > - vbuf[1] = 0; > - vbuf[2] = 0; > - vbuf[3] = 0; > - vbuf[4] = 0; > - > - ngx_cpuid(0, vbuf); > - > - vendor = (u_char *) &vbuf[1]; > - > - if (vbuf[0] == 0) { > - return; > - } > - > - ngx_cpuid(1, cpu); > - > - if (ngx_strcmp(vendor, "GenuineIntel") == 0) { > - > - switch ((cpu[0] & 0xf00) >> 8) { > - > - /* Pentium */ > - case 5: > - ngx_cacheline_size = 32; > - break; > - > - /* Pentium Pro, II, III */ > - case 6: > - ngx_cacheline_size = 32; > - > - model = ((cpu[0] & 0xf0000) >> 8) | (cpu[0] & 0xf0); > - > - if (model >= 0xd0) { > - /* Intel Core, Core 2, Atom */ > - ngx_cacheline_size = 64; > - } > - > - break; > - > - /* > - * Pentium 4, although its cache line size is 64 bytes, > - * it prefetches up to two cache lines during memory read > - */ > - case 15: > - ngx_cacheline_size = 128; > - break; > - } > - > - } else if (ngx_strcmp(vendor, "AuthenticAMD") == 0) { > - ngx_cacheline_size = 64; > - } > -} > - > -#else > - > - > -void > -ngx_cpuinfo(void) > -{ > -} > - > - > -#endif > diff -r f1720934c45b -r b66ee34cea2f src/os/unix/ngx_posix_init.c > --- a/src/os/unix/ngx_posix_init.c Fri Dec 27 19:43:01 2019 +0300 > +++ b/src/os/unix/ngx_posix_init.c Fri Jan 03 10:10:36 2020 -0800 > @@ -51,10 +51,20 @@ > } > > ngx_pagesize = getpagesize(); > - ngx_cacheline_size = NGX_CPU_CACHE_LINE; > > for (n = ngx_pagesize; n >>= 1; ngx_pagesize_shift++) { /* void */ } > > +#if (NGX_HAVE_LEVEL1_DCACHE_LINESIZE) > + size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE); > + if (size > 0) { > + ngx_cacheline_size = size; > + } else { > + ngx_cacheline_size = NGX_CPU_CACHE_LINE; > + } > +#else > + ngx_cacheline_size = NGX_CPU_CACHE_LINE; > +#endif > + > #if (NGX_HAVE_SC_NPROCESSORS_ONLN) > if (ngx_ncpu == 0) { > ngx_ncpu = sysconf(_SC_NPROCESSORS_ONLN); > @@ -65,15 +75,6 @@ > ngx_ncpu = 1; > } > > -#if (NGX_HAVE_LEVEL1_DCACHE_LINESIZE) > - size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE); > - if (size > 0) { > - ngx_cacheline_size = size; > - } > -#endif > - > - ngx_cpuinfo(); > - > if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) { > ngx_log_error(NGX_LOG_ALERT, log, errno, > "getrlimit(RLIMIT_NOFILE) failed"); > Thank you for sharing! Removing ngx_cpuinfo() doesn't look correct: by doing this you deprive non-Linux systems (BSDs, windows and some others) support for CPU detection. From sampson at downundersports.com Thu Jan 16 15:18:10 2020 From: sampson at downundersports.com (Sampson Crowley) Date: Thu, 16 Jan 2020 08:18:10 -0700 Subject: [PATCH] Add "compliant" option to ssl_verify_client for CORS support In-Reply-To: <20200116120858.GL12894@mdounin.ru> References: <4ba211814386f2e4adcd.1579121494@samps-dus> <20200116120858.GL12894@mdounin.ru> Message-ID: 1) The consumer shouldn't need a whole series of checks just to actually do things correctly and be *compliant* with the http specs 2) I don't see how "compliant" is misleading to be "compliant" with how things are SUPPOSED to work in the first place On Thu, Jan 16, 2020, 05:09 Maxim Dounin wrote: > Hello! > > On Wed, Jan 15, 2020 at 01:51:34PM -0700, sampsonsprojects at gmail.com > wrote: > > > # HG changeset patch > > # User Sampson Crowley > > # Date 1579118065 25200 > > # Wed Jan 15 12:54:25 2020 -0700 > > # Node ID 4ba211814386f2e4adcd855b27d7d2534a5036a7 > > # Parent 8a7b59347401bba7b018c7292409ab095ce83466 > > Add "compliant" option to ssl_verify_client for CORS support > > > > The CORS Spec specifically prohibits any form of credentials > > during preflight checks. Because "on" fails ALL requests if > > a certificate is not provided, it becomes impossible to use > > "ssl_verify_client on;" with spec compliant browsers and CORS, > > namely Firefox. I didnt want to break any configs that rely on > > or prefer that failure to occur, so I added an additional option > > to allow only OPTIONS requests to bypass the client certificate > > validation. > > Thanks for the patch. > > In no particular order: > > - The argument name suggested looks wrong and misleading, it says > nothing about what the particular setting is expected to do. > > - The behaviour you are implementing can be configured without any > additional arguments, by using "ssl_verify_client optional;" and > appropriate checks during request processing. For example: > > ssl_verify_client optional; > > set $allow 0; > > if ($ssl_client_verify = OK) { > set $allow 1; > } > > if ($method = OPTIONS) { > set $allow 1; > } > > if (!$allow) { > return 496; > } > > While the currently required configuration might be a bit too > complex for typical tasks, using CORS with SSL certificate > verification is probably rare enough to don't care. On the other > hand, if we nevertheless want to simplify it, a better solution > might be to do this with a simplier checks during request > processing, instead of introduction of a CORS-specific argument to > an SSL-level configuration directive. > > -- > Maxim Dounin > http://mdounin.ru/ > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -------------- next part -------------- An HTML attachment was scrubbed... URL: From joe.konno at linux.intel.com Thu Jan 16 15:39:07 2020 From: joe.konno at linux.intel.com (Joe Konno) Date: Thu, 16 Jan 2020 07:39:07 -0800 Subject: [PATCH nginx v2] remove ngx_cpuinfo, use sysconf or define In-Reply-To: <20200116144309.GA2627064@vlpc> References: <20200116144309.GA2627064@vlpc> Message-ID: <17c636cf-035c-9deb-d2ee-97ad6142f051@linux.intel.com> Scroll to bottom: On 1/16/20 6:43 AM, Vladimir Homutov wrote: > On Fri, Jan 03, 2020 at 02:39:29PM -0800, Joe Konno wrote: >> # HG changeset patch >> # User Joe Konno >> # Date 1578075036 28800 >> # Fri Jan 03 10:10:36 2020 -0800 >> # Node ID b66ee34cea2f539bb8ce4986d6bd332f75ee06b6 >> # Parent f1720934c45be1c6469841a55d1f31fe9a630c85 >> remove ngx_cpuinfo, use sysconf or define >> >> Function ngx_cpuinfo() is used to (sub-optimally) determine the value of >> ngx_cacheline_size on x86 hardware. On hardware running Linux, there may be a >> sysconf call that correctly reports the cache line size using architecturally >> appropriate methods-- for x86 hardware, the CPUID instruction. >> >> Therefore, ngx_cpuinfo is no longer needed. If said sysconf call is >> unavailable, set ngx_cachline_size to defined NGX_CPU_CACHE_LINE, the value of >> which is determined at configure time. >> >> Signed-off-by: Joe Konno >> >> diff -r f1720934c45b -r b66ee34cea2f auto/sources >> --- a/auto/sources Fri Dec 27 19:43:01 2019 +0300 >> +++ b/auto/sources Fri Jan 03 10:10:36 2020 -0800 >> @@ -71,7 +71,6 @@ >> src/core/ngx_cycle.c \ >> src/core/ngx_spinlock.c \ >> src/core/ngx_rwlock.c \ >> - src/core/ngx_cpuinfo.c \ >> src/core/ngx_conf_file.c \ >> src/core/ngx_module.c \ >> src/core/ngx_resolver.c \ >> diff -r f1720934c45b -r b66ee34cea2f src/core/ngx_core.h >> --- a/src/core/ngx_core.h Fri Dec 27 19:43:01 2019 +0300 >> +++ b/src/core/ngx_core.h Fri Jan 03 10:10:36 2020 -0800 >> @@ -102,7 +102,6 @@ >> #define ngx_max(val1, val2) ((val1 < val2) ? (val2) : (val1)) >> #define ngx_min(val1, val2) ((val1 > val2) ? (val2) : (val1)) >> >> -void ngx_cpuinfo(void); >> >> #if (NGX_HAVE_OPENAT) >> #define NGX_DISABLE_SYMLINKS_OFF 0 >> diff -r f1720934c45b -r b66ee34cea2f src/core/ngx_cpuinfo.c >> --- a/src/core/ngx_cpuinfo.c Fri Dec 27 19:43:01 2019 +0300 >> +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 >> @@ -1,139 +0,0 @@ >> - >> -/* >> - * Copyright (C) Igor Sysoev >> - * Copyright (C) Nginx, Inc. >> - */ >> - >> - >> -#include >> -#include >> - >> - >> -#if (( __i386__ || __amd64__ ) && ( __GNUC__ || __INTEL_COMPILER )) >> - >> - >> -static ngx_inline void ngx_cpuid(uint32_t i, uint32_t *buf); >> - >> - >> -#if ( __i386__ ) >> - >> -static ngx_inline void >> -ngx_cpuid(uint32_t i, uint32_t *buf) >> -{ >> - >> - /* >> - * we could not use %ebx as output parameter if gcc builds PIC, >> - * and we could not save %ebx on stack, because %esp is used, >> - * when the -fomit-frame-pointer optimization is specified. >> - */ >> - >> - __asm__ ( >> - >> - " mov %%ebx, %%esi; " >> - >> - " cpuid; " >> - " mov %%eax, (%1); " >> - " mov %%ebx, 4(%1); " >> - " mov %%edx, 8(%1); " >> - " mov %%ecx, 12(%1); " >> - >> - " mov %%esi, %%ebx; " >> - >> - : : "a" (i), "D" (buf) : "ecx", "edx", "esi", "memory" ); >> -} >> - >> - >> -#else /* __amd64__ */ >> - >> - >> -static ngx_inline void >> -ngx_cpuid(uint32_t i, uint32_t *buf) >> -{ >> - uint32_t eax, ebx, ecx, edx; >> - >> - __asm__ ( >> - >> - "cpuid" >> - >> - : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (i) ); >> - >> - buf[0] = eax; >> - buf[1] = ebx; >> - buf[2] = edx; >> - buf[3] = ecx; >> -} >> - >> - >> -#endif >> - >> - >> -/* auto detect the L2 cache line size of modern and widespread CPUs */ >> - >> -void >> -ngx_cpuinfo(void) >> -{ >> - u_char *vendor; >> - uint32_t vbuf[5], cpu[4], model; >> - >> - vbuf[0] = 0; >> - vbuf[1] = 0; >> - vbuf[2] = 0; >> - vbuf[3] = 0; >> - vbuf[4] = 0; >> - >> - ngx_cpuid(0, vbuf); >> - >> - vendor = (u_char *) &vbuf[1]; >> - >> - if (vbuf[0] == 0) { >> - return; >> - } >> - >> - ngx_cpuid(1, cpu); >> - >> - if (ngx_strcmp(vendor, "GenuineIntel") == 0) { >> - >> - switch ((cpu[0] & 0xf00) >> 8) { >> - >> - /* Pentium */ >> - case 5: >> - ngx_cacheline_size = 32; >> - break; >> - >> - /* Pentium Pro, II, III */ >> - case 6: >> - ngx_cacheline_size = 32; >> - >> - model = ((cpu[0] & 0xf0000) >> 8) | (cpu[0] & 0xf0); >> - >> - if (model >= 0xd0) { >> - /* Intel Core, Core 2, Atom */ >> - ngx_cacheline_size = 64; >> - } >> - >> - break; >> - >> - /* >> - * Pentium 4, although its cache line size is 64 bytes, >> - * it prefetches up to two cache lines during memory read >> - */ >> - case 15: >> - ngx_cacheline_size = 128; >> - break; >> - } >> - >> - } else if (ngx_strcmp(vendor, "AuthenticAMD") == 0) { >> - ngx_cacheline_size = 64; >> - } >> -} >> - >> -#else >> - >> - >> -void >> -ngx_cpuinfo(void) >> -{ >> -} >> - >> - >> -#endif >> diff -r f1720934c45b -r b66ee34cea2f src/os/unix/ngx_posix_init.c >> --- a/src/os/unix/ngx_posix_init.c Fri Dec 27 19:43:01 2019 +0300 >> +++ b/src/os/unix/ngx_posix_init.c Fri Jan 03 10:10:36 2020 -0800 >> @@ -51,10 +51,20 @@ >> } >> >> ngx_pagesize = getpagesize(); >> - ngx_cacheline_size = NGX_CPU_CACHE_LINE; >> >> for (n = ngx_pagesize; n >>= 1; ngx_pagesize_shift++) { /* void */ } >> >> +#if (NGX_HAVE_LEVEL1_DCACHE_LINESIZE) >> + size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE); >> + if (size > 0) { >> + ngx_cacheline_size = size; >> + } else { >> + ngx_cacheline_size = NGX_CPU_CACHE_LINE; >> + } >> +#else >> + ngx_cacheline_size = NGX_CPU_CACHE_LINE; >> +#endif >> + >> #if (NGX_HAVE_SC_NPROCESSORS_ONLN) >> if (ngx_ncpu == 0) { >> ngx_ncpu = sysconf(_SC_NPROCESSORS_ONLN); >> @@ -65,15 +75,6 @@ >> ngx_ncpu = 1; >> } >> >> -#if (NGX_HAVE_LEVEL1_DCACHE_LINESIZE) >> - size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE); >> - if (size > 0) { >> - ngx_cacheline_size = size; >> - } >> -#endif >> - >> - ngx_cpuinfo(); >> - >> if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) { >> ngx_log_error(NGX_LOG_ALERT, log, errno, >> "getrlimit(RLIMIT_NOFILE) failed"); >> > > Thank you for sharing! > > Removing ngx_cpuinfo() doesn't look correct: by doing this you deprive > non-Linux systems (BSDs, windows and some others) support for CPU detection. Valid point. Thanks for reviewing. v1 of that patch used CPUID to retrieve the cache line size directly from H/W: http://mailman.nginx.org/pipermail/nginx-devel/2019-December/012853.html From sampson at downundersports.com Thu Jan 16 15:39:08 2020 From: sampson at downundersports.com (Sampson Crowley) Date: Thu, 16 Jan 2020 08:39:08 -0700 Subject: [PATCH] Add "compliant" option to ssl_verify_client for CORS support In-Reply-To: References: <4ba211814386f2e4adcd.1579121494@samps-dus> <20200116120858.GL12894@mdounin.ru> Message-ID: What if it's changed to "preflight_optional" or "on_spec_compliant" is that a better description in your opinion? On Thu, Jan 16, 2020, 08:18 Sampson Crowley wrote: > 1) The consumer shouldn't need a whole series of checks just to actually > do things correctly and be *compliant* with the http specs > > 2) I don't see how "compliant" is misleading to be "compliant" with how > things are SUPPOSED to work in the first place > > On Thu, Jan 16, 2020, 05:09 Maxim Dounin wrote: > >> Hello! >> >> On Wed, Jan 15, 2020 at 01:51:34PM -0700, sampsonsprojects at gmail.com >> wrote: >> >> > # HG changeset patch >> > # User Sampson Crowley >> > # Date 1579118065 25200 >> > # Wed Jan 15 12:54:25 2020 -0700 >> > # Node ID 4ba211814386f2e4adcd855b27d7d2534a5036a7 >> > # Parent 8a7b59347401bba7b018c7292409ab095ce83466 >> > Add "compliant" option to ssl_verify_client for CORS support >> > >> > The CORS Spec specifically prohibits any form of credentials >> > during preflight checks. Because "on" fails ALL requests if >> > a certificate is not provided, it becomes impossible to use >> > "ssl_verify_client on;" with spec compliant browsers and CORS, >> > namely Firefox. I didnt want to break any configs that rely on >> > or prefer that failure to occur, so I added an additional option >> > to allow only OPTIONS requests to bypass the client certificate >> > validation. >> >> Thanks for the patch. >> >> In no particular order: >> >> - The argument name suggested looks wrong and misleading, it says >> nothing about what the particular setting is expected to do. >> >> - The behaviour you are implementing can be configured without any >> additional arguments, by using "ssl_verify_client optional;" and >> appropriate checks during request processing. For example: >> >> ssl_verify_client optional; >> >> set $allow 0; >> >> if ($ssl_client_verify = OK) { >> set $allow 1; >> } >> >> if ($method = OPTIONS) { >> set $allow 1; >> } >> >> if (!$allow) { >> return 496; >> } >> >> While the currently required configuration might be a bit too >> complex for typical tasks, using CORS with SSL certificate >> verification is probably rare enough to don't care. On the other >> hand, if we nevertheless want to simplify it, a better solution >> might be to do this with a simplier checks during request >> processing, instead of introduction of a CORS-specific argument to >> an SSL-level configuration directive. >> >> -- >> Maxim Dounin >> http://mdounin.ru/ >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From vl at nginx.com Thu Jan 16 15:46:45 2020 From: vl at nginx.com (Vladimir Homutov) Date: Thu, 16 Jan 2020 18:46:45 +0300 Subject: [PATCH nginx v2] remove ngx_cpuinfo, use sysconf or define In-Reply-To: <17c636cf-035c-9deb-d2ee-97ad6142f051@linux.intel.com> References: <20200116144309.GA2627064@vlpc> <17c636cf-035c-9deb-d2ee-97ad6142f051@linux.intel.com> Message-ID: <20200116154645.GA2631367@vlpc> On Thu, Jan 16, 2020 at 07:39:07AM -0800, Joe Konno wrote: > Scroll to bottom: > > On 1/16/20 6:43 AM, Vladimir Homutov wrote: > > On Fri, Jan 03, 2020 at 02:39:29PM -0800, Joe Konno wrote: > >> # HG changeset patch > >> # User Joe Konno > >> # Date 1578075036 28800 > >> # Fri Jan 03 10:10:36 2020 -0800 > >> # Node ID b66ee34cea2f539bb8ce4986d6bd332f75ee06b6 > >> # Parent f1720934c45be1c6469841a55d1f31fe9a630c85 > >> remove ngx_cpuinfo, use sysconf or define > >> > >> Function ngx_cpuinfo() is used to (sub-optimally) determine the value of > >> ngx_cacheline_size on x86 hardware. On hardware running Linux, there may be a > >> sysconf call that correctly reports the cache line size using architecturally > >> appropriate methods-- for x86 hardware, the CPUID instruction. > >> > >> Therefore, ngx_cpuinfo is no longer needed. If said sysconf call is > >> unavailable, set ngx_cachline_size to defined NGX_CPU_CACHE_LINE, the value of > >> which is determined at configure time. > >> > >> Signed-off-by: Joe Konno > >> > >> diff -r f1720934c45b -r b66ee34cea2f auto/sources > >> --- a/auto/sources Fri Dec 27 19:43:01 2019 +0300 > >> +++ b/auto/sources Fri Jan 03 10:10:36 2020 -0800 > >> @@ -71,7 +71,6 @@ > >> src/core/ngx_cycle.c \ > >> src/core/ngx_spinlock.c \ > >> src/core/ngx_rwlock.c \ > >> - src/core/ngx_cpuinfo.c \ > >> src/core/ngx_conf_file.c \ > >> src/core/ngx_module.c \ > >> src/core/ngx_resolver.c \ > >> diff -r f1720934c45b -r b66ee34cea2f src/core/ngx_core.h > >> --- a/src/core/ngx_core.h Fri Dec 27 19:43:01 2019 +0300 > >> +++ b/src/core/ngx_core.h Fri Jan 03 10:10:36 2020 -0800 > >> @@ -102,7 +102,6 @@ > >> #define ngx_max(val1, val2) ((val1 < val2) ? (val2) : (val1)) > >> #define ngx_min(val1, val2) ((val1 > val2) ? (val2) : (val1)) > >> > >> -void ngx_cpuinfo(void); > >> > >> #if (NGX_HAVE_OPENAT) > >> #define NGX_DISABLE_SYMLINKS_OFF 0 > >> diff -r f1720934c45b -r b66ee34cea2f src/core/ngx_cpuinfo.c > >> --- a/src/core/ngx_cpuinfo.c Fri Dec 27 19:43:01 2019 +0300 > >> +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 > >> @@ -1,139 +0,0 @@ > >> - > >> -/* > >> - * Copyright (C) Igor Sysoev > >> - * Copyright (C) Nginx, Inc. > >> - */ > >> - > >> - > >> -#include > >> -#include > >> - > >> - > >> -#if (( __i386__ || __amd64__ ) && ( __GNUC__ || __INTEL_COMPILER )) > >> - > >> - > >> -static ngx_inline void ngx_cpuid(uint32_t i, uint32_t *buf); > >> - > >> - > >> -#if ( __i386__ ) > >> - > >> -static ngx_inline void > >> -ngx_cpuid(uint32_t i, uint32_t *buf) > >> -{ > >> - > >> - /* > >> - * we could not use %ebx as output parameter if gcc builds PIC, > >> - * and we could not save %ebx on stack, because %esp is used, > >> - * when the -fomit-frame-pointer optimization is specified. > >> - */ > >> - > >> - __asm__ ( > >> - > >> - " mov %%ebx, %%esi; " > >> - > >> - " cpuid; " > >> - " mov %%eax, (%1); " > >> - " mov %%ebx, 4(%1); " > >> - " mov %%edx, 8(%1); " > >> - " mov %%ecx, 12(%1); " > >> - > >> - " mov %%esi, %%ebx; " > >> - > >> - : : "a" (i), "D" (buf) : "ecx", "edx", "esi", "memory" ); > >> -} > >> - > >> - > >> -#else /* __amd64__ */ > >> - > >> - > >> -static ngx_inline void > >> -ngx_cpuid(uint32_t i, uint32_t *buf) > >> -{ > >> - uint32_t eax, ebx, ecx, edx; > >> - > >> - __asm__ ( > >> - > >> - "cpuid" > >> - > >> - : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (i) ); > >> - > >> - buf[0] = eax; > >> - buf[1] = ebx; > >> - buf[2] = edx; > >> - buf[3] = ecx; > >> -} > >> - > >> - > >> -#endif > >> - > >> - > >> -/* auto detect the L2 cache line size of modern and widespread CPUs */ > >> - > >> -void > >> -ngx_cpuinfo(void) > >> -{ > >> - u_char *vendor; > >> - uint32_t vbuf[5], cpu[4], model; > >> - > >> - vbuf[0] = 0; > >> - vbuf[1] = 0; > >> - vbuf[2] = 0; > >> - vbuf[3] = 0; > >> - vbuf[4] = 0; > >> - > >> - ngx_cpuid(0, vbuf); > >> - > >> - vendor = (u_char *) &vbuf[1]; > >> - > >> - if (vbuf[0] == 0) { > >> - return; > >> - } > >> - > >> - ngx_cpuid(1, cpu); > >> - > >> - if (ngx_strcmp(vendor, "GenuineIntel") == 0) { > >> - > >> - switch ((cpu[0] & 0xf00) >> 8) { > >> - > >> - /* Pentium */ > >> - case 5: > >> - ngx_cacheline_size = 32; > >> - break; > >> - > >> - /* Pentium Pro, II, III */ > >> - case 6: > >> - ngx_cacheline_size = 32; > >> - > >> - model = ((cpu[0] & 0xf0000) >> 8) | (cpu[0] & 0xf0); > >> - > >> - if (model >= 0xd0) { > >> - /* Intel Core, Core 2, Atom */ > >> - ngx_cacheline_size = 64; > >> - } > >> - > >> - break; > >> - > >> - /* > >> - * Pentium 4, although its cache line size is 64 bytes, > >> - * it prefetches up to two cache lines during memory read > >> - */ > >> - case 15: > >> - ngx_cacheline_size = 128; > >> - break; > >> - } > >> - > >> - } else if (ngx_strcmp(vendor, "AuthenticAMD") == 0) { > >> - ngx_cacheline_size = 64; > >> - } > >> -} > >> - > >> -#else > >> - > >> - > >> -void > >> -ngx_cpuinfo(void) > >> -{ > >> -} > >> - > >> - > >> -#endif > >> diff -r f1720934c45b -r b66ee34cea2f src/os/unix/ngx_posix_init.c > >> --- a/src/os/unix/ngx_posix_init.c Fri Dec 27 19:43:01 2019 +0300 > >> +++ b/src/os/unix/ngx_posix_init.c Fri Jan 03 10:10:36 2020 -0800 > >> @@ -51,10 +51,20 @@ > >> } > >> > >> ngx_pagesize = getpagesize(); > >> - ngx_cacheline_size = NGX_CPU_CACHE_LINE; > >> > >> for (n = ngx_pagesize; n >>= 1; ngx_pagesize_shift++) { /* void */ } > >> > >> +#if (NGX_HAVE_LEVEL1_DCACHE_LINESIZE) > >> + size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE); > >> + if (size > 0) { > >> + ngx_cacheline_size = size; > >> + } else { > >> + ngx_cacheline_size = NGX_CPU_CACHE_LINE; > >> + } > >> +#else > >> + ngx_cacheline_size = NGX_CPU_CACHE_LINE; > >> +#endif > >> + > >> #if (NGX_HAVE_SC_NPROCESSORS_ONLN) > >> if (ngx_ncpu == 0) { > >> ngx_ncpu = sysconf(_SC_NPROCESSORS_ONLN); > >> @@ -65,15 +75,6 @@ > >> ngx_ncpu = 1; > >> } > >> > >> -#if (NGX_HAVE_LEVEL1_DCACHE_LINESIZE) > >> - size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE); > >> - if (size > 0) { > >> - ngx_cacheline_size = size; > >> - } > >> -#endif > >> - > >> - ngx_cpuinfo(); > >> - > >> if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) { > >> ngx_log_error(NGX_LOG_ALERT, log, errno, > >> "getrlimit(RLIMIT_NOFILE) failed"); > >> > > > > Thank you for sharing! > > > > Removing ngx_cpuinfo() doesn't look correct: by doing this you deprive > > non-Linux systems (BSDs, windows and some others) support for CPU detection. > > Valid point. Thanks for reviewing. > > v1 of that patch used CPUID to retrieve the cache line size directly > from H/W: > > http://mailman.nginx.org/pipermail/nginx-devel/2019-December/012853.html yes, I've seen this too. Although our current ngx_cpuinfo() may seem a bit outdated, it does its job, and contains some manually crafted cases. What we don't want is to make things more complex here and introduce more very specific code. If you know about specific cases when things get wrong with current implementation, please report. From xeioex at nginx.com Thu Jan 16 16:35:02 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 16 Jan 2020 16:35:02 +0000 Subject: [njs] HTTP: introduced promise support in r.subrequest(). Message-ID: details: https://hg.nginx.org/njs/rev/6fccbc9f1288 branches: changeset: 1301:6fccbc9f1288 user: Dmitry Volyntsev date: Thu Jan 16 19:18:39 2020 +0300 description: HTTP: introduced promise support in r.subrequest(). If callback is not provided r.subrequest() returns an ordinary Promise object that resolves to subrequest response object. diffstat: nginx/ngx_http_js_module.c | 86 ++++++++++++++++++++++++++++++++------------- src/njs.h | 10 +++++ src/njs_function.c | 18 +++++++++ src/njs_promise.c | 22 +++++++++++ src/njs_value.h | 2 - 5 files changed, 111 insertions(+), 27 deletions(-) diffs (254 lines): diff -r cb4f1052954f -r 6fccbc9f1288 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Thu Jan 16 15:14:38 2020 +0300 +++ b/nginx/ngx_http_js_module.c Thu Jan 16 19:18:39 2020 +0300 @@ -32,6 +32,7 @@ typedef struct { njs_opaque_value_t request; njs_opaque_value_t request_body; ngx_str_t redirect_uri; + njs_opaque_value_t promise_callbacks[2]; } ngx_http_js_ctx_t; @@ -1760,10 +1761,30 @@ ngx_http_js_ext_set_variable(njs_vm_t *v static njs_int_t +ngx_http_js_promise_trampoline(njs_vm_t *vm, njs_value_t *args, + njs_uint_t nargs, njs_index_t unused) +{ + njs_function_t *callback; + ngx_http_js_ctx_t *ctx; + ngx_http_request_t *r; + + r = njs_vm_external(vm, njs_argument(args, 1)); + ctx = ngx_http_get_module_ctx(r, ngx_http_js_module); + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "js subrequest promise trampoline ctx: %p", ctx); + + callback = njs_value_function(njs_value_arg(&ctx->promise_callbacks[0])); + + return njs_vm_call(vm, callback, njs_argument(args, 1), 1); +} + + +static njs_int_t ngx_http_js_ext_subrequest(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - ngx_int_t rc; + ngx_int_t rc, promise; njs_str_t uri_arg, args_arg, method_name, body_arg; ngx_uint_t method, methods_max, has_body; njs_value_t *value, *arg, *options; @@ -1799,6 +1820,7 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, r = njs_vm_external(vm, njs_arg(args, nargs, 0)); if (njs_slow_path(r == NULL)) { + njs_vm_error(vm, "this is not an external"); return NJS_ERROR; } @@ -1829,6 +1851,7 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, args_arg.length = 0; args_arg.start = NULL; has_body = 0; + promise = 0; arg = njs_arg(args, nargs, 2); @@ -1901,6 +1924,15 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, } } + if (callback == NULL) { + callback = njs_vm_function_alloc(vm, ngx_http_js_promise_trampoline); + if (callback == NULL) { + goto memory_error; + } + + promise = 1; + } + rc = ngx_http_js_subrequest(r, &uri_arg, &args_arg, callback, &sr); if (rc != NGX_OK) { return NJS_ERROR; @@ -1916,7 +1948,7 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, sr->method_name.data = method_name.start; } - sr->header_only = (sr->method == NGX_HTTP_HEAD) || (callback == NULL); + sr->header_only = (sr->method == NGX_HTTP_HEAD); if (has_body) { rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); @@ -1949,6 +1981,18 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, sr->headers_in.chunked = 0; } + if (promise) { + ctx = ngx_pcalloc(sr->pool, sizeof(ngx_http_js_ctx_t)); + if (ctx == NULL) { + return NGX_ERROR; + } + + ngx_http_set_ctx(sr, ctx, ngx_http_js_module); + + return njs_vm_promise_create(vm, njs_vm_retval(vm), + njs_value_arg(&ctx->promise_callbacks)); + } + return NJS_OK; memory_error: @@ -1971,31 +2015,23 @@ ngx_http_js_subrequest(ngx_http_request_ ctx = ngx_http_get_module_ctx(r, ngx_http_js_module); - flags = NGX_HTTP_SUBREQUEST_BACKGROUND; - - if (callback != NULL) { - ps = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t)); - if (ps == NULL) { - njs_vm_error(ctx->vm, "internal error"); - return NJS_ERROR; - } - - vm_event = njs_vm_add_event(ctx->vm, callback, 1, NULL, NULL); - if (vm_event == NULL) { - njs_vm_error(ctx->vm, "internal error"); - return NJS_ERROR; - } - - ps->handler = ngx_http_js_subrequest_done; - ps->data = vm_event; - - flags |= NGX_HTTP_SUBREQUEST_IN_MEMORY; - - } else { - ps = NULL; - vm_event = NULL; + flags = NGX_HTTP_SUBREQUEST_BACKGROUND | NGX_HTTP_SUBREQUEST_IN_MEMORY; + + ps = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t)); + if (ps == NULL) { + njs_vm_error(ctx->vm, "internal error"); + return NJS_ERROR; } + vm_event = njs_vm_add_event(ctx->vm, callback, 1, NULL, NULL); + if (vm_event == NULL) { + njs_vm_error(ctx->vm, "internal error"); + return NJS_ERROR; + } + + ps->handler = ngx_http_js_subrequest_done; + ps->data = vm_event; + uri.len = uri_arg->length; uri.data = uri_arg->start; diff -r cb4f1052954f -r 6fccbc9f1288 src/njs.h --- a/src/njs.h Thu Jan 16 15:14:38 2020 +0300 +++ b/src/njs.h Thu Jan 16 19:18:39 2020 +0300 @@ -102,6 +102,9 @@ struct njs_external_s { }; +typedef njs_int_t (*njs_function_native_t) (njs_vm_t *vm, njs_value_t *args, + njs_uint_t nargs, njs_index_t retval); + /* * NJS and event loops. * @@ -238,6 +241,9 @@ NJS_EXPORT njs_int_t njs_vm_external_cre NJS_EXPORT njs_external_ptr_t njs_vm_external(njs_vm_t *vm, const njs_value_t *value); +NJS_EXPORT njs_function_t *njs_vm_function_alloc(njs_vm_t *vm, + njs_function_native_t native); + NJS_EXPORT void njs_disassembler(njs_vm_t *vm); NJS_EXPORT void njs_disassemble(u_char *start, u_char *end); @@ -316,4 +322,8 @@ NJS_EXPORT njs_int_t njs_vm_json_parse(n NJS_EXPORT njs_int_t njs_vm_json_stringify(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs); +NJS_EXPORT njs_int_t njs_vm_promise_create(njs_vm_t *vm, njs_value_t *retval, + njs_value_t *callbacks); + + #endif /* _NJS_H_INCLUDED_ */ diff -r cb4f1052954f -r 6fccbc9f1288 src/njs_function.c --- a/src/njs_function.c Thu Jan 16 15:14:38 2020 +0300 +++ b/src/njs_function.c Thu Jan 16 19:18:39 2020 +0300 @@ -74,6 +74,24 @@ fail: njs_function_t * +njs_vm_function_alloc(njs_vm_t *vm, njs_function_native_t native) +{ + njs_function_t *function; + + function = njs_mp_zalloc(vm->mem_pool, sizeof(njs_function_t)); + if (njs_slow_path(function == NULL)) { + return NULL; + } + + function->native = 1; + function->args_offset = 1; + function->u.native = native; + + return function; +} + + +njs_function_t * njs_function_value_copy(njs_vm_t *vm, njs_value_t *value) { njs_function_t *function, *copy; diff -r cb4f1052954f -r 6fccbc9f1288 src/njs_promise.c --- a/src/njs_promise.c Thu Jan 16 15:14:38 2020 +0300 +++ b/src/njs_promise.c Thu Jan 16 19:18:39 2020 +0300 @@ -140,6 +140,28 @@ njs_promise_constructor(njs_vm_t *vm, nj } +njs_int_t +njs_vm_promise_create(njs_vm_t *vm, njs_value_t *retval, njs_value_t *callbacks) +{ + njs_int_t ret; + njs_promise_t *promise; + + promise = njs_promise_alloc(vm); + if (njs_slow_path(promise == NULL)) { + return NJS_ERROR; + } + + ret = njs_promise_create_resolving_functions(vm, promise, callbacks); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + njs_set_promise(retval, promise); + + return NJS_OK; +} + + static njs_promise_t * njs_promise_constructor_call(njs_vm_t *vm, njs_function_t *function) { diff -r cb4f1052954f -r 6fccbc9f1288 src/njs_value.h --- a/src/njs_value.h Thu Jan 16 15:14:38 2020 +0300 +++ b/src/njs_value.h Thu Jan 16 19:18:39 2020 +0300 @@ -108,8 +108,6 @@ typedef struct njs_object_init_s nj */ typedef njs_int_t (*njs_prop_handler_t) (njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, njs_value_t *retval); -typedef njs_int_t (*njs_function_native_t) (njs_vm_t *vm, njs_value_t *args, - njs_uint_t nargs, njs_index_t retval); #if (!NJS_HAVE_GCC_ATTRIBUTE_ALIGNED) #error "aligned attribute is required" From xeioex at nginx.com Thu Jan 16 16:35:04 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 16 Jan 2020 16:35:04 +0000 Subject: [njs] Fixed memory-leak introduced in b840b7af946e. Message-ID: details: https://hg.nginx.org/njs/rev/22e3b0285ad6 branches: changeset: 1302:22e3b0285ad6 user: Dmitry Volyntsev date: Thu Jan 16 19:18:41 2020 +0300 description: Fixed memory-leak introduced in b840b7af946e. diffstat: src/njs_json.c | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-) diffs (26 lines): diff -r 6fccbc9f1288 -r 22e3b0285ad6 src/njs_json.c --- a/src/njs_json.c Thu Jan 16 19:18:39 2020 +0300 +++ b/src/njs_json.c Thu Jan 16 19:18:41 2020 +0300 @@ -2011,6 +2011,9 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_ goto memory_error; } + visited.separate = 0; + visited.pointer = 0; + goto done; } @@ -2226,10 +2229,10 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_ } } +done: + njs_arr_destroy(&visited); -done: - ret = njs_chb_join(&chain, &str); if (njs_slow_path(ret != NJS_OK)) { goto memory_error; From xeioex at nginx.com Thu Jan 16 16:35:05 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 16 Jan 2020 16:35:05 +0000 Subject: [njs] Fixed format specifier in typed-array constructor. Message-ID: details: https://hg.nginx.org/njs/rev/6017c94f59b2 branches: changeset: 1303:6017c94f59b2 user: Dmitry Volyntsev date: Thu Jan 16 19:18:41 2020 +0300 description: Fixed format specifier in typed-array constructor. diffstat: src/njs_typed_array.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 22e3b0285ad6 -r 6017c94f59b2 src/njs_typed_array.c --- a/src/njs_typed_array.c Thu Jan 16 19:18:41 2020 +0300 +++ b/src/njs_typed_array.c Thu Jan 16 19:18:41 2020 +0300 @@ -63,7 +63,7 @@ njs_typed_array_constructor(njs_vm_t *vm size *= element_size; if (njs_slow_path((offset + size) > buffer->size)) { - njs_range_error(vm, "Invalid typed array length: %uD", size); + njs_range_error(vm, "Invalid typed array length: %uL", size); return NJS_ERROR; } From mdounin at mdounin.ru Thu Jan 16 18:09:45 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 16 Jan 2020 21:09:45 +0300 Subject: [PATCH] Add "compliant" option to ssl_verify_client for CORS support In-Reply-To: References: <4ba211814386f2e4adcd.1579121494@samps-dus> <20200116120858.GL12894@mdounin.ru> Message-ID: <20200116180945.GN12894@mdounin.ru> Hello! On Thu, Jan 16, 2020 at 08:18:10AM -0700, Sampson Crowley wrote: > 1) The consumer shouldn't need a whole series of checks just to actually do > things correctly and be *compliant* with the http specs You assume that CORS is a part of HTTP specification. It's not. Neither it's a part of SSL / TLS specification, which is a separate one. Further, all current variants of ssl_verify_client are HTTP-complaint, as well as SSL/TLS-complaint. Further, I suspect that these are also CORS-complaint (though I never checked the exact wording of the CORS specification), even if some of them may prevent CORS preflight requests from working. > 2) I don't see how "compliant" is misleading to be "compliant" with how > things are SUPPOSED to work in the first place Sure. And things already complaint. The question is how exactly things work, and what exactly happens in a given situation. Introducing a separate "complaint" variant suggests that other variants aren't complaint, which is not true. Further, it doesn't define to what exactly things are expected to be complaint. -- Maxim Dounin http://mdounin.ru/ From sampson at downundersports.com Thu Jan 16 19:24:54 2020 From: sampson at downundersports.com (Sampson Crowley) Date: Thu, 16 Jan 2020 12:24:54 -0700 Subject: [PATCH] Add "compliant" option to ssl_verify_client for CORS support In-Reply-To: <20200116180945.GN12894@mdounin.ru> References: <4ba211814386f2e4adcd.1579121494@samps-dus> <20200116120858.GL12894@mdounin.ru> <20200116180945.GN12894@mdounin.ru> Message-ID: the fact is that CORS is part of the whatwg spec, endpoint consumers don't differentiate what section of the spec it's a part of, and requiring credentials on a preflight request is against the spec, so no, it's not compliant. https://bugzilla.mozilla.org/show_bug.cgi?id=1019603#c9 On Thu, Jan 16, 2020 at 11:09 AM Maxim Dounin wrote: > Hello! > > On Thu, Jan 16, 2020 at 08:18:10AM -0700, Sampson Crowley wrote: > > > 1) The consumer shouldn't need a whole series of checks just to actually > do > > things correctly and be *compliant* with the http specs > > You assume that CORS is a part of HTTP specification. It's not. > Neither it's a part of SSL / TLS specification, which is a > separate one. Further, all current variants of ssl_verify_client > are HTTP-complaint, as well as SSL/TLS-complaint. Further, I > suspect that these are also CORS-complaint (though I never checked > the exact wording of the CORS specification), even if some of them > may prevent CORS preflight requests from working. > > > 2) I don't see how "compliant" is misleading to be "compliant" with how > > things are SUPPOSED to work in the first place > > Sure. And things already complaint. The question is how exactly > things work, and what exactly happens in a given situation. > Introducing a separate "complaint" variant suggests that other > variants aren't complaint, which is not true. Further, it doesn't > define to what exactly things are expected to be complaint. > > -- > Maxim Dounin > http://mdounin.ru/ > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -------------- next part -------------- An HTML attachment was scrubbed... URL: From sampson at downundersports.com Thu Jan 16 19:42:38 2020 From: sampson at downundersports.com (Sampson Crowley) Date: Thu, 16 Jan 2020 12:42:38 -0700 Subject: [PATCH] Add "compliant" option to ssl_verify_client for CORS support In-Reply-To: References: <4ba211814386f2e4adcd.1579121494@samps-dus> <20200116120858.GL12894@mdounin.ru> <20200116180945.GN12894@mdounin.ru> Message-ID: Maxim the work around you provided is invalid, ssl_verify_client optional; set $allow 0; if ($ssl_client_verify = OK) { set $allow 1; } if ($method = OPTIONS) { set $allow 1; } if (!$allow) { return 496; } returns 'invalid condition "!$allow" by nginx and the service fails to start On Thu, Jan 16, 2020 at 12:24 PM Sampson Crowley < sampson at downundersports.com> wrote: > the fact is that CORS is part of the whatwg spec, endpoint consumers don't > differentiate what section of the spec it's a part of, and requiring > credentials on a preflight request is against the spec, so no, it's not > compliant. https://bugzilla.mozilla.org/show_bug.cgi?id=1019603#c9 > > On Thu, Jan 16, 2020 at 11:09 AM Maxim Dounin wrote: > >> Hello! >> >> On Thu, Jan 16, 2020 at 08:18:10AM -0700, Sampson Crowley wrote: >> >> > 1) The consumer shouldn't need a whole series of checks just to >> actually do >> > things correctly and be *compliant* with the http specs >> >> You assume that CORS is a part of HTTP specification. It's not. >> Neither it's a part of SSL / TLS specification, which is a >> separate one. Further, all current variants of ssl_verify_client >> are HTTP-complaint, as well as SSL/TLS-complaint. Further, I >> suspect that these are also CORS-complaint (though I never checked >> the exact wording of the CORS specification), even if some of them >> may prevent CORS preflight requests from working. >> >> > 2) I don't see how "compliant" is misleading to be "compliant" with how >> > things are SUPPOSED to work in the first place >> >> Sure. And things already complaint. The question is how exactly >> things work, and what exactly happens in a given situation. >> Introducing a separate "complaint" variant suggests that other >> variants aren't complaint, which is not true. Further, it doesn't >> define to what exactly things are expected to be complaint. >> >> -- >> Maxim Dounin >> http://mdounin.ru/ >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From joe.konno at linux.intel.com Thu Jan 16 20:44:00 2020 From: joe.konno at linux.intel.com (Joe Konno) Date: Thu, 16 Jan 2020 12:44:00 -0800 Subject: [PATCH nginx v2] remove ngx_cpuinfo, use sysconf or define In-Reply-To: <20200116154645.GA2631367@vlpc> References: <20200116144309.GA2627064@vlpc> <17c636cf-035c-9deb-d2ee-97ad6142f051@linux.intel.com> <20200116154645.GA2631367@vlpc> Message-ID: Scroll to bottom (removing the v2-specific patch text and review as it's not relevant to my v1 commentary): On 1/16/20 7:46 AM, Vladimir Homutov wrote: [snip] > On Thu, Jan 16, 2020 at 07:39:07AM -0800, Joe Konno wrote: [snip] >> v1 of that patch used CPUID to retrieve the cache line size directly >> from H/W: >> >> http://mailman.nginx.org/pipermail/nginx-devel/2019-December/012853.html > > yes, I've seen this too. Thanks for the review! > Although our current ngx_cpuinfo() may seem a bit outdated, it does its > job, and contains some manually crafted cases. What we don't want is to > make things more complex here and introduce more very specific code. Fair enough. At the end of the day, nginx maintainers have to do what they feel is best for nginx. Generally speaking, for any code base that wishes to optimize for, e.g., cache line size, the standing recommendation is to query the x86 hardware directly by using the appropriate CPUID leaves. Regardless of what happens to the patch(es), I wanted to spotlight CPUID and how it could help nginx-- this is just one case. > If you know about specific cases when things get wrong with current > implementation, please report. Succinctly, no, I haven't seen things go wrong. I haven't done extensive testing, though. Assuming the implementations of cache line-sensitive algorithms are correct (e.g. CRC), the case where nginx's code sets the wrong cache line size would probably yield sub-optimal performance on x86 hardware. Further analysis would be needed to determine the exact cost of an incorrect cache line size on x86, given these implementations and how-often/when/where they are used. From mdounin at mdounin.ru Fri Jan 17 11:53:09 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 17 Jan 2020 14:53:09 +0300 Subject: [PATCH] Add "compliant" option to ssl_verify_client for CORS support In-Reply-To: References: <4ba211814386f2e4adcd.1579121494@samps-dus> <20200116120858.GL12894@mdounin.ru> <20200116180945.GN12894@mdounin.ru> Message-ID: <20200117115309.GQ12894@mdounin.ru> Hello! On Thu, Jan 16, 2020 at 12:42:38PM -0700, Sampson Crowley wrote: > Maxim the work around you provided is invalid, > > ssl_verify_client optional; > > set $allow 0; > > if ($ssl_client_verify = OK) { > set $allow 1; > } > > if ($method = OPTIONS) { > set $allow 1; > } > > if (!$allow) { > return 496; > } > > returns 'invalid condition "!$allow" by nginx and the service fails to start Sure, my bad. It should be "$allow != 1". And "$method" should be "$request_method" instead. -- Maxim Dounin http://mdounin.ru/ From mdounin at mdounin.ru Fri Jan 17 11:58:53 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 17 Jan 2020 14:58:53 +0300 Subject: [PATCH] Add "compliant" option to ssl_verify_client for CORS support In-Reply-To: References: <4ba211814386f2e4adcd.1579121494@samps-dus> <20200116120858.GL12894@mdounin.ru> <20200116180945.GN12894@mdounin.ru> Message-ID: <20200117115853.GR12894@mdounin.ru> Hello! On Thu, Jan 16, 2020 at 12:24:54PM -0700, Sampson Crowley wrote: > the fact is that CORS is part of the whatwg spec, endpoint consumers don't > differentiate what section of the spec it's a part of, and requiring > credentials on a preflight request is against the spec, so no, it's not > compliant. https://bugzilla.mozilla.org/show_bug.cgi?id=1019603#c9 There is more than one spec in the world, and being complaint to one of them can easily mean being non-complaint to another one. The word "complaint" means nothing unless it specifies complaint to what. And no, requiring credentials on all requests doesn't mean that nginx with "ssl_verify_client on;" isn't complaint with the CORS spec. This behaviour might be perfectly complaint, for example, if no preflight requests are expected on the server. Anyway, thank you for the patch. It was considered and it won't be committed. If you want to allow preflight requests while using SSL certificate verification, consider using "ssl_verify_client optional;" with appropriate checks during request processing. -- Maxim Dounin http://mdounin.ru/ From xeioex at nginx.com Fri Jan 17 12:19:44 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 17 Jan 2020 12:19:44 +0000 Subject: [njs] Fixed use-of-uninitialized-value for the global this object. Message-ID: details: https://hg.nginx.org/njs/rev/ef8c8f65ac0e branches: changeset: 1304:ef8c8f65ac0e user: Dmitry Volyntsev date: Thu Jan 16 21:29:43 2020 +0300 description: Fixed use-of-uninitialized-value for the global this object. Found by MemorySanitizer. diffstat: src/njs_builtin.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diffs (12 lines): diff -r 6017c94f59b2 -r ef8c8f65ac0e src/njs_builtin.c --- a/src/njs_builtin.c Thu Jan 16 19:18:41 2020 +0300 +++ b/src/njs_builtin.c Thu Jan 16 21:29:43 2020 +0300 @@ -373,6 +373,8 @@ njs_builtin_objects_clone(njs_vm_t *vm, } vm->global_object.__proto__ = object_prototype; + + njs_set_undefined(global); njs_set_object(global, &vm->global_object); vm->string_object = vm->shared->string_object; From xeioex at nginx.com Fri Jan 17 12:19:46 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 17 Jan 2020 12:19:46 +0000 Subject: [njs] Introduced njs_fs_path_arg(). Message-ID: details: https://hg.nginx.org/njs/rev/c735708203e8 branches: changeset: 1305:c735708203e8 user: Artem S. Povalyukhin date: Fri Jan 17 10:04:28 2020 +0300 description: Introduced njs_fs_path_arg(). diffstat: src/njs_fs.c | 123 ++++++++++++++++----------------------- src/test/njs_interactive_test.c | 2 +- src/test/njs_unit_test.c | 54 +++++++++++++--- 3 files changed, 96 insertions(+), 83 deletions(-) diffs (338 lines): diff -r ef8c8f65ac0e -r c735708203e8 src/njs_fs.c --- a/src/njs_fs.c Thu Jan 16 21:29:43 2020 +0300 +++ b/src/njs_fs.c Fri Jan 17 10:04:28 2020 +0300 @@ -69,6 +69,24 @@ static njs_fs_entry_t njs_flags_table[] }; +njs_inline njs_int_t +njs_fs_path_arg(njs_vm_t *vm, const char **dst, + const njs_value_t* src, const njs_str_t *prop_name) +{ + if (njs_slow_path(!njs_is_string(src))) { + njs_type_error(vm, "\"%V\" must be a string", prop_name); + return NJS_ERROR; + } + + *dst = njs_string_to_c_string(vm, njs_value_arg(src)); + if (njs_slow_path(*dst == NULL)) { + return NJS_ERROR; + } + + return NJS_OK; +} + + static njs_int_t njs_fs_read_file(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) @@ -85,16 +103,17 @@ njs_fs_read_file(njs_vm_t *vm, njs_value njs_object_prop_t *prop; njs_lvlhsh_query_t lhq; + ret = njs_fs_path_arg(vm, &path, njs_arg(args, nargs, 1), + &njs_str_value("path")); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + if (njs_slow_path(nargs < 3)) { njs_type_error(vm, "too few arguments"); return NJS_ERROR; } - if (njs_slow_path(!njs_is_string(&args[1]))) { - njs_type_error(vm, "path must be a string"); - return NJS_ERROR; - } - flag.start = NULL; encoding.length = 0; encoding.start = NULL; @@ -156,11 +175,6 @@ njs_fs_read_file(njs_vm_t *vm, njs_value return NJS_ERROR; } - path = njs_string_to_c_string(vm, &args[1]); - if (njs_slow_path(path == NULL)) { - return NJS_ERROR; - } - if (encoding.length != 0 && (encoding.length != 4 || memcmp(encoding.start, "utf8", 4) != 0)) { @@ -320,16 +334,17 @@ njs_fs_read_file_sync(njs_vm_t *vm, njs_ njs_object_prop_t *prop; njs_lvlhsh_query_t lhq; + ret = njs_fs_path_arg(vm, &path, njs_arg(args, nargs, 1), + &njs_str_value("path")); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + if (njs_slow_path(nargs < 2)) { njs_type_error(vm, "too few arguments"); return NJS_ERROR; } - if (njs_slow_path(!njs_is_string(&args[1]))) { - njs_type_error(vm, "path must be a string"); - return NJS_ERROR; - } - flag.start = NULL; encoding.length = 0; encoding.start = NULL; @@ -557,16 +572,17 @@ static njs_int_t njs_fs_write_file_inter njs_object_prop_t *prop; njs_lvlhsh_query_t lhq; + ret = njs_fs_path_arg(vm, &path, njs_arg(args, nargs, 1), + &njs_str_value("path")); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + if (njs_slow_path(nargs < 4)) { njs_type_error(vm, "too few arguments"); return NJS_ERROR; } - if (njs_slow_path(!njs_is_string(&args[1]))) { - njs_type_error(vm, "path must be a string"); - return NJS_ERROR; - } - if (njs_slow_path(!njs_is_string(&args[2]))) { njs_type_error(vm, "data must be a string"); return NJS_ERROR; @@ -654,11 +670,6 @@ static njs_int_t njs_fs_write_file_inter md = 0666; } - path = njs_string_to_c_string(vm, &args[1]); - if (njs_slow_path(path == NULL)) { - return NJS_ERROR; - } - if (encoding.length != 0 && (encoding.length != 4 || memcmp(encoding.start, "utf8", 4) != 0)) { @@ -745,16 +756,17 @@ njs_fs_write_file_sync_internal(njs_vm_t njs_object_prop_t *prop; njs_lvlhsh_query_t lhq; + ret = njs_fs_path_arg(vm, &path, njs_arg(args, nargs, 1), + &njs_str_value("path")); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + if (njs_slow_path(nargs < 3)) { njs_type_error(vm, "too few arguments"); return NJS_ERROR; } - if (njs_slow_path(!njs_is_string(&args[1]))) { - njs_type_error(vm, "path must be a string"); - return NJS_ERROR; - } - if (njs_slow_path(!njs_is_string(&args[2]))) { njs_type_error(vm, "data must be a string"); return NJS_ERROR; @@ -827,11 +839,6 @@ njs_fs_write_file_sync_internal(njs_vm_t md = 0666; } - path = njs_string_to_c_string(vm, &args[1]); - if (njs_slow_path(path == NULL)) { - return NJS_ERROR; - } - if (encoding.length != 0 && (encoding.length != 4 || memcmp(encoding.start, "utf8", 4) != 0)) { @@ -896,45 +903,19 @@ static njs_int_t njs_fs_rename_sync(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - int ret; - const char *old_path, *new_path; - njs_value_t *old, *new; + njs_int_t ret; + const char *old_path, *new_path; - if (njs_slow_path(nargs < 3)) { - if (nargs < 2) { - njs_type_error(vm, "oldPath must be a string"); - return NJS_ERROR; - } - - njs_type_error(vm, "newPath must be a string"); - return NJS_ERROR; + ret = njs_fs_path_arg(vm, &old_path, njs_arg(args, nargs, 1), + &njs_str_value("oldPath")); + if (njs_slow_path(ret != NJS_OK)) { + return ret; } - old = njs_argument(args, 1); - new = njs_argument(args, 2); - - if (njs_slow_path(!njs_is_string(old))) { - ret = njs_value_to_string(vm, old, old); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - } - - if (njs_slow_path(!njs_is_string(new))) { - ret = njs_value_to_string(vm, new, new); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - } - - old_path = njs_string_to_c_string(vm, old); - if (njs_slow_path(old_path == NULL)) { - return NJS_ERROR; - } - - new_path = njs_string_to_c_string(vm, new); - if (njs_slow_path(new_path == NULL)) { - return NJS_ERROR; + ret = njs_fs_path_arg(vm, &new_path, njs_arg(args, nargs, 2), + &njs_str_value("newPath")); + if (njs_slow_path(ret != NJS_OK)) { + return ret; } ret = rename(old_path, new_path); diff -r ef8c8f65ac0e -r c735708203e8 src/test/njs_interactive_test.c --- a/src/test/njs_interactive_test.c Thu Jan 16 21:29:43 2020 +0300 +++ b/src/test/njs_interactive_test.c Fri Jan 17 10:04:28 2020 +0300 @@ -233,7 +233,7 @@ static njs_interactive_test_t njs_test[ " at main (native)\n") }, { njs_str("var fs = require('fs'); fs.readFile()" ENTER), - njs_str("TypeError: too few arguments\n" + njs_str("TypeError: \"path\" must be a string\n" " at fs.readFile (native)\n" " at main (native)\n") }, diff -r ef8c8f65ac0e -r c735708203e8 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Thu Jan 16 21:29:43 2020 +0300 +++ b/src/test/njs_unit_test.c Fri Jan 17 10:04:28 2020 +0300 @@ -15520,7 +15520,7 @@ static njs_unit_test_t njs_test[] = { njs_str("var fs = require('fs');" "fs.readFile()"), - njs_str("TypeError: too few arguments") }, + njs_str("TypeError: \"path\" must be a string") }, { njs_str("var fs = require('fs');" "fs.readFile('/njs_unknown_path')"), @@ -15550,11 +15550,11 @@ static njs_unit_test_t njs_test[] = { njs_str("var fs = require('fs');" "fs.readFileSync()"), - njs_str("TypeError: too few arguments") }, + njs_str("TypeError: \"path\" must be a string") }, { njs_str("var fs = require('fs');" "fs.readFileSync({})"), - njs_str("TypeError: path must be a string") }, + njs_str("TypeError: \"path\" must be a string") }, { njs_str("var fs = require('fs');" "fs.readFileSync('/njs_unknown_path', {flag:'xx'})"), @@ -15577,7 +15577,7 @@ static njs_unit_test_t njs_test[] = { njs_str("var fs = require('fs');" "fs.writeFile()"), - njs_str("TypeError: too few arguments") }, + njs_str("TypeError: \"path\" must be a string") }, { njs_str("var fs = require('fs');" "fs.writeFile('/njs_unknown_path')"), @@ -15589,7 +15589,7 @@ static njs_unit_test_t njs_test[] = { njs_str("var fs = require('fs');" "fs.writeFile({}, '', function () {})"), - njs_str("TypeError: path must be a string") }, + njs_str("TypeError: \"path\" must be a string") }, { njs_str("var fs = require('fs');" "fs.writeFile('/njs_unknown_path', '', 'utf8')"), @@ -15615,7 +15615,7 @@ static njs_unit_test_t njs_test[] = { njs_str("var fs = require('fs');" "fs.writeFileSync()"), - njs_str("TypeError: too few arguments") }, + njs_str("TypeError: \"path\" must be a string") }, { njs_str("var fs = require('fs');" "fs.writeFileSync('/njs_unknown_path')"), @@ -15623,7 +15623,7 @@ static njs_unit_test_t njs_test[] = { njs_str("var fs = require('fs');" "fs.writeFileSync({}, '')"), - njs_str("TypeError: path must be a string") }, + njs_str("TypeError: \"path\" must be a string") }, { njs_str("var fs = require('fs');" "fs.writeFileSync('/njs_unknown_path', '', {flag:'xx'})"), @@ -15641,15 +15641,47 @@ static njs_unit_test_t njs_test[] = "fs.writeFileSync('/njs_unknown_path', '', true)"), njs_str("TypeError: Unknown options type (a string or object required)") }, - /* require('fs').writeFileSync() */ + /* require('fs').renameSync() */ { njs_str("var fs = require('fs');" "fs.renameSync()"), - njs_str("TypeError: oldPath must be a string") }, + njs_str("TypeError: \"oldPath\" must be a string") }, + + { njs_str("var fs = require('fs');" + "fs.renameSync('/njs_unknown_path')"), + njs_str("TypeError: \"newPath\" must be a string") }, + + { njs_str("var fs = require('fs');" + "[undefined, null, false, NaN, Symbol(), {}, Object('/njs_unknown_path')]" + ".map((x) => { try { fs.renameSync(x, '/njs_unknown_path'); } " + " catch (e) { return (e instanceof TypeError); } })" + ".every((x) => x === true)"), + njs_str("true")}, { njs_str("var fs = require('fs');" - "fs.renameSync({toString(){return '/path/1'}})"), - njs_str("TypeError: newPath must be a string") }, + "[undefined, null, false, NaN, Symbol(), {}, Object('/njs_unknown_path')]" + ".map((x) => { try { fs.renameSync('/njs_unknown_path', x); } " + " catch (e) { return (e instanceof TypeError); } })" + ".every((x) => x === true)"), + njs_str("true")}, + + { njs_str("var " + "fs = require('fs')," + "func = [" + "'readFile'," + "'readFileSync'," + "'writeFile'," + "'writeFileSync'," + "'appendFile'," + "'appendFileSync'," + "]," + "test = (fname) =>" + "[undefined, null, false, NaN, Symbol(), {}, Object('/njs_unknown_path')]" + ".map((x) => { try { fs[fname](x); } " + " catch (e) { return (e instanceof TypeError); } })" + ".every((x) => x === true);" + "func.map(test).every((x) => x)"), + njs_str("true")}, /* require('crypto').createHash() */ From vl at nginx.com Fri Jan 17 12:39:02 2020 From: vl at nginx.com (Vladimir Homutov) Date: Fri, 17 Jan 2020 12:39:02 +0000 Subject: [nginx] gRPC: variables support in the "grpc_pass" directive. Message-ID: details: https://hg.nginx.org/nginx/rev/6439ef81e37d branches: changeset: 7619:6439ef81e37d user: Vladimir Homutov date: Fri Jan 17 12:13:02 2020 +0300 description: gRPC: variables support in the "grpc_pass" directive. diffstat: src/http/modules/ngx_http_grpc_module.c | 234 ++++++++++++++++++++++++++----- 1 files changed, 193 insertions(+), 41 deletions(-) diffs (358 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 @@ -27,6 +27,9 @@ typedef struct { ngx_str_t host; ngx_uint_t host_set; + ngx_array_t *grpc_lengths; + ngx_array_t *grpc_values; + #if (NGX_HTTP_SSL) ngx_uint_t ssl; ngx_uint_t ssl_protocols; @@ -119,6 +122,8 @@ typedef struct { unsigned status:1; ngx_http_request_t *request; + + ngx_str_t host; } ngx_http_grpc_ctx_t; @@ -135,6 +140,8 @@ typedef struct { } ngx_http_grpc_frame_t; +static ngx_int_t ngx_http_grpc_eval(ngx_http_request_t *r, + ngx_http_grpc_ctx_t *ctx, ngx_http_grpc_loc_conf_t *glcf); static ngx_int_t ngx_http_grpc_create_request(ngx_http_request_t *r); static ngx_int_t ngx_http_grpc_reinit_request(ngx_http_request_t *r); static ngx_int_t ngx_http_grpc_body_output_filter(void *data, ngx_chain_t *in); @@ -524,22 +531,40 @@ ngx_http_grpc_handler(ngx_http_request_t return NGX_HTTP_INTERNAL_SERVER_ERROR; } + ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_grpc_ctx_t)); + if (ctx == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + ctx->request = r; + + ngx_http_set_ctx(r, ctx, ngx_http_grpc_module); + glcf = ngx_http_get_module_loc_conf(r, ngx_http_grpc_module); u = r->upstream; + if (glcf->grpc_lengths == NULL) { + ctx->host = glcf->host; + #if (NGX_HTTP_SSL) - u->ssl = (glcf->upstream.ssl != NULL); - - if (u->ssl) { - ngx_str_set(&u->schema, "grpcs://"); + u->ssl = (glcf->upstream.ssl != NULL); + + if (u->ssl) { + ngx_str_set(&u->schema, "grpcs://"); + + } else { + ngx_str_set(&u->schema, "grpc://"); + } +#else + ngx_str_set(&u->schema, "grpc://"); +#endif } else { - ngx_str_set(&u->schema, "grpc://"); + if (ngx_http_grpc_eval(r, ctx, glcf) != NGX_OK) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } } -#else - ngx_str_set(&u->schema, "grpc://"); -#endif u->output.tag = (ngx_buf_tag_t) &ngx_http_grpc_module; @@ -551,15 +576,6 @@ ngx_http_grpc_handler(ngx_http_request_t u->abort_request = ngx_http_grpc_abort_request; u->finalize_request = ngx_http_grpc_finalize_request; - ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_grpc_ctx_t)); - if (ctx == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - ctx->request = r; - - ngx_http_set_ctx(r, ctx, ngx_http_grpc_module); - u->input_filter_init = ngx_http_grpc_filter_init; u->input_filter = ngx_http_grpc_filter; u->input_filter_ctx = ctx; @@ -577,6 +593,103 @@ ngx_http_grpc_handler(ngx_http_request_t static ngx_int_t +ngx_http_grpc_eval(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx, + ngx_http_grpc_loc_conf_t *glcf) +{ + size_t add; + ngx_url_t url; + ngx_http_upstream_t *u; + + ngx_memzero(&url, sizeof(ngx_url_t)); + + if (ngx_http_script_run(r, &url.url, glcf->grpc_lengths->elts, 0, + glcf->grpc_values->elts) + == NULL) + { + return NGX_ERROR; + } + + if (url.url.len > 7 + && ngx_strncasecmp(url.url.data, (u_char *) "grpc://", 7) == 0) + { + add = 7; + + } else if (url.url.len > 8 + && ngx_strncasecmp(url.url.data, (u_char *) "grpcs://", 8) == 0) + { + +#if (NGX_HTTP_SSL) + add = 8; + r->upstream->ssl = 1; +#else + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "grpcs protocol requires SSL support"); + return NGX_ERROR; +#endif + + } else { + add = 0; + } + + u = r->upstream; + + if (add) { + u->schema.len = add; + u->schema.data = url.url.data; + + url.url.data += add; + url.url.len -= add; + + } else { + ngx_str_set(&u->schema, "grpc://"); + } + + url.no_resolve = 1; + + if (ngx_parse_url(r->pool, &url) != NGX_OK) { + if (url.err) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "%s in upstream \"%V\"", url.err, &url.url); + } + + return NGX_ERROR; + } + + u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t)); + if (u->resolved == NULL) { + return NGX_ERROR; + } + + if (url.addrs) { + u->resolved->sockaddr = url.addrs[0].sockaddr; + u->resolved->socklen = url.addrs[0].socklen; + u->resolved->name = url.addrs[0].name; + u->resolved->naddrs = 1; + } + + u->resolved->host = url.host; + u->resolved->port = url.port; + u->resolved->no_port = url.no_port; + + if (url.family != AF_UNIX) { + + if (url.no_port) { + ctx->host = url.host; + + } else { + ctx->host.len = url.host.len + 1 + url.port_text.len; + ctx->host.data = url.host.data; + } + + } else { + ngx_str_set(&ctx->host, "localhost"); + } + + return NGX_OK; +} + + +static ngx_int_t ngx_http_grpc_create_request(ngx_http_request_t *r) { u_char *p, *tmp, *key_tmp, *val_tmp, *headers_frame; @@ -587,6 +700,7 @@ ngx_http_grpc_create_request(ngx_http_re ngx_chain_t *cl, *body; ngx_list_part_t *part; ngx_table_elt_t *header; + ngx_http_grpc_ctx_t *ctx; ngx_http_upstream_t *u; ngx_http_grpc_frame_t *f; ngx_http_script_code_pt code; @@ -598,6 +712,8 @@ ngx_http_grpc_create_request(ngx_http_re glcf = ngx_http_get_module_loc_conf(r, ngx_http_grpc_module); + ctx = ngx_http_get_module_ctx(r, ngx_http_grpc_module); + len = sizeof(ngx_http_grpc_connection_start) - 1 + sizeof(ngx_http_grpc_frame_t); /* headers frame */ @@ -637,10 +753,10 @@ ngx_http_grpc_create_request(ngx_http_re /* :authority header */ if (!glcf->host_set) { - len += 1 + NGX_HTTP_V2_INT_OCTETS + glcf->host.len; - - if (tmp_len < glcf->host.len) { - tmp_len = glcf->host.len; + len += 1 + NGX_HTTP_V2_INT_OCTETS + ctx->host.len; + + if (tmp_len < ctx->host.len) { + tmp_len = ctx->host.len; } } @@ -785,7 +901,7 @@ ngx_http_grpc_create_request(ngx_http_re } #if (NGX_HTTP_SSL) - if (glcf->ssl) { + if (u->ssl) { *b->last++ = ngx_http_v2_indexed(NGX_HTTP_V2_SCHEME_HTTPS_INDEX); ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, @@ -846,11 +962,11 @@ ngx_http_grpc_create_request(ngx_http_re if (!glcf->host_set) { *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_AUTHORITY_INDEX); - b->last = ngx_http_v2_write_value(b->last, glcf->host.data, - glcf->host.len, tmp); + b->last = ngx_http_v2_write_value(b->last, ctx->host.data, + ctx->host.len, tmp); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "grpc header: \":authority: %V\"", &glcf->host); + "grpc header: \":authority: %V\"", &ctx->host); } ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); @@ -4319,15 +4435,23 @@ ngx_http_grpc_merge_loc_conf(ngx_conf_t clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - if (clcf->noname && conf->upstream.upstream == NULL) { + if (clcf->noname + && conf->upstream.upstream == NULL && conf->grpc_lengths == NULL) + { conf->upstream.upstream = prev->upstream.upstream; conf->host = prev->host; + + conf->grpc_lengths = prev->grpc_lengths; + conf->grpc_values = prev->grpc_values; + #if (NGX_HTTP_SSL) conf->upstream.ssl = prev->upstream.ssl; #endif } - if (clcf->lmt_excpt && clcf->handler == NULL && conf->upstream.upstream) { + if (clcf->lmt_excpt && clcf->handler == NULL + && (conf->upstream.upstream || conf->grpc_lengths)) + { clcf->handler = ngx_http_grpc_handler; } @@ -4537,18 +4661,54 @@ ngx_http_grpc_pass(ngx_conf_t *cf, ngx_c { ngx_http_grpc_loc_conf_t *glcf = conf; - size_t add; - ngx_str_t *value, *url; - ngx_url_t u; - ngx_http_core_loc_conf_t *clcf; - - if (glcf->upstream.upstream) { + size_t add; + ngx_str_t *value, *url; + ngx_url_t u; + ngx_uint_t n; + ngx_http_core_loc_conf_t *clcf; + ngx_http_script_compile_t sc; + + if (glcf->upstream.upstream || glcf->grpc_lengths) { return "is duplicate"; } + clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); + + clcf->handler = ngx_http_grpc_handler; + + if (clcf->name.len && clcf->name.data[clcf->name.len - 1] == '/') { + clcf->auto_redirect = 1; + } + value = cf->args->elts; + url = &value[1]; + n = ngx_http_script_variables_count(url); + + if (n) { + + ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); + + sc.cf = cf; + sc.source = url; + sc.lengths = &glcf->grpc_lengths; + sc.values = &glcf->grpc_values; + sc.variables = n; + sc.complete_lengths = 1; + sc.complete_values = 1; + + if (ngx_http_script_compile(&sc) != NGX_OK) { + return NGX_CONF_ERROR; + } + +#if (NGX_HTTP_SSL) + glcf->ssl = 1; +#endif + + return NGX_CONF_OK; + } + if (ngx_strncasecmp(url->data, (u_char *) "grpc://", 7) == 0) { add = 7; @@ -4593,14 +4753,6 @@ ngx_http_grpc_pass(ngx_conf_t *cf, ngx_c ngx_str_set(&glcf->host, "localhost"); } - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - - clcf->handler = ngx_http_grpc_handler; - - if (clcf->name.len && clcf->name.data[clcf->name.len - 1] == '/') { - clcf->auto_redirect = 1; - } - return NGX_CONF_OK; } From sampson at downundersports.com Fri Jan 17 16:52:59 2020 From: sampson at downundersports.com (Sampson Crowley) Date: Fri, 17 Jan 2020 09:52:59 -0700 Subject: [PATCH] Add "compliant" option to ssl_verify_client for CORS support In-Reply-To: <20200117115309.GQ12894@mdounin.ru> References: <4ba211814386f2e4adcd.1579121494@samps-dus> <20200116120858.GL12894@mdounin.ru> <20200116180945.GN12894@mdounin.ru> <20200117115309.GQ12894@mdounin.ru> Message-ID: That fails the request even with a valid certificate On Fri, Jan 17, 2020, 04:53 Maxim Dounin wrote: > Hello! > > On Thu, Jan 16, 2020 at 12:42:38PM -0700, Sampson Crowley wrote: > > > Maxim the work around you provided is invalid, > > > > ssl_verify_client optional; > > > > set $allow 0; > > > > if ($ssl_client_verify = OK) { > > set $allow 1; > > } > > > > if ($method = OPTIONS) { > > set $allow 1; > > } > > > > if (!$allow) { > > return 496; > > } > > > > returns 'invalid condition "!$allow" by nginx and the service fails to > start > > Sure, my bad. It should be "$allow != 1". And "$method" should be > "$request_method" instead. > > -- > Maxim Dounin > http://mdounin.ru/ > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -------------- next part -------------- An HTML attachment was scrubbed... URL: From spacewanderlzx at gmail.com Mon Jan 20 12:27:42 2020 From: spacewanderlzx at gmail.com (Zexuan Luo) Date: Mon, 20 Jan 2020 20:27:42 +0800 Subject: [PATCH] Keep remote port unchanged if real address doesn't contain a port. Message-ID: # HG changeset patch # User spacewander # Date 1579523127 -28800 # Mon Jan 20 20:25:27 2020 +0800 # Branch ident # Node ID 86dbfc59e9c01608244c4fdc0d9a87fd9d330648 # Parent 4fb5603514f2d324c50cb7e12c6ed0dc8935de0f Keep remote port unchanged if real address doesn't contain a port. Previously, when the request comes from a trusted address and it doesn't contain the port part, the $remote_port will be empty. This change has two advantages: 1. no need to write your own fallback with $remote_port and $realip_remote_port. 2. the $remote_port in the existent code doesn't need to be changed. diff -r 4fb5603514f2 -r 86dbfc59e9c0 src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c Thu Apr 18 17:59:00 2019 +0800 +++ b/src/http/ngx_http_core_module.c Mon Jan 20 20:25:27 2020 +0800 @@ -2683,6 +2683,12 @@ return NGX_DECLINED; } + in_port_t port = ngx_inet_get_port(paddr.sockaddr); + if (port == 0) { + port = ngx_inet_get_port(addr->sockaddr); + ngx_inet_set_port(paddr.sockaddr, port); + } + *addr = paddr; if (recursive && p > xff) { -------------- next part -------------- An HTML attachment was scrubbed... URL: From ru at nginx.com Mon Jan 20 14:26:24 2020 From: ru at nginx.com (Ruslan Ermilov) Date: Mon, 20 Jan 2020 17:26:24 +0300 Subject: [PATCH] Keep remote port unchanged if real address doesn't contain a port. In-Reply-To: References: Message-ID: <20200120142624.GC45176@lo0.su> On Mon, Jan 20, 2020 at 08:27:42PM +0800, Zexuan Luo wrote: > # HG changeset patch > # User spacewander > # Date 1579523127 -28800 > # Mon Jan 20 20:25:27 2020 +0800 > # Branch ident > # Node ID 86dbfc59e9c01608244c4fdc0d9a87fd9d330648 > # Parent 4fb5603514f2d324c50cb7e12c6ed0dc8935de0f > Keep remote port unchanged if real address doesn't contain a port. > > Previously, when the request comes from a trusted address and it doesn't > contain > the port part, the $remote_port will be empty. > > This change has two advantages: > 1. no need to write your own fallback with $remote_port and > $realip_remote_port. > 2. the $remote_port in the existent code doesn't need to be changed. Preserving the port while changing the client address would be misleading. Also, it's been the behavior before realip learned how to change the client's port (1.11.0). Thus, it's believed that the current behavior is correct. From mstavrev at gmail.com Mon Jan 20 15:29:25 2020 From: mstavrev at gmail.com (mstavrev at gmail.com) Date: Mon, 20 Jan 2020 17:29:25 +0200 Subject: [PATCH] Fix for the HT on request headers problem (#1752) Message-ID: # HG changeset patch # User Marin Stavrev # Date 1579526641 -7200 # Mon Jan 20 15:24:01 2020 +0200 # Node ID bf238762fdaf03383c2f3c3718c401e6141e3935 # Parent 6439ef81e37dfccfc3a8c57fed278bf56014ef39 Fix for the HT on request headers problem (#1752) When client send HTTP request with a header of Content-Length that starts with horizontal tab character (HT=0x09), Nginx responds with HTTP 400 Bad Request. According to HTTP RFC2616 section 4.2, "... The field value MAY be preceded by any amount of LWS, though a single SP is preferred.". The difinition of LWS is: LWS = [CRLF] 1*( SP | HT ) So a header such as the following should be processed fine: Content-Length:<0x09>110\r\n diff -r 6439ef81e37d -r bf238762fdaf src/http/ngx_http_parse.c --- a/src/http/ngx_http_parse.c Fri Jan 17 12:13:02 2020 +0300 +++ b/src/http/ngx_http_parse.c Mon Jan 20 15:24:01 2020 +0200 @@ -1000,6 +1000,7 @@ case sw_space_before_value: switch (ch) { case ' ': + case '\x9': break; case CR: r->header_start = p; @@ -1023,6 +1024,7 @@ case sw_value: switch (ch) { case ' ': + case '\x9': r->header_end = p; state = sw_space_after_value; break; @@ -1042,6 +1044,7 @@ case sw_space_after_value: switch (ch) { case ' ': + case '\x9': break; case CR: state = sw_almost_done; From xeioex at nginx.com Tue Jan 21 13:04:42 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 21 Jan 2020 13:04:42 +0000 Subject: [njs] Fixed Function constructor according to the spec. Message-ID: details: https://hg.nginx.org/njs/rev/142b3fec5d4f branches: changeset: 1306:142b3fec5d4f user: Dmitry Volyntsev date: Tue Jan 21 16:01:45 2020 +0300 description: Fixed Function constructor according to the spec. "this" value should point to the global object. diffstat: src/njs.h | 2 +- src/njs_function.c | 127 ++++++++++++++++++++++++++-------------------- src/njs_value.h | 3 +- src/test/njs_unit_test.c | 12 ++++ test/njs_expect_test.exp | 6 ++ 5 files changed, 93 insertions(+), 57 deletions(-) diffs (242 lines): diff -r c735708203e8 -r 142b3fec5d4f src/njs.h --- a/src/njs.h Fri Jan 17 10:04:28 2020 +0300 +++ b/src/njs.h Tue Jan 21 16:01:45 2020 +0300 @@ -41,7 +41,7 @@ typedef struct { /* sizeof(njs_value_t) is 16 bytes. */ #define njs_argument(args, n) \ - (njs_value_t *) ((u_char *) args + n * 16) + (njs_value_t *) ((u_char *) args + (n) * 16) extern const njs_value_t njs_value_undefined; diff -r c735708203e8 -r 142b3fec5d4f src/njs_function.c --- a/src/njs_function.c Fri Jan 17 10:04:28 2020 +0300 +++ b/src/njs_function.c Tue Jan 21 16:01:45 2020 +0300 @@ -463,7 +463,14 @@ njs_function_lambda_frame(njs_vm_t *vm, native_frame->arguments = value; if (bound == NULL) { - *value++ = *this; + *value = *this; + + if (njs_slow_path(function->global_this + && njs_is_null_or_undefined(this))) { + njs_set_object(value, &vm->global_object); + } + + value++; } else { n = function->args_offset; @@ -838,64 +845,69 @@ static njs_int_t njs_function_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - size_t size; - u_char *start, *end; - njs_int_t ret; - njs_str_t str, file; - njs_uint_t i; - njs_lexer_t lexer; - njs_parser_t *parser; - njs_generator_t generator; - njs_parser_scope_t *scope; + njs_chb_t chain; + njs_int_t ret; + njs_str_t str, file; + njs_uint_t i; + njs_value_t *body; + njs_lexer_t lexer; + njs_parser_t *parser; + njs_function_t *function; + njs_generator_t generator; + njs_parser_scope_t *scope; + njs_function_lambda_t *lambda; + njs_vmcode_function_t *code; if (!vm->options.unsafe) { - njs_type_error(vm, "function constructor is disabled in \"safe\" mode"); - return NJS_ERROR; + body = njs_argument(args, nargs - 1); + ret = njs_value_to_string(vm, body, body); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + njs_string_get(body, &str); + + /* + * Safe mode exception: + * "(new Function('return this'))" is often used to get + * the global object in a portable way. + */ + + if (str.length != njs_length("return this") + || memcmp(str.start, "return this", 11) != 0) + { + njs_type_error(vm, "function constructor is disabled" + " in \"safe\" mode"); + return NJS_ERROR; + } } - if (nargs < 2) { - start = (u_char *) "(function(){})"; - end = start + njs_length("(function(){})"); + njs_chb_init(&chain, vm->mem_pool); - } else { - size = njs_length("(function(") + nargs + njs_length("){})"); + njs_chb_append_literal(&chain, "(function("); - for (i = 1; i < nargs; i++) { - if (!njs_is_string(&args[i])) { - ret = njs_value_to_string(vm, &args[i], &args[i]); - if (ret != NJS_OK) { - return ret; - } - } - - njs_string_get(&args[i], &str); - size += str.length; + for (i = 1; i < nargs - 1; i++) { + ret = njs_value_to_chain(vm, &chain, njs_argument(args, i)); + if (njs_slow_path(ret < NJS_OK)) { + return ret; } - start = njs_mp_alloc(vm->mem_pool, size); - if (njs_slow_path(start == NULL)) { - return NJS_ERROR; - } + njs_chb_append_literal(&chain, ","); + } - end = njs_cpymem(start, "(function(", njs_length("(function(")); - - for (i = 1; i < nargs - 1; i++) { - if (i != 1) { - *end++ = ','; - } + njs_chb_append_literal(&chain, "){"); - njs_string_get(&args[i], &str); - end = njs_cpymem(end, str.start, str.length); - } + ret = njs_value_to_chain(vm, &chain, njs_argument(args, nargs - 1)); + if (njs_slow_path(ret < NJS_OK)) { + return ret; + } - *end++ = ')'; - *end++ = '{'; + njs_chb_append_literal(&chain, "})"); - njs_string_get(&args[nargs - 1], &str); - end = njs_cpymem(end, str.start, str.length); - - *end++ = '}'; - *end++ = ')'; + ret = njs_chb_join(&chain, &str); + if (njs_slow_path(ret != NJS_OK)) { + njs_memory_error(vm); + return NJS_ERROR; } vm->options.accumulative = 1; @@ -909,7 +921,7 @@ njs_function_constructor(njs_vm_t *vm, n file = njs_str_value("runtime"); - ret = njs_lexer_init(vm, &lexer, &file, start, end); + ret = njs_lexer_init(vm, &lexer, &file, str.start, str.start + str.length); if (njs_slow_path(ret != NJS_OK)) { return ret; } @@ -940,15 +952,20 @@ njs_function_constructor(njs_vm_t *vm, n return ret; } - if (vm->options.disassemble) { - njs_printf("new Function:runtime\n"); - njs_disassemble(generator.code_start, generator.code_end); + njs_chb_destroy(&chain); + + code = (njs_vmcode_function_t *) generator.code_start; + lambda = code->lambda; + + function = njs_function_alloc(vm, lambda, NULL, 0); + if (njs_slow_path(function == NULL)) { + return NJS_ERROR; } - ret = njs_vmcode_interpreter(vm, generator.code_start); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } + function->global_this = 1; + function->args_count = lambda->nargs - lambda->rest_parameters; + + njs_set_function(&vm->retval, function); return NJS_OK; } diff -r c735708203e8 -r 142b3fec5d4f src/njs_value.h --- a/src/njs_value.h Fri Jan 17 10:04:28 2020 +0300 +++ b/src/njs_value.h Tue Jan 21 16:01:45 2020 +0300 @@ -278,7 +278,7 @@ struct njs_function_s { uint8_t args_offset; - uint8_t args_count:5; + uint8_t args_count:4; /* * If "closure" is true njs_closure_t[] is available right after the @@ -291,6 +291,7 @@ struct njs_function_s { uint8_t closure:1; uint8_t native:1; uint8_t ctor:1; + uint8_t global_this:1; uint8_t magic; diff -r c735708203e8 -r 142b3fec5d4f src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Fri Jan 17 10:04:28 2020 +0300 +++ b/src/test/njs_unit_test.c Tue Jan 21 16:01:45 2020 +0300 @@ -11296,6 +11296,18 @@ static njs_unit_test_t njs_test[] = { njs_str("var fn = (function() { return new Function('return this'); }).call({}), o = {}; fn.call(o) == o && fn.bind(o).call(this) == o"), njs_str("true") }, + { njs_str("(new Function('return this'))() === globalThis"), + njs_str("true") }, + + { njs_str("(new Function('a', 'return a')).length"), + njs_str("1") }, + + { njs_str("(new Function('a','b', 'return a + b')).length"), + njs_str("2") }, + + { njs_str("var o = {}; (new Function('return this')).call(o) === o"), + njs_str("true") }, + { njs_str("this.NN = {}; var f = Function('eval = 42;'); f()"), njs_str("SyntaxError: Identifier \"eval\" is forbidden as left-hand in assignment in runtime:1") }, diff -r c735708203e8 -r 142b3fec5d4f test/njs_expect_test.exp --- a/test/njs_expect_test.exp Fri Jan 17 10:04:28 2020 +0300 +++ b/test/njs_expect_test.exp Tue Jan 21 16:01:45 2020 +0300 @@ -849,6 +849,12 @@ njs_test { njs_test { {"new Function()\r\n" "TypeError: function constructor is disabled in \"safe\" mode\r\n"} + {"(new Function('return this'))() === globalThis\r\n" + "true\r\n"} + {"new Function('return this;')\r\n" + "TypeError: function constructor is disabled in \"safe\" mode\r\n"} + {"new Function('return thi')\r\n" + "TypeError: function constructor is disabled in \"safe\" mode\r\n"} } "-u" From xeioex at nginx.com Tue Jan 21 13:04:44 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 21 Jan 2020 13:04:44 +0000 Subject: [njs] Added %TypedArray%.prototype.subarray(). Message-ID: details: https://hg.nginx.org/njs/rev/5cf918cc0d06 branches: changeset: 1307:5cf918cc0d06 user: Dmitry Volyntsev date: Tue Jan 21 16:01:48 2020 +0300 description: Added %TypedArray%.prototype.subarray(). diffstat: src/njs_typed_array.c | 87 ++++++++++++++++++++++++++++++----------------- src/test/njs_unit_test.c | 32 +++++++++++++++++ 2 files changed, 87 insertions(+), 32 deletions(-) diffs (188 lines): diff -r 142b3fec5d4f -r 5cf918cc0d06 src/njs_typed_array.c --- a/src/njs_typed_array.c Tue Jan 21 16:01:45 2020 +0300 +++ b/src/njs_typed_array.c Tue Jan 21 16:01:48 2020 +0300 @@ -607,10 +607,10 @@ njs_typed_array_prototype_fill(njs_vm_t static njs_int_t njs_typed_array_species_create(njs_vm_t *vm, njs_value_t *exemplar, - int64_t count, njs_value_t *retval) + njs_value_t *args, njs_uint_t nargs, njs_value_t *retval) { njs_int_t ret; - njs_value_t this, constructor, argument; + njs_value_t this, constructor; njs_object_t *object; njs_typed_array_t *array; @@ -630,10 +630,9 @@ njs_typed_array_species_create(njs_vm_t } njs_set_object(&this, object); - njs_set_number(&argument, count); ret = njs_function_call2(vm, njs_function(&constructor), &this, - &argument, 1, retval, 1); + args, nargs, retval, 1); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -644,24 +643,18 @@ njs_typed_array_species_create(njs_vm_t return NJS_ERROR; } - array = njs_typed_array(retval); - if (njs_typed_array_length(array) < count) { - njs_type_error(vm, "Derived TypedArray constructor too small array"); - return NJS_ERROR; - } - return NJS_OK; } static njs_int_t njs_typed_array_prototype_slice(njs_vm_t *vm, njs_value_t *args, - njs_uint_t nargs, njs_index_t unused) + njs_uint_t nargs, njs_index_t copy) { - int64_t start, end, count; + int64_t start, end, count, offset; uint32_t i, element_size, length; njs_int_t ret; - njs_value_t *this, *value; + njs_value_t arguments[3], *this, *value; njs_typed_array_t *array, *new_array; njs_array_buffer_t *buffer, *new_buffer; @@ -698,32 +691,54 @@ njs_typed_array_prototype_slice(njs_vm_t end = (end < 0) ? njs_max(length + end, 0) : njs_min(end, length); - count = njs_max(end - start, 0); - - ret = njs_typed_array_species_create(vm, this, count, &vm->retval); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - new_array = njs_typed_array(&vm->retval); - new_buffer = njs_typed_array_buffer(new_array); element_size = njs_typed_array_element_size(array->type); - if (njs_fast_path(array->type == new_array->type)) { - start = start * element_size; - count = count * element_size; + if (copy) { + count = njs_max(end - start, 0); + njs_set_number(&arguments[0], count); - memcpy(&new_buffer->u.u8[0], &buffer->u.u8[start], count); + ret = njs_typed_array_species_create(vm, this, + njs_value_arg(arguments), 1, + &vm->retval); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + new_array = njs_typed_array(&vm->retval); + if (njs_typed_array_length(new_array) < count) { + njs_type_error(vm, "Derived TypedArray constructor is " + "too small array"); + return NJS_ERROR; + } - } else { - for (i = 0; i < count; i++) { - njs_typed_array_set(new_array, i, - njs_typed_array_get(array, i + start)); + new_buffer = njs_typed_array_buffer(new_array); + element_size = njs_typed_array_element_size(array->type); + + if (njs_fast_path(array->type == new_array->type)) { + start = start * element_size; + count = count * element_size; + + memcpy(&new_buffer->u.u8[0], &buffer->u.u8[start], count); + + } else { + for (i = 0; i < count; i++) { + njs_typed_array_set(new_array, i, + njs_typed_array_get(array, i + start)); + } } + + return NJS_OK; } + offset = array->offset * element_size; + offset += start * element_size; - return NJS_OK; + njs_set_array_buffer(&arguments[0], buffer); + njs_set_number(&arguments[1], offset); + njs_set_number(&arguments[2], njs_max(end - start, 0)); + + return njs_typed_array_species_create(vm, this, njs_value_arg(arguments), 3, + &vm->retval); } @@ -1024,7 +1039,15 @@ static const njs_object_prop_t njs_type { .type = NJS_PROPERTY, .name = njs_string("slice"), - .value = njs_native_function(njs_typed_array_prototype_slice, 2), + .value = njs_native_function2(njs_typed_array_prototype_slice, 2, 1), + .writable = 1, + .configurable = 1, + }, + + { + .type = NJS_PROPERTY, + .name = njs_string("subarray"), + .value = njs_native_function2(njs_typed_array_prototype_slice, 2, 0), .writable = 1, .configurable = 1, }, diff -r 142b3fec5d4f -r 5cf918cc0d06 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Tue Jan 21 16:01:45 2020 +0300 +++ b/src/test/njs_unit_test.c Tue Jan 21 16:01:48 2020 +0300 @@ -5315,6 +5315,38 @@ static njs_unit_test_t njs_test[] = njs_str("true") }, { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{var a = new v([1,2,3]); " + " var r = a.slice(1,3);" + " return a.buffer !== r.buffer;})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{var a = new v([1,2,3]); " + " var r = a.slice(1,3);" + " a[1] = 0;" + " return njs.dump(r) === `${v.name} [2,3]`;})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{var a = new v([1,2,3,4]); " + " var r = a.subarray(1,3);" + " a[1] = 0;" + " return njs.dump(r) === `${v.name} [0,3]`;})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{var a = new v([1,2,3,4]); " + " a.subarray(1,3).fill(0);" + " return njs.dump(a) === `${v.name} [1,0,0,4]`;})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{var a = new v([1,2,3]); " + " var r = a.subarray(1,3);" + " return a.buffer === r.buffer;})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST ".every(v=>{var a = new v([1,2,3,4]); a.copyWithin(2); " " return a.toString() === '1,2,1,2'})"), njs_str("true") }, From xeioex at nginx.com Tue Jan 21 13:04:46 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 21 Jan 2020 13:04:46 +0000 Subject: [njs] Fixed %TypedArray%.prototype.fill(). Message-ID: details: https://hg.nginx.org/njs/rev/a34f1293edba branches: changeset: 1308:a34f1293edba user: Dmitry Volyntsev date: Tue Jan 21 16:03:30 2020 +0300 description: Fixed %TypedArray%.prototype.fill(). For subarrays starting from non-zero offset. diffstat: src/njs_typed_array.c | 30 ++++++++++++++++-------------- src/njs_typed_array.h | 6 ++---- src/test/njs_unit_test.c | 11 +++++++++++ 3 files changed, 29 insertions(+), 18 deletions(-) diffs (134 lines): diff -r 5cf918cc0d06 -r a34f1293edba src/njs_typed_array.c --- a/src/njs_typed_array.c Tue Jan 21 16:01:48 2020 +0300 +++ b/src/njs_typed_array.c Tue Jan 21 16:03:30 2020 +0300 @@ -491,7 +491,7 @@ njs_typed_array_prototype_fill(njs_vm_t int16_t i16; int32_t i32; uint8_t u8; - int64_t start, end; + int64_t start, end, offset; uint32_t i, length; njs_int_t ret; njs_value_t *this, *setval, lvalue; @@ -535,20 +535,22 @@ njs_typed_array_prototype_fill(njs_vm_t njs_set_typed_array(&vm->retval, array); buffer = array->buffer; + offset = array->offset; switch (array->type) { case NJS_OBJ_TYPE_UINT8_CLAMPED_ARRAY: - if (num < 0) { - num = 0; + if (isnan(num) || num < 0) { + u8 = 0; } else if (num > 255) { - num = 255; + u8 = 255; + + } else { + u8 = lrint(num); } - u8 = lrint(num); - - for (i = start; i < end; i++) { - buffer->u.u8[i] = u8; + if (start < end) { + memset(&buffer->u.u8[start + offset], u8, end - start); } break; @@ -557,8 +559,8 @@ njs_typed_array_prototype_fill(njs_vm_t case NJS_OBJ_TYPE_INT8_ARRAY: i8 = njs_number_to_int32(num); - for (i = start; i < end; i++) { - buffer->u.u8[i] = i8; + if (start < end) { + memset(&buffer->u.u8[start + offset], i8, end - start); } break; @@ -568,7 +570,7 @@ njs_typed_array_prototype_fill(njs_vm_t i16 = njs_number_to_int32(num); for (i = start; i < end; i++) { - buffer->u.u16[i] = i16; + buffer->u.u16[i + offset] = i16; } break; @@ -578,7 +580,7 @@ njs_typed_array_prototype_fill(njs_vm_t i32 = njs_number_to_int32(num); for (i = start; i < end; i++) { - buffer->u.u32[i] = i32; + buffer->u.u32[i + offset] = i32; } break; @@ -587,7 +589,7 @@ njs_typed_array_prototype_fill(njs_vm_t f32 = num; for (i = start; i < end; i++) { - buffer->u.f32[i] = f32; + buffer->u.f32[i + offset] = f32; } break; @@ -597,7 +599,7 @@ njs_typed_array_prototype_fill(njs_vm_t /* NJS_OBJ_TYPE_FLOAT64_ARRAY. */ for (i = start; i < end; i++) { - buffer->u.f64[i] = num; + buffer->u.f64[i + offset] = num; } } diff -r 5cf918cc0d06 -r a34f1293edba src/njs_typed_array.h --- a/src/njs_typed_array.h Tue Jan 21 16:01:48 2020 +0300 +++ b/src/njs_typed_array.h Tue Jan 21 16:03:30 2020 +0300 @@ -103,11 +103,9 @@ njs_typed_array_set(njs_typed_array_t *a switch (array->type) { case NJS_OBJ_TYPE_UINT8_CLAMPED_ARRAY: - if (v < 0) { + if (isnan(v) || v < 0) { v = 0; - } - - if (v > 255) { + } else if (v > 255) { v = 255; } diff -r 5cf918cc0d06 -r a34f1293edba src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Tue Jan 21 16:01:48 2020 +0300 +++ b/src/test/njs_unit_test.c Tue Jan 21 16:03:30 2020 +0300 @@ -5005,6 +5005,11 @@ static njs_unit_test_t njs_test[] = " return (a[0] === 1 && a[1] === 12 && a[2] === 3 && a.length == 3)})"), njs_str("true") }, + { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{var a = new v([0,0,0,0,0]).fill(8, -1, -3); " + " return njs.dump(a) === `${v.name} [0,0,0,0,0]`;})"), + njs_str("true") }, + { njs_str(NJS_INT_TYPED_ARRAY_LIST ".every(v=>{var a = new v([1,2,3]); a.fill('qq', 1, 2); " " return (a[0] === 1 && a[1] === 0 && a[2] === 3 && a.length == 3)})"), @@ -5341,6 +5346,12 @@ static njs_unit_test_t njs_test[] = njs_str("true") }, { njs_str(NJS_TYPED_ARRAY_LIST + ".every(v=>{var a = new v([1,2,3,4]); " + " a.subarray(1,10).fill(0);" + " return njs.dump(a) === `${v.name} [1,0,0,0]`;})"), + njs_str("true") }, + + { njs_str(NJS_TYPED_ARRAY_LIST ".every(v=>{var a = new v([1,2,3]); " " var r = a.subarray(1,3);" " return a.buffer === r.buffer;})"), From xeioex at nginx.com Tue Jan 21 13:30:47 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 21 Jan 2020 13:30:47 +0000 Subject: [njs] Version 0.3.8. Message-ID: details: https://hg.nginx.org/njs/rev/1abb97e9d9dc branches: changeset: 1309:1abb97e9d9dc user: Dmitry Volyntsev date: Tue Jan 21 16:06:20 2020 +0300 description: Version 0.3.8. diffstat: CHANGES | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ LICENSE | 7 ++++--- 2 files changed, 66 insertions(+), 3 deletions(-) diffs (84 lines): diff -r a34f1293edba -r 1abb97e9d9dc CHANGES --- a/CHANGES Tue Jan 21 16:03:30 2020 +0300 +++ b/CHANGES Tue Jan 21 16:06:20 2020 +0300 @@ -1,3 +1,65 @@ + +Changes with njs 0.3.8 21 Jan 2020 + + nginx modules: + + *) Feature: added Promise support for r.subrequest(). If callback + is not provided r.subrequest() returns an ordinary Promise object + that resolves to subrequest response object. + + *) Change: r.parent property handler now returns "undefined" + instead of throwing exception if parent object is not available. + + Core: + + *) Feature: added Promise support. Implemented according to + the specification without: Promise.all(), Promise.allSettled(), + Promise.race(). + + *) Feature: added initial Typed-arrays support. + Thanks to Tiago Natel de Moura. + + *) Feature: added ArrayBuffer support. + Thanks to Tiago Natel de Moura. + + *) Feature: added initial Symbol support. + Thanks to Artem S. Povalyukhin. + + *) Feature: added externals supopor for JSON.stringify(). + + *) Feature: added Object.is(). + Thanks to Artem S. Povalyukhin. + + *) Feature: added Object.setPrototypeOf(). + Thanks to Artem S. Povalyukhin. + + *) Feature: introduced nullish coalescing operator. + Thanks to Valentin Bartenev. + + *) Bugfix: fixed Object.getPrototypeOf() according to the + specification. + + *) Bugfix: fixed Object.prototype.valueOf() according to the + specification. + + *) Bugfix: fixed JSON.stringify() with unprintable values and + replacer function. + + *) Bugfix: fixed operator "in" according to the specification. + + *) Bugfix: fixed Object.defineProperties() according to the + specification. + + *) Bugfix: fixed Object.create() according to the specification. + Thanks to Artem S. Povalyukhin. + + *) Bugfix: fixed Number.prototype.toString(radix) when + fast-math is enabled. + + *) Bugfix: fixed RegExp() instance properties. + + *) Bugfix: fixed import segfault. + Thanks to ??? (Hong Zhi Dao). Changes with njs 0.3.7 19 Nov 2019 diff -r a34f1293edba -r 1abb97e9d9dc LICENSE --- a/LICENSE Tue Jan 21 16:03:30 2020 +0300 +++ b/LICENSE Tue Jan 21 16:06:20 2020 +0300 @@ -1,7 +1,8 @@ /* - * Copyright (C) 2015-2019 NGINX, Inc. - * Copyright (C) 2015-2019 Igor Sysoev - * Copyright (C) 2017-2019 Dmitry Volyntsev + * Copyright (C) 2015-2020 NGINX, Inc. + * Copyright (C) 2015-2020 Igor Sysoev + * Copyright (C) 2017-2020 Dmitry Volyntsev + * Copyright (C) 2019-2020 Alexander Borisov * All rights reserved. * * Redistribution and use in source and binary forms, with or without From xeioex at nginx.com Tue Jan 21 13:30:49 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 21 Jan 2020 13:30:49 +0000 Subject: [njs] Added tag 0.3.8 for changeset 1abb97e9d9dc Message-ID: details: https://hg.nginx.org/njs/rev/5396e72ca030 branches: changeset: 1310:5396e72ca030 user: Dmitry Volyntsev date: Tue Jan 21 16:30:20 2020 +0300 description: Added tag 0.3.8 for changeset 1abb97e9d9dc diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff -r 1abb97e9d9dc -r 5396e72ca030 .hgtags --- a/.hgtags Tue Jan 21 16:06:20 2020 +0300 +++ b/.hgtags Tue Jan 21 16:30:20 2020 +0300 @@ -31,3 +31,4 @@ 8eadbb3a7c7b7c3426f73adabfa251cd9d296752 b7fa83f27f1b64443b88c990e1851f59583b2182 0.3.5 7b302775917b72537e1abdbd5dc9d04e55a7d582 0.3.6 9e5ef927c7eaed003de3e5e4a16fa3eab08de7f7 0.3.7 +1abb97e9d9dc07dcff2616d4c75132e6d189a6aa 0.3.8 From mdounin at mdounin.ru Tue Jan 21 13:47:00 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 21 Jan 2020 13:47:00 +0000 Subject: [nginx] nginx-1.17.8-RELEASE Message-ID: details: https://hg.nginx.org/nginx/rev/fdacd273711d branches: changeset: 7620:fdacd273711d user: Maxim Dounin date: Tue Jan 21 16:39:41 2020 +0300 description: nginx-1.17.8-RELEASE diffstat: docs/xml/nginx/changes.xml | 36 ++++++++++++++++++++++++++++++++++++ 1 files changed, 36 insertions(+), 0 deletions(-) diffs (46 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,42 @@ + + + + +????????? grpc_pass ???????????? ??????????. + + +variables support in the "grpc_pass" directive. + + + + + +??? ????????? pipelined-???????? ?? SSL-?????????? ??? ????????? ???????; +?????? ????????? ? 1.17.5. + + +a timeout might occur while handling pipelined requests in an SSL connection; +the bug had appeared in 1.17.5. + + + + + +? ????????? debug_points ??? ????????????? HTTP/2.
+??????? ??????? ?????????. +
+ +in the "debug_points" directive when using HTTP/2.
+Thanks to Daniil Bondarev. +
+
+ +
+ + From mdounin at mdounin.ru Tue Jan 21 13:47:03 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 21 Jan 2020 13:47:03 +0000 Subject: [nginx] release-1.17.8 tag Message-ID: details: https://hg.nginx.org/nginx/rev/b8a512c6466c branches: changeset: 7621:b8a512c6466c user: Maxim Dounin date: Tue Jan 21 16:39:42 2020 +0300 description: release-1.17.8 tag diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -446,3 +446,4 @@ ce2ced3856909f36f8130c99eaa4dbdbae636ddc 9af0dddbddb2c368bfedd2801bc100ffad01e19b release-1.17.5 de68d0d94320cbf033599c6f3ca37e5335c67fd7 release-1.17.6 e56295fe0ea76bf53b06bffa77a2d3a9a335cb8c release-1.17.7 +fdacd273711ddf20f778c1fb91529ab53979a454 release-1.17.8 From xeioex at nginx.com Wed Jan 22 12:58:06 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 22 Jan 2020 12:58:06 +0000 Subject: [njs] Version bump. Message-ID: details: https://hg.nginx.org/njs/rev/b4531fb781b8 branches: changeset: 1311:b4531fb781b8 user: Dmitry Volyntsev date: Tue Jan 21 17:37:37 2020 +0300 description: Version bump. diffstat: src/njs.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 5396e72ca030 -r b4531fb781b8 src/njs.h --- a/src/njs.h Tue Jan 21 16:30:20 2020 +0300 +++ b/src/njs.h Tue Jan 21 17:37:37 2020 +0300 @@ -11,7 +11,7 @@ #include -#define NJS_VERSION "0.3.8" +#define NJS_VERSION "0.3.9" #include /* STDOUT_FILENO, STDERR_FILENO */ From xeioex at nginx.com Wed Jan 22 12:58:08 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 22 Jan 2020 12:58:08 +0000 Subject: [njs] Fixed typo introduced in 1abb97e9d9dc. Message-ID: details: https://hg.nginx.org/njs/rev/74c2de51636c branches: changeset: 1312:74c2de51636c user: Dmitry Volyntsev date: Wed Jan 22 15:29:44 2020 +0300 description: Fixed typo introduced in 1abb97e9d9dc. diffstat: CHANGES | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r b4531fb781b8 -r 74c2de51636c CHANGES --- a/CHANGES Tue Jan 21 17:37:37 2020 +0300 +++ b/CHANGES Wed Jan 22 15:29:44 2020 +0300 @@ -25,7 +25,7 @@ Changes with njs 0.3.8 *) Feature: added initial Symbol support. Thanks to Artem S. Povalyukhin. - *) Feature: added externals supopor for JSON.stringify(). + *) Feature: added externals support for JSON.stringify(). *) Feature: added Object.is(). Thanks to Artem S. Povalyukhin. From xeioex at nginx.com Wed Jan 22 12:58:10 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 22 Jan 2020 12:58:10 +0000 Subject: [njs] Fixed match of native function is backtraces. Message-ID: details: https://hg.nginx.org/njs/rev/b247b1c5531f branches: changeset: 1313:b247b1c5531f user: Dmitry Volyntsev date: Wed Jan 22 15:29:47 2020 +0300 description: Fixed match of native function is backtraces. Since 6df48738a043 native methods are not uniquely identifiable by a function pointer as several method may share common C function and differ only in magic argument. diffstat: src/njs_builtin.c | 10 ++++++---- src/njs_function.h | 7 +++++++ src/njs_vm.c | 3 +-- src/njs_vm.h | 2 +- src/test/njs_interactive_test.c | 13 +++++++++---- 5 files changed, 24 insertions(+), 11 deletions(-) diffs (116 lines): diff -r 74c2de51636c -r b247b1c5531f src/njs_builtin.c --- a/src/njs_builtin.c Wed Jan 22 15:29:44 2020 +0300 +++ b/src/njs_builtin.c Wed Jan 22 15:29:47 2020 +0300 @@ -15,7 +15,7 @@ typedef struct { NJS_BUILTIN_TRAVERSE_MATCH, } type; - njs_function_native_t native; + njs_function_t *func; njs_lvlhsh_t keys; njs_str_t match; @@ -391,6 +391,7 @@ njs_builtin_traverse(njs_vm_t *vm, njs_t u_char *p, *start, *end; njs_int_t ret, n; njs_str_t name; + njs_function_t *func; njs_object_prop_t *prop; njs_lvlhsh_query_t lhq; njs_builtin_traverse_t *ctx; @@ -401,10 +402,11 @@ njs_builtin_traverse(njs_vm_t *vm, njs_t if (ctx->type == NJS_BUILTIN_TRAVERSE_MATCH) { prop = traverse->prop; + func = ctx->func; if (!(njs_is_function(&prop->value) && njs_function(&prop->value)->native - && njs_function(&prop->value)->u.native == ctx->native)) + && njs_native_function_same(njs_function(&prop->value), func))) { return NJS_OK; } @@ -739,7 +741,7 @@ njs_object_completions(njs_vm_t *vm, njs njs_int_t -njs_builtin_match_native_function(njs_vm_t *vm, njs_function_native_t func, +njs_builtin_match_native_function(njs_vm_t *vm, njs_function_t *function, njs_str_t *name) { njs_int_t ret; @@ -750,7 +752,7 @@ njs_builtin_match_native_function(njs_vm njs_builtin_traverse_t ctx; ctx.type = NJS_BUILTIN_TRAVERSE_MATCH; - ctx.native = func; + ctx.func = function; /* Global object. */ diff -r 74c2de51636c -r b247b1c5531f src/njs_function.h --- a/src/njs_function.h Wed Jan 22 15:29:44 2020 +0300 +++ b/src/njs_function.h Wed Jan 22 15:29:47 2020 +0300 @@ -203,6 +203,13 @@ njs_function_apply(njs_vm_t *vm, njs_fun } +njs_inline njs_bool_t +njs_native_function_same(const njs_function_t *f1, const njs_function_t *f2) +{ + return f1->u.native == f2->u.native && f1->magic == f2->magic; +} + + extern const njs_object_type_init_t njs_function_type_init; extern const njs_object_init_t njs_function_instance_init; extern const njs_object_init_t njs_arrow_instance_init; diff -r 74c2de51636c -r b247b1c5531f src/njs_vm.c --- a/src/njs_vm.c Wed Jan 22 15:29:44 2020 +0300 +++ b/src/njs_vm.c Wed Jan 22 15:29:47 2020 +0300 @@ -991,8 +991,7 @@ njs_vm_add_backtrace_entry(njs_vm_t *vm, function = function->u.bound_target; } - ret = njs_builtin_match_native_function(vm, function->u.native, - &be->name); + ret = njs_builtin_match_native_function(vm, function, &be->name); if (ret == NJS_OK) { return NJS_OK; } diff -r 74c2de51636c -r b247b1c5531f src/njs_vm.h --- a/src/njs_vm.h Wed Jan 22 15:29:44 2020 +0300 +++ b/src/njs_vm.h Wed Jan 22 15:29:47 2020 +0300 @@ -302,7 +302,7 @@ njs_int_t njs_vm_backtrace_to_string(njs njs_int_t njs_builtin_objects_create(njs_vm_t *vm); njs_int_t njs_builtin_objects_clone(njs_vm_t *vm, njs_value_t *global); njs_int_t njs_builtin_match_native_function(njs_vm_t *vm, - njs_function_native_t func, njs_str_t *name); + njs_function_t *function, njs_str_t *name); njs_arr_t *njs_vm_completions(njs_vm_t *vm, njs_str_t *expression); diff -r 74c2de51636c -r b247b1c5531f src/test/njs_interactive_test.c --- a/src/test/njs_interactive_test.c Wed Jan 22 15:29:44 2020 +0300 +++ b/src/test/njs_interactive_test.c Wed Jan 22 15:29:47 2020 +0300 @@ -232,10 +232,15 @@ static njs_interactive_test_t njs_test[ " at f (:1)\n" " at main (native)\n") }, - { njs_str("var fs = require('fs'); fs.readFile()" ENTER), - njs_str("TypeError: \"path\" must be a string\n" - " at fs.readFile (native)\n" - " at main (native)\n") }, + { njs_str("var fs = require('fs');" + "['readFile'," + " 'readFileSync'," + " 'writeFile'," + " 'writeFileSync'," + " 'appendFile'," + " 'appendFileSync']" + ".every(v=>{ try {fs[v]();} catch (e) { return e.stack.search(`fs.${v} `) >= 0}})" ENTER), + njs_str("true") }, { njs_str("parseInt({ toString: function() { return [1] } })" ENTER), njs_str("TypeError: Cannot convert object to primitive value\n" From xeioex at nginx.com Wed Jan 22 12:58:12 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Wed, 22 Jan 2020 12:58:12 +0000 Subject: [njs] Fixed callback invocations in "fs" module. Message-ID: details: https://hg.nginx.org/njs/rev/2b75ee955589 branches: changeset: 1314:2b75ee955589 user: Artem S. Povalyukhin date: Mon Jan 20 13:24:09 2020 +0300 description: Fixed callback invocations in "fs" module. This closes #200 issue on Github. diffstat: src/njs_fs.c | 799 +++++++++++++++------------------------------- src/test/njs_unit_test.c | 34 +- test/njs_expect_test.exp | 42 +- 3 files changed, 305 insertions(+), 570 deletions(-) diffs (truncated from 1262 to 1000 lines): diff -r b247b1c5531f -r 2b75ee955589 src/njs_fs.c --- a/src/njs_fs.c Wed Jan 22 15:29:47 2020 +0300 +++ b/src/njs_fs.c Mon Jan 20 13:24:09 2020 +0300 @@ -8,37 +8,51 @@ #include +#define njs_fs_magic(calltype, mode) \ + (((mode) << 2) | calltype) + + +typedef enum { + NJS_FS_DIRECT, + NJS_FS_PROMISE, + NJS_FS_CALLBACK, +} njs_fs_calltype_t; + + +typedef enum { + NJS_FS_TRUNC, + NJS_FS_APPEND, +} njs_fs_writemode_t; + + typedef struct { - njs_str_t name; - int value; + njs_str_t name; + int value; } njs_fs_entry_t; +typedef struct { + int errn; + const char *desc; + const char *syscall; +} njs_fs_ioerror_t; + + static njs_int_t njs_fs_read_file(njs_vm_t *vm, njs_value_t *args, - njs_uint_t nargs, njs_index_t unused); -static njs_int_t njs_fs_read_file_sync(njs_vm_t *vm, njs_value_t *args, - njs_uint_t nargs, njs_index_t unused); -static njs_int_t njs_fs_append_file(njs_vm_t *vm, njs_value_t *args, - njs_uint_t nargs, njs_index_t unused); + njs_uint_t nargs, njs_index_t calltype); static njs_int_t njs_fs_write_file(njs_vm_t *vm, njs_value_t *args, - njs_uint_t nargs, njs_index_t unused); -static njs_int_t njs_fs_append_file_sync(njs_vm_t *vm, njs_value_t *args, - njs_uint_t nargs, njs_index_t unused); -static njs_int_t njs_fs_write_file_sync(njs_vm_t *vm, njs_value_t *args, - njs_uint_t nargs, njs_index_t unused); -static njs_int_t njs_fs_write_file_internal(njs_vm_t *vm, njs_value_t *args, - njs_uint_t nargs, int default_flags); -static njs_int_t njs_fs_write_file_sync_internal(njs_vm_t *vm, - njs_value_t *args, njs_uint_t nargs, int default_flags); + njs_uint_t nargs, njs_index_t magic); static njs_int_t njs_fs_rename_sync(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused); -static njs_int_t njs_fs_fd_read(njs_vm_t *vm, njs_value_t *path, int fd, - njs_str_t *data); +static njs_int_t njs_fs_fd_read(njs_vm_t *vm, int fd, njs_str_t *data, + njs_fs_ioerror_t *ioerror); static njs_int_t njs_fs_error(njs_vm_t *vm, const char *syscall, const char *description, njs_value_t *path, int errn, njs_value_t *retval); static int njs_fs_flags(njs_str_t *value); static mode_t njs_fs_mode(njs_value_t *value); +static njs_int_t njs_fs_add_event(njs_vm_t *vm, const njs_value_t *callback, + const njs_value_t *err, const njs_value_t *result); static const njs_value_t njs_fs_errno_string = njs_string("errno"); @@ -70,8 +84,8 @@ static njs_fs_entry_t njs_flags_table[] njs_inline njs_int_t -njs_fs_path_arg(njs_vm_t *vm, const char **dst, - const njs_value_t* src, const njs_str_t *prop_name) +njs_fs_path_arg(njs_vm_t *vm, const char **dst, const njs_value_t* src, + const njs_str_t *prop_name) { if (njs_slow_path(!njs_is_string(src))) { njs_type_error(vm, "\"%V\" must be a string", prop_name); @@ -87,21 +101,33 @@ njs_fs_path_arg(njs_vm_t *vm, const char } +njs_inline void +njs_fs_set_ioerr(njs_fs_ioerror_t *ioerror, int errn, const char *desc, + const char *syscall) +{ + ioerror->errn = errn; + ioerror->desc = desc; + ioerror->syscall = syscall; +} + + static njs_int_t njs_fs_read_file(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, - njs_index_t unused) + njs_index_t calltype) { - int fd, errn, flags; + int fd, flags; u_char *start; size_t size; ssize_t length; njs_str_t flag, encoding, data; njs_int_t ret; - const char *path, *syscall, *description; + const char *path; struct stat sb; - njs_value_t *callback, arguments[3]; + const njs_value_t *callback, *options; + njs_value_t err; njs_object_prop_t *prop; njs_lvlhsh_query_t lhq; + njs_fs_ioerror_t ioerror; ret = njs_fs_path_arg(vm, &path, njs_arg(args, nargs, 1), &njs_str_value("path")); @@ -109,247 +135,28 @@ njs_fs_read_file(njs_vm_t *vm, njs_value return ret; } - if (njs_slow_path(nargs < 3)) { - njs_type_error(vm, "too few arguments"); - return NJS_ERROR; + options = njs_arg(args, nargs, 2); + + if (njs_slow_path(calltype == NJS_FS_CALLBACK)) { + callback = njs_arg(args, nargs, njs_min(nargs - 1, 3)); + if (!njs_is_function(callback)) { + njs_type_error(vm, "\"callback\" must be a function"); + return NJS_ERROR; + } + if (options == callback) { + options = &njs_value_undefined; + } + + } else { + /* GCC complains about uninitialized callback. */ + callback = NULL; } flag.start = NULL; encoding.length = 0; encoding.start = NULL; - if (!njs_is_function(&args[2])) { - if (njs_is_string(&args[2])) { - njs_string_get(&args[2], &encoding); - - } else if (njs_is_object(&args[2])) { - lhq.key_hash = NJS_FLAG_HASH; - lhq.key = njs_str_value("flag"); - lhq.proto = &njs_object_hash_proto; - - ret = njs_lvlhsh_find(njs_object_hash(&args[2]), &lhq); - if (ret == NJS_OK) { - prop = lhq.value; - njs_string_get(&prop->value, &flag); - } - - lhq.key_hash = NJS_ENCODING_HASH; - lhq.key = njs_str_value("encoding"); - lhq.proto = &njs_object_hash_proto; - - ret = njs_lvlhsh_find(njs_object_hash(&args[2]), &lhq); - if (ret == NJS_OK) { - prop = lhq.value; - njs_string_get(&prop->value, &encoding); - } - - } else { - njs_type_error(vm, "Unknown options type " - "(a string or object required)"); - return NJS_ERROR; - } - - if (njs_slow_path(nargs < 4 || !njs_is_function(&args[3]))) { - njs_type_error(vm, "callback must be a function"); - return NJS_ERROR; - } - - callback = &args[3]; - - } else { - if (njs_slow_path(!njs_is_function(&args[2]))) { - njs_type_error(vm, "callback must be a function"); - return NJS_ERROR; - } - - callback = &args[2]; - } - - if (flag.start == NULL) { - flag = njs_str_value("r"); - } - - flags = njs_fs_flags(&flag); - if (njs_slow_path(flags == -1)) { - njs_type_error(vm, "Unknown file open flags: \"%V\"", &flag); - return NJS_ERROR; - } - - if (encoding.length != 0 - && (encoding.length != 4 || memcmp(encoding.start, "utf8", 4) != 0)) - { - njs_type_error(vm, "Unknown encoding: \"%V\"", &encoding); - return NJS_ERROR; - } - - description = NULL; - - /* GCC 4 complains about uninitialized errn and syscall. */ - errn = 0; - syscall = NULL; - - fd = open(path, flags); - if (njs_slow_path(fd < 0)) { - errn = errno; - description = strerror(errno); - syscall = "open"; - goto done; - } - - ret = fstat(fd, &sb); - if (njs_slow_path(ret == -1)) { - errn = errno; - description = strerror(errno); - syscall = "stat"; - goto done; - } - - if (njs_slow_path(!S_ISREG(sb.st_mode))) { - errn = 0; - description = "File is not regular"; - syscall = "stat"; - goto done; - } - - 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; - } - - size = sb.st_size; - - if (njs_fast_path(size != 0)) { - - start = njs_string_alloc(vm, &arguments[2], size, length); - if (njs_slow_path(start == NULL)) { - goto fail; - } - - data.start = start; - data.length = size; - - ret = njs_fs_fd_read(vm, &args[1], fd, &data); - if (ret != NJS_OK) { - goto fail; - } - - start = data.start; - - } else { - /* size of the file is not known in advance. */ - - data.length = 0; - - ret = njs_fs_fd_read(vm, &args[1], fd, &data); - if (ret != NJS_OK) { - goto fail; - } - - size = data.length; - start = data.start; - - ret = njs_string_new(vm, &arguments[2], start, size, length); - if (njs_slow_path(ret != NJS_OK)) { - goto fail; - } - } - - if (encoding.length != 0) { - length = njs_utf8_length(start, size); - - if (length >= 0) { - njs_string_length_set(&arguments[2], length); - - } else { - errn = 0; - description = "Non-UTF8 file, convertion is not implemented"; - syscall = NULL; - goto done; - } - } - -done: - - if (fd != -1) { - (void) close(fd); - } - - if (description != 0) { - (void) njs_fs_error(vm, syscall, description, &args[1], errn, - &arguments[1]); - - njs_set_undefined(&arguments[2]); - - } else { - njs_set_undefined(&arguments[1]); - } - - njs_set_undefined(&arguments[0]); - - ret = njs_function_apply(vm, njs_function(callback), arguments, 3, - &vm->retval); - - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - njs_set_undefined(&vm->retval); - - return NJS_OK; - -fail: - - if (fd != -1) { - (void) close(fd); - } - - return NJS_ERROR; -} - - -static njs_int_t -njs_fs_read_file_sync(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, - njs_index_t unused) -{ - int fd, errn, flags; - u_char *start; - size_t size; - ssize_t length; - njs_str_t flag, encoding, data; - njs_int_t ret; - const char *path, *syscall, *description; - struct stat sb; - njs_object_prop_t *prop; - njs_lvlhsh_query_t lhq; - - ret = njs_fs_path_arg(vm, &path, njs_arg(args, nargs, 1), - &njs_str_value("path")); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - if (njs_slow_path(nargs < 2)) { - njs_type_error(vm, "too few arguments"); - return NJS_ERROR; - } - - flag.start = NULL; - encoding.length = 0; - encoding.start = NULL; - - if (nargs == 3) { + if (njs_slow_path(!njs_is_undefined(options))) { if (njs_is_string(&args[2])) { njs_string_get(&args[2], &encoding); @@ -391,11 +198,6 @@ njs_fs_read_file_sync(njs_vm_t *vm, njs_ return NJS_ERROR; } - path = njs_string_to_c_string(vm, &args[1]); - if (njs_slow_path(path == NULL)) { - return NJS_ERROR; - } - if (encoding.length != 0 && (encoding.length != 4 || memcmp(encoding.start, "utf8", 4) != 0)) { @@ -403,32 +205,22 @@ njs_fs_read_file_sync(njs_vm_t *vm, njs_ return NJS_ERROR; } - description = NULL; - - /* GCC 4 complains about uninitialized errn and syscall. */ - errn = 0; - syscall = NULL; + njs_fs_set_ioerr(&ioerror, 0, NULL, NULL); fd = open(path, flags); if (njs_slow_path(fd < 0)) { - errn = errno; - description = strerror(errno); - syscall = "open"; + njs_fs_set_ioerr(&ioerror, errno, strerror(errno), "open"); goto done; } ret = fstat(fd, &sb); if (njs_slow_path(ret == -1)) { - errn = errno; - description = strerror(errno); - syscall = "stat"; + njs_fs_set_ioerr(&ioerror, errno, strerror(errno), "fstat"); goto done; } if (njs_slow_path(!S_ISREG(sb.st_mode))) { - errn = 0; - description = "File is not regular"; - syscall = "stat"; + njs_fs_set_ioerr(&ioerror, 0, "File is not regular", "stat"); goto done; } @@ -452,7 +244,6 @@ njs_fs_read_file_sync(njs_vm_t *vm, njs_ size = sb.st_size; if (njs_fast_path(size != 0)) { - start = njs_string_alloc(vm, &vm->retval, size, length); if (njs_slow_path(start == NULL)) { goto fail; @@ -461,8 +252,12 @@ njs_fs_read_file_sync(njs_vm_t *vm, njs_ data.start = start; data.length = size; - ret = njs_fs_fd_read(vm, &args[1], fd, &data); + ret = njs_fs_fd_read(vm, fd, &data, &ioerror); if (ret != NJS_OK) { + if (ioerror.desc != NULL) { + goto done; + } + goto fail; } @@ -473,8 +268,12 @@ njs_fs_read_file_sync(njs_vm_t *vm, njs_ data.length = 0; - ret = njs_fs_fd_read(vm, &args[1], fd, &data); + ret = njs_fs_fd_read(vm, fd, &data, &ioerror); if (ret != NJS_OK) { + if (ioerror.desc != NULL) { + goto done; + } + goto fail; } @@ -494,9 +293,9 @@ njs_fs_read_file_sync(njs_vm_t *vm, njs_ njs_string_length_set(&vm->retval, length); } else { - errn = 0; - description = "Non-UTF8 file, convertion is not implemented"; - syscall = NULL; + njs_fs_set_ioerr(&ioerror, 0, + "Non-UTF8 file, convertion is not implemented", + NULL); goto done; } } @@ -507,12 +306,46 @@ done: (void) close(fd); } - if (description != 0) { - return njs_fs_error(vm, syscall, description, &args[1], errn, - &vm->retval); + if (njs_fast_path(calltype == NJS_FS_DIRECT)) { + if (njs_slow_path(ioerror.desc != NULL)) { + (void) njs_fs_error(vm, ioerror.syscall, ioerror.desc, + &args[1], ioerror.errn, &vm->retval); + return NJS_ERROR; + } + + return NJS_OK; + } + + if (calltype == NJS_FS_PROMISE) { + njs_internal_error(vm, "promise callback is not implemented"); + return NJS_ERROR; } - return NJS_OK; + if (calltype == NJS_FS_CALLBACK) { + if (njs_slow_path(ioerror.desc)) { + ret = njs_fs_error(vm, ioerror.syscall, ioerror.desc, + &args[1], ioerror.errn, &err); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + njs_set_undefined(&vm->retval); + + } else { + njs_set_undefined(&err); + } + + ret = njs_fs_add_event(vm, callback, &err, &vm->retval); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + njs_set_undefined(&vm->retval); + return NJS_OK; + } + + njs_internal_error(vm, "invalid calltype"); + return NJS_ERROR; fail: @@ -525,50 +358,20 @@ fail: static njs_int_t -njs_fs_append_file(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, - njs_index_t unused) -{ - return njs_fs_write_file_internal(vm, args, nargs, - O_APPEND | O_CREAT | O_WRONLY); -} - - -static njs_int_t njs_fs_write_file(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, - njs_index_t unused) + njs_index_t magic) { - return njs_fs_write_file_internal(vm, args, nargs, - O_TRUNC | O_CREAT | O_WRONLY); -} - - -static njs_int_t njs_fs_append_file_sync(njs_vm_t *vm, njs_value_t *args, - njs_uint_t nargs, njs_index_t unused) -{ - return njs_fs_write_file_sync_internal(vm, args, nargs, - O_APPEND | O_CREAT | O_WRONLY); -} - - -static njs_int_t njs_fs_write_file_sync(njs_vm_t *vm, njs_value_t *args, - njs_uint_t nargs, njs_index_t unused) -{ - return njs_fs_write_file_sync_internal(vm, args, nargs, - O_TRUNC | O_CREAT | O_WRONLY); -} - - -static njs_int_t njs_fs_write_file_internal(njs_vm_t *vm, njs_value_t *args, - njs_uint_t nargs, int default_flags) -{ - int fd, errn, flags; + int fd, flags; u_char *p, *end; mode_t md; ssize_t n; njs_str_t data, flag, encoding; njs_int_t ret; - const char *path, *syscall, *description; - njs_value_t *callback, *mode, arguments[2]; + const char *path; + njs_value_t *mode, err; + njs_fs_calltype_t calltype; + const njs_value_t *callback, *options; + njs_fs_ioerror_t ioerror; njs_object_prop_t *prop; njs_lvlhsh_query_t lhq; @@ -578,14 +381,24 @@ static njs_int_t njs_fs_write_file_inter return ret; } - if (njs_slow_path(nargs < 4)) { - njs_type_error(vm, "too few arguments"); + if (njs_slow_path(!njs_is_string(njs_arg(args, nargs, 2)))) { + njs_type_error(vm, "\"data\" must be a string"); return NJS_ERROR; } - if (njs_slow_path(!njs_is_string(&args[2]))) { - njs_type_error(vm, "data must be a string"); - return NJS_ERROR; + callback = NULL; + calltype = magic & 3; + options = njs_arg(args, nargs, 3); + + if (njs_slow_path(calltype == NJS_FS_CALLBACK)) { + callback = njs_arg(args, nargs, njs_min(nargs - 1, 4)); + if (!njs_is_function(callback)) { + njs_type_error(vm, "\"callback\" must be a function"); + return NJS_ERROR; + } + if (options == callback) { + options = &njs_value_undefined; + } } mode = NULL; @@ -595,191 +408,7 @@ static njs_int_t njs_fs_write_file_inter encoding.length = 0; encoding.start = NULL; - if (!njs_is_function(&args[3])) { - if (njs_is_string(&args[3])) { - njs_string_get(&args[3], &encoding); - - } else if (njs_is_object(&args[3])) { - lhq.key_hash = NJS_FLAG_HASH; - lhq.key = njs_str_value("flag"); - lhq.proto = &njs_object_hash_proto; - - ret = njs_lvlhsh_find(njs_object_hash(&args[3]), &lhq); - if (ret == NJS_OK) { - prop = lhq.value; - njs_string_get(&prop->value, &flag); - } - - lhq.key_hash = NJS_ENCODING_HASH; - lhq.key = njs_str_value("encoding"); - lhq.proto = &njs_object_hash_proto; - - ret = njs_lvlhsh_find(njs_object_hash(&args[3]), &lhq); - if (ret == NJS_OK) { - prop = lhq.value; - njs_string_get(&prop->value, &encoding); - } - - lhq.key_hash = NJS_MODE_HASH; - lhq.key = njs_str_value("mode"); - lhq.proto = &njs_object_hash_proto; - - ret = njs_lvlhsh_find(njs_object_hash(&args[3]), &lhq); - if (ret == NJS_OK) { - prop = lhq.value; - mode = &prop->value; - } - - } else { - njs_type_error(vm, "Unknown options type " - "(a string or object required)"); - return NJS_ERROR; - } - - if (njs_slow_path(nargs < 5 || !njs_is_function(&args[4]))) { - njs_type_error(vm, "callback must be a function"); - return NJS_ERROR; - } - - callback = &args[4]; - - } else { - if (njs_slow_path(!njs_is_function(&args[3]))) { - njs_type_error(vm, "callback must be a function"); - return NJS_ERROR; - } - - callback = &args[3]; - } - - if (flag.start != NULL) { - flags = njs_fs_flags(&flag); - if (njs_slow_path(flags == -1)) { - njs_type_error(vm, "Unknown file open flags: \"%V\"", &flag); - return NJS_ERROR; - } - - } else { - flags = default_flags; - } - - if (mode != NULL) { - md = njs_fs_mode(mode); - - } else { - md = 0666; - } - - if (encoding.length != 0 - && (encoding.length != 4 || memcmp(encoding.start, "utf8", 4) != 0)) - { - njs_type_error(vm, "Unknown encoding: \"%V\"", &encoding); - return NJS_ERROR; - } - - description = NULL; - - /* GCC 4 complains about uninitialized errn and syscall. */ - errn = 0; - syscall = NULL; - - fd = open(path, flags, md); - if (njs_slow_path(fd < 0)) { - errn = errno; - description = strerror(errno); - syscall = "open"; - goto done; - } - - njs_string_get(&args[2], &data); - - p = data.start; - end = p + data.length; - - while (p < end) { - n = write(fd, p, end - p); - if (njs_slow_path(n == -1)) { - if (errno == EINTR) { - continue; - } - - errn = errno; - description = strerror(errno); - syscall = "write"; - goto done; - } - - p += n; - } - -done: - - if (fd != -1) { - (void) close(fd); - } - - if (description != 0) { - (void) njs_fs_error(vm, syscall, description, &args[1], errn, - &arguments[1]); - - } else { - njs_set_undefined(&arguments[1]); - } - - njs_set_undefined(&arguments[0]); - - ret = njs_function_apply(vm, njs_function(callback), arguments, 2, - &vm->retval); - - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - njs_set_undefined(&vm->retval); - - return NJS_OK; -} - - -static njs_int_t -njs_fs_write_file_sync_internal(njs_vm_t *vm, njs_value_t *args, - njs_uint_t nargs, int default_flags) -{ - int fd, errn, flags; - u_char *p, *end; - mode_t md; - ssize_t n; - njs_str_t data, flag, encoding; - njs_int_t ret; - const char *path, *syscall, *description; - njs_value_t *mode; - njs_object_prop_t *prop; - njs_lvlhsh_query_t lhq; - - ret = njs_fs_path_arg(vm, &path, njs_arg(args, nargs, 1), - &njs_str_value("path")); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - if (njs_slow_path(nargs < 3)) { - njs_type_error(vm, "too few arguments"); - return NJS_ERROR; - } - - if (njs_slow_path(!njs_is_string(&args[2]))) { - njs_type_error(vm, "data must be a string"); - return NJS_ERROR; - } - - mode = NULL; - /* GCC complains about uninitialized flag.length. */ - flag.length = 0; - flag.start = NULL; - encoding.length = 0; - encoding.start = NULL; - - if (nargs == 4) { + if (njs_slow_path(!njs_is_undefined(options))) { if (njs_is_string(&args[3])) { njs_string_get(&args[3], &encoding); @@ -829,7 +458,8 @@ njs_fs_write_file_sync_internal(njs_vm_t } } else { - flags = default_flags; + flags = O_CREAT | O_WRONLY; + flags |= ((magic >> 2) == NJS_FS_APPEND) ? O_APPEND : O_TRUNC; } if (mode != NULL) { @@ -846,17 +476,11 @@ njs_fs_write_file_sync_internal(njs_vm_t return NJS_ERROR; } - description = NULL; - - /* GCC 4 complains about uninitialized errn and syscall. */ - errn = 0; - syscall = NULL; + njs_fs_set_ioerr(&ioerror, 0, NULL, NULL); fd = open(path, flags, md); if (njs_slow_path(fd < 0)) { - errn = errno; - description = strerror(errno); - syscall = "open"; + njs_fs_set_ioerr(&ioerror, errno, strerror(errno), "open"); goto done; } @@ -872,9 +496,7 @@ njs_fs_write_file_sync_internal(njs_vm_t continue; } - errn = errno; - description = strerror(errno); - syscall = "write"; + njs_fs_set_ioerr(&ioerror, errno, strerror(errno), "write"); goto done; } @@ -887,15 +509,45 @@ done: (void) close(fd); } - if (description != 0) { - return njs_fs_error(vm, syscall, description, &args[1], errn, - &vm->retval); + if (njs_fast_path(calltype == NJS_FS_DIRECT)) { + if (njs_slow_path(ioerror.desc != NULL)) { + (void) njs_fs_error(vm, ioerror.syscall, ioerror.desc, &args[1], + ioerror.errn, &vm->retval); + return NJS_ERROR; + } - } else { njs_set_undefined(&vm->retval); + return NJS_OK; + } + + if (calltype == NJS_FS_PROMISE) { + njs_internal_error(vm, "not implemented"); + return NJS_ERROR; } - return NJS_OK; + if (calltype == NJS_FS_CALLBACK) { + if (ioerror.desc != NULL) { + ret = njs_fs_error(vm, ioerror.syscall, ioerror.desc, &args[1], + ioerror.errn, &err); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + } else { + njs_set_undefined(&err); + } + + ret = njs_fs_add_event(vm, callback, &err, NULL); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + njs_set_undefined(&vm->retval); + return NJS_OK; + } + + njs_internal_error(vm, "invalid calltype"); + return NJS_ERROR; } @@ -920,8 +572,9 @@ njs_fs_rename_sync(njs_vm_t *vm, njs_val ret = rename(old_path, new_path); if (njs_slow_path(ret != 0)) { - return njs_fs_error(vm, "rename", strerror(errno), NULL, errno, + (void) njs_fs_error(vm, "rename", strerror(errno), NULL, errno, &vm->retval); + return NJS_ERROR; } njs_set_undefined(&vm->retval); @@ -931,7 +584,8 @@ njs_fs_rename_sync(njs_vm_t *vm, njs_val static njs_int_t -njs_fs_fd_read(njs_vm_t *vm, njs_value_t *path, int fd, njs_str_t *data) +njs_fs_fd_read(njs_vm_t *vm, int fd, njs_str_t *data, + njs_fs_ioerror_t *ioerror) { u_char *p, *end, *start; size_t size; @@ -956,8 +610,8 @@ njs_fs_fd_read(njs_vm_t *vm, njs_value_t n = read(fd, p, end - p); if (njs_slow_path(n < 0)) { - return njs_fs_error(vm, "read", strerror(errno), path, errno, - &vm->retval); + njs_fs_set_ioerr(ioerror, errno, strerror(errno), "read"); + return NJS_DECLINED; } p += n; @@ -1084,7 +738,7 @@ njs_fs_error(njs_vm_t *vm, const char *s njs_set_object(retval, error); - return NJS_ERROR; + return NJS_OK; } @@ -1127,6 +781,61 @@ njs_fs_mode(njs_value_t *value) } +static njs_int_t +njs_fs_add_event(njs_vm_t *vm, const njs_value_t *callback, + const njs_value_t *err, const njs_value_t *result) +{ + njs_int_t nargs; + njs_event_t *event; + njs_vm_ops_t *ops; + + nargs = (result == NULL) ? 1 : 2; + + ops = vm->options.ops; + if (njs_slow_path(ops == NULL)) { + njs_internal_error(vm, "not supported by host environment"); + return NJS_ERROR; + } + + event = njs_mp_alloc(vm->mem_pool, sizeof(njs_event_t)); + if (njs_slow_path(event == NULL)) { + goto memory_error; + } + + event->destructor = ops->clear_timer; + event->function = njs_function(callback); + event->nargs = nargs; + event->once = 1; + event->posted = 0; + + event->args = njs_mp_alloc(vm->mem_pool, sizeof(njs_value_t) * nargs); + if (njs_slow_path(event->args == NULL)) { + goto memory_error; + } + + /* GC: retain */ + event->args[0] = *err; + + if (nargs == 2) { + event->args[1] = *result; + } + + event->host_event = ops->set_timer(vm->external, 0, event); + if (njs_slow_path(event->host_event == NULL)) { + njs_internal_error(vm, "set_timer() failed"); + return NJS_ERROR; + } + + return njs_add_event(vm, event); + From mdounin at mdounin.ru Thu Jan 23 19:29:31 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 23 Jan 2020 22:29:31 +0300 Subject: [PATCH] Fix for the HT on request headers problem (#1752) In-Reply-To: References: Message-ID: <20200123192931.GI12894@mdounin.ru> Hello! On Mon, Jan 20, 2020 at 05:29:25PM +0200, mstavrev at gmail.com wrote: > # HG changeset patch > # User Marin Stavrev > # Date 1579526641 -7200 > # Mon Jan 20 15:24:01 2020 +0200 > # Node ID bf238762fdaf03383c2f3c3718c401e6141e3935 > # Parent 6439ef81e37dfccfc3a8c57fed278bf56014ef39 > Fix for the HT on request headers problem (#1752) > > When client send HTTP request with a header of Content-Length that starts with > horizontal tab character (HT=0x09), Nginx responds with HTTP 400 Bad Request. > According to HTTP RFC2616 section 4.2, "... The field value MAY be preceded by > any amount of LWS, though a single SP is preferred.". The difinition of LWS is: > > LWS = [CRLF] 1*( SP | HT ) > > So a header such as the following should be processed fine: > > Content-Length:<0x09>110\r\n Note that RFC 2616 you are quoting was obsoleted by RFC 7230. In particular, line folding (the "[CRLF]" part of the grammar) is obsolete and must not be generated. Modern syntax rules to refer to would be RFC 7230, section 3.2: header-field = field-name ":" OWS field-value OWS Where OWS is defined in section 3.2.3 as: OWS = *( SP / HTAB ) ; optional whitespace and text says that "a sender SHOULD generate the optional whitespace as a single SP" where an optional whitespace can improve readability. However, we haven't seen any interoperability problems due to no HTAB support in nginx. As such, instead of adding HTAB support it might be better to keep parsing strict. [...] -- Maxim Dounin http://mdounin.ru/ From martin.grigorov at gmail.com Thu Jan 23 20:26:46 2020 From: martin.grigorov at gmail.com (Martin Grigorov) Date: Thu, 23 Jan 2020 22:26:46 +0200 Subject: Is Nginx being tested on ARM architecture ? In-Reply-To: References: Message-ID: Hello Nginx developers, I was not able to find any information what continous integration (CI) Nginx project is using. I'd like to ask whether you run a CI server/agent on ARM 32/64 architecture ? At my job we are going to use more and more ARM64 based servers and we would like to know whether this is a safe bet with Nginx. At https://nginx.org/en/index.html #tested_os_and_platforms I see " Linux 3 ? 4 / armv6l, armv7l, aarch64, ppc64le;". Does that mean that Linux 5.x is not supported/tested or just that this documentation page needs to be updated ? Thank you! Regards, Martin Grigorov -------------- next part -------------- An HTML attachment was scrubbed... URL: From mstavrev at gmail.com Fri Jan 24 07:07:49 2020 From: mstavrev at gmail.com (Marin Stavrev) Date: Fri, 24 Jan 2020 09:07:49 +0200 Subject: [PATCH] Fix for the HT on request headers problem (#1752) In-Reply-To: <20200123192931.GI12894@mdounin.ru> References: <20200123192931.GI12894@mdounin.ru> Message-ID: Hello, I can understand your point, but still RFC 7230 defines OWS to allow HTAB and the therm used to suggest a single SP is SHOULD (recommendation) not MUST (mandatory). Thus, Nginx is not fully compliant. I would never post such a change if it wasn't really needed - I am not pushing for this change just out of love for RFC compliance.I have this issue causing problems with some Chinese IP cameras and NVRs that are generating such headers. I understand this is quite rare, and to be frank this is the only case I had personally seen such a (lousy) HTTP implementation. Unfortunately, I don't have any control over their FW and thus needed this fix on the server side. I know it does not matter much, but both Apache and Microsoft IIS handle such headers as expected and do not treat the request as a bad one as Nginx currently does. Best Regards M. Stavrev On Thu, Jan 23, 2020 at 9:29 PM Maxim Dounin wrote: > Hello! > > On Mon, Jan 20, 2020 at 05:29:25PM +0200, mstavrev at gmail.com wrote: > > > # HG changeset patch > > # User Marin Stavrev > > # Date 1579526641 -7200 > > # Mon Jan 20 15:24:01 2020 +0200 > > # Node ID bf238762fdaf03383c2f3c3718c401e6141e3935 > > # Parent 6439ef81e37dfccfc3a8c57fed278bf56014ef39 > > Fix for the HT on request headers problem (#1752) > > > > When client send HTTP request with a header of Content-Length that > starts with > > horizontal tab character (HT=0x09), Nginx responds with HTTP 400 Bad > Request. > > According to HTTP RFC2616 section 4.2, "... The field value MAY be > preceded by > > any amount of LWS, though a single SP is preferred.". The difinition of > LWS is: > > > > LWS = [CRLF] 1*( SP | HT ) > > > > So a header such as the following should be processed fine: > > > > Content-Length:<0x09>110\r\n > > Note that RFC 2616 you are quoting was obsoleted by RFC 7230. In > particular, line folding (the "[CRLF]" part of the grammar) is > obsolete and must not be generated. Modern syntax rules to refer > to would be RFC 7230, section 3.2: > > header-field = field-name ":" OWS field-value OWS > > Where OWS is defined in section 3.2.3 as: > > OWS = *( SP / HTAB ) > ; optional whitespace > > and text says that "a sender SHOULD generate the optional > whitespace as a single SP" where an optional whitespace can > improve readability. > > However, we haven't seen any interoperability problems due to no > HTAB support in nginx. As such, instead of adding HTAB support it > might be better to keep parsing strict. > > [...] > > -- > Maxim Dounin > http://mdounin.ru/ > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -------------- next part -------------- An HTML attachment was scrubbed... URL: From thresh at nginx.com Fri Jan 24 10:45:05 2020 From: thresh at nginx.com (Konstantin Pavlov) Date: Fri, 24 Jan 2020 13:45:05 +0300 Subject: Is Nginx being tested on ARM architecture ? In-Reply-To: References: Message-ID: <22a46dc6-981e-1675-545e-0a011ac830e5@nginx.com> Hi Martin, Hope all is well. 23.01.2020 23:26, Martin Grigorov wrote: > Hello Nginx developers, > > I was not able to find any information what continous integration (CI) > Nginx project is using. > I'd like to ask whether you run a CI server/agent on ARM 32/64 > architecture ? Indeed there is no public information on our CI system, and the page you linked rather specifies that we were able to build and test nginx under those targets. Nevertheless, ARM64/aarch64 is indeed a part of our CI, and every nginx/njs/unit revision is built and tested the same way as other supported architectures. Among CI builds, we provide aarch64/ARM64 packages for select linux distributions: http://nginx.org/en/linux_packages.html#distributions . We don't have a CI target for a 32bit arm since its marketshare on server side is pretty much zero and for any real usage 64bit machines are the way to go. > At my job we are going to use more and more ARM64 based servers and we > would like to know whether this is a safe bet with Nginx. > At?https://nginx.org/en/index.html > #tested_os_and_platforms > I see " Linux 3 ? 4 / armv6l, armv7l, aarch64, ppc64le;". Does that mean > that Linux 5.x is not supported/tested or just that this documentation > page needs to be updated ? At the moment we have no targets in our CI system that run aarch64 under Linux kernel 5.x - currently tested are Ubuntu 16.04 (Linux 4.15), Ubuntu 18.04 (also Linux 4.15) and Amazon Linux 2 (Linux 4.14). It seems Ubuntu 20.04 will be released with 5.3.0 this April, so when we have it in our CI it'll be mentioned on the page as well. To sum it up, aarch64 is a good choice wrt nginx usage these days, and it's safe to assume it's not going anywhere. Have a good one, -- Konstantin Pavlov https://www.nginx.com/ From martin.grigorov at gmail.com Fri Jan 24 11:26:05 2020 From: martin.grigorov at gmail.com (Martin Grigorov) Date: Fri, 24 Jan 2020 13:26:05 +0200 Subject: Is Nginx being tested on ARM architecture ? In-Reply-To: <22a46dc6-981e-1675-545e-0a011ac830e5@nginx.com> References: <22a46dc6-981e-1675-545e-0a011ac830e5@nginx.com> Message-ID: Thank you for the detailed answer, Konstantin! Keep the good work! Martin On Fri, Jan 24, 2020 at 12:45 PM Konstantin Pavlov wrote: > Hi Martin, > > Hope all is well. > > 23.01.2020 23:26, Martin Grigorov wrote: > > Hello Nginx developers, > > > > I was not able to find any information what continous integration (CI) > > Nginx project is using. > > I'd like to ask whether you run a CI server/agent on ARM 32/64 > > architecture ? > > Indeed there is no public information on our CI system, and the page you > linked rather specifies that we were able to build and test nginx under > those targets. > > Nevertheless, ARM64/aarch64 is indeed a part of our CI, and every > nginx/njs/unit revision is built and tested the same way as other > supported architectures. Among CI builds, we provide aarch64/ARM64 > packages for select linux distributions: > http://nginx.org/en/linux_packages.html#distributions . > > We don't have a CI target for a 32bit arm since its marketshare on > server side is pretty much zero and for any real usage 64bit machines > are the way to go. > > > At my job we are going to use more and more ARM64 based servers and we > > would like to know whether this is a safe bet with Nginx. > > At https://nginx.org/en/index.html > > >#tested_os_and_platforms > > I see " Linux 3 ? 4 / armv6l, armv7l, aarch64, ppc64le;". Does that mean > > that Linux 5.x is not supported/tested or just that this documentation > > page needs to be updated ? > > At the moment we have no targets in our CI system that run aarch64 under > Linux kernel 5.x - currently tested are Ubuntu 16.04 (Linux 4.15), > Ubuntu 18.04 (also Linux 4.15) and Amazon Linux 2 (Linux 4.14). It > seems Ubuntu 20.04 will be released with 5.3.0 this April, so when we > have it in our CI it'll be mentioned on the page as well. > > To sum it up, aarch64 is a good choice wrt nginx usage these days, and > it's safe to assume it's not going anywhere. > > Have a good one, > > -- > Konstantin Pavlov > https://www.nginx.com/ > -------------- next part -------------- An HTML attachment was scrubbed... URL: From aidan.kodi at gmail.com Fri Jan 24 22:17:31 2020 From: aidan.kodi at gmail.com (Aidan Carson) Date: Fri, 24 Jan 2020 14:17:31 -0800 Subject: limit_req_zone Documentation Wrong Message-ID: Hello, I believe the documentation for the limit_req_zone directive on this page is wrong: http://nginx.org/en/docs/http/ngx_http_limit_req_module.html It says that a rate parameter is not optional, but it is. The directive requires at least three parameters, but limit_req_zone $binary_remote_addr zone=limit:64k sync; or limit_req_zone $binary_remote_addr zone=limit:64k zone=limit:64k; are valid, omitting the rate. I see in the code that the default is 1r/s. Perhaps updating the documentation to list the default would be good, or changing the code to have the rate be required. Thank you, Aidan Carson -------------- next part -------------- An HTML attachment was scrubbed... URL: From val.kulkov at gmail.com Tue Jan 28 18:16:49 2020 From: val.kulkov at gmail.com (Val Kulkov) Date: Tue, 28 Jan 2020 13:16:49 -0500 Subject: trac is offline Message-ID: https://trac.nginx.org/ produces "502 Bad Gateway". Can someone look into that please? From val.kulkov at gmail.com Thu Jan 30 03:26:29 2020 From: val.kulkov at gmail.com (Val Kulkov) Date: Wed, 29 Jan 2020 22:26:29 -0500 Subject: submitting a bug report Message-ID: The "How to report bug" page at trac.nginx.org says: "You need to authorize with Google, GitHub, StackExchange or Yandex to submit bug report." I have logged in to Trac with my GitHub account. I am seeing "logged in as Val Kulkov" in the top line of the page. But there is no way to submit a bug report! There is no button, no link, nothing. I can only see reports, but I cannot open a new ticket. Is there some problem with the Trac server [again]? Can someone check what is going on please? Thanks. From shanira14 at gmail.com Fri Jan 31 09:06:54 2020 From: shanira14 at gmail.com (Shani Ranasinghe) Date: Fri, 31 Jan 2020 14:36:54 +0530 Subject: Does NJS support reg ex positive look behinds? Message-ID: Hi, I would like to know if njs supports regex positive look behinds. I have written a script in perl and would like to convert it to njs. The reg ex I have in perl is "((?<=[a-z])(?=[A-Z])(?!ID)(?!^Open$)|(?<=ABC)|(?<=API)(?=[A-Z])|(?=Connect))" This would give the following outputs. *Inputs and expected outputs* are *listed below* in the format *Input -> Expected Output* 1. InstallAndSetup -> install-and-setup 2. DeployingABCDefGhijk -> deploying-abc-def-ghijk (assuming abc is a noun that is frequently used) 3. OpenIDConnect -> openid-connect 4. OAuth2Scopes->oauth2-scopes 5. APISecurity -> api-security I would like to know if there's a way to achieve this with njs? Thank you in advance. Regards, Shani. -------------- next part -------------- An HTML attachment was scrubbed... URL: From xeioex at nginx.com Fri Jan 31 13:02:11 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 31 Jan 2020 16:02:11 +0300 Subject: Does NJS support reg ex positive look behinds? In-Reply-To: References: Message-ID: On 31.01.2020 12:06, Shani Ranasinghe wrote: > Hi, > I would like to know if njs supports regex positive look behinds. > I have written a script in perl and would like to convert it to njs. The > reg ex I have in perl is > "((?<=[a-z])(?=[A-Z])(?!ID)(?!^Open$)|(?<=ABC)|(?<=API)(?=[A-Z])|(?=Connect))" > This would give the following outputs. > > *Inputs and expected outputs* are *listed below* in the format *Input -> > Expected Output* > > 1. > > InstallAndSetup -> install-and-setup > > 2. > > DeployingABCDefGhijk -> deploying-abc-def-ghijk (assuming abc is a > noun that is frequently used) > > 3. OpenIDConnect -> openid-connect > 4. OAuth2Scopes->oauth2-scopes > 5. APISecurity -> api-security > > I would like to know if there's a way to achieve this with njs? > > Thank you in advance. > Regards, > Shani. Hi Shani, njs uses libpcre for regexp which supports positive look behinds (but only fixed length lookbehind) compare (using njs CLI, which is installed with official njs packet) : >> (new RegExp("(?<=[A-Z]+)(abc)")).exec('Aabc') : Thrown: : SyntaxError: pcre_compile("(?<=[A-Z]+)(abc)") failed: lookbehind assertion is not fixed length at ")(abc)" : at RegExp.prototype.constructor (native) : at main (native) with : >> (new RegExp("(?<=[A-Z])(abc)")).exec('Aabc') : [ : 'abc', : 'abc' : ] > I would like to know if there's a way to achieve this with njs? Almost everything is possible, the question is what you are trying to do. Converting CamelCase to kebab-case? You may want to use something like this: : >> function camelCaseToDash(s) { return s.replace(/([A-Za-z0-9])([A-Z][a-z])/g, '$1-$2').toLowerCase() } : undefined : >> function normalize(s) {return s.replace(/(API|OAuth|ABC)/g, (m)=>`${m[0]}${m.substring(1).toLowerCase()}`)} : undefined : >> ['InstallAndSetup', 'DeployingABCDefGhijk', 'OpenIDConnect', 'OAuth2Scopes', : 'APISecurity'].map(normalize).map(camelCaseToDash) : [ : 'install-and-setup', : 'deploying-abc-def-ghijk', : 'openid-connect', : 'oauth2-scopes', : 'api-security' : ] > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > From val.kulkov at gmail.com Fri Jan 31 15:38:57 2020 From: val.kulkov at gmail.com (Val Kulkov) Date: Fri, 31 Jan 2020 10:38:57 -0500 Subject: submitting a bug report In-Reply-To: References: Message-ID: Some futher information on the problem reported earlier. On attempting to login to Trac, I am getting the following today: Oops? Trac detected an internal error: InvalidClientSecretsError: ('Error opening file', '', 'No such file or directory', 2) There was an internal error in Trac. It is recommended that you notify your local Trac administrator with the information needed to reproduce the issue. To that end, you could a ticket. The action that triggered the error was: GET: /login TracGuide ? The Trac User and Administration Guide On Wed, 29 Jan 2020 at 22:26, Val Kulkov wrote: > > The "How to report bug" page at trac.nginx.org says: > > "You need to authorize with Google, GitHub, StackExchange or Yandex to > submit bug report." > > I have logged in to Trac with my GitHub account. I am seeing "logged > in as Val Kulkov" in the top line of the page. But there is no way to > submit a bug report! There is no button, no link, nothing. I can only > see reports, but I cannot open a new ticket. > > Is there some problem with the Trac server [again]? Can someone check > what is going on please? Thanks.