diff options
author | nginx <nginx@nginx.org> | 2013-09-17 13:36:21 +0000 |
---|---|---|
committer | Jon Kolb <jon@b0g.us> | 2013-09-17 13:36:21 +0000 |
commit | c6e358d8a8b9773f4244cca3fb0f4dff1a93c838 (patch) | |
tree | d521395e241ea7525b0743b76c97913319c6fda8 | |
parent | b4f0587460c1cec132bbf547b658057a674aa94e (diff) | |
download | nginx-1.5.5.tar.gz |
Changes with nginx 1.5.5 17 Sep 2013v1.5.5
*) Change: now nginx assumes HTTP/1.0 by default if it is not able to
detect protocol reliably.
*) Feature: the "disable_symlinks" directive now uses O_PATH on Linux.
*) Feature: now nginx uses EPOLLRDHUP events to detect premature
connection close by clients if the "epoll" method is used.
*) Bugfix: in the "valid_referers" directive if the "server_names"
parameter was used.
*) Bugfix: the $request_time variable did not work in nginx/Windows.
*) Bugfix: in the "image_filter" directive.
Thanks to Lanshun Zhou.
*) Bugfix: OpenSSL 1.0.1f compatibility.
Thanks to Piotr Sikora.
49 files changed, 553 insertions, 160 deletions
@@ -1,4 +1,26 @@ +Changes with nginx 1.5.5 17 Sep 2013 + + *) Change: now nginx assumes HTTP/1.0 by default if it is not able to + detect protocol reliably. + + *) Feature: the "disable_symlinks" directive now uses O_PATH on Linux. + + *) Feature: now nginx uses EPOLLRDHUP events to detect premature + connection close by clients if the "epoll" method is used. + + *) Bugfix: in the "valid_referers" directive if the "server_names" + parameter was used. + + *) Bugfix: the $request_time variable did not work in nginx/Windows. + + *) Bugfix: in the "image_filter" directive. + Thanks to Lanshun Zhou. + + *) Bugfix: OpenSSL 1.0.1f compatibility. + Thanks to Piotr Sikora. + + Changes with nginx 1.5.4 27 Aug 2013 *) Change: the "js" extension MIME type has been changed to diff --git a/CHANGES.ru b/CHANGES.ru index bbc8b908c..de89fa996 100644 --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,27 @@ +Изменения в nginx 1.5.5 17.09.2013 + + *) Изменение: теперь nginx по умолчанию использует HTTP/1.0, если точно + определить протокол не удалось. + + *) Добавление: директива disable_symlinks теперь использует O_PATH на + Linux. + + *) Добавление: для определения того, что клиент закрыл соединение, при + использовании метода epoll теперь используются события EPOLLRDHUP. + + *) Исправление: в директиве valid_referers при использовании параметра + server_names. + + *) Исправление: переменная $request_time не работала в nginx/Windows. + + *) Исправление: в директиве image_filter. + Спасибо Lanshun Zhou. + + *) Исправление: совместимость с OpenSSL 1.0.1f. + Спасибо Piotr Sikora. + + Изменения в nginx 1.5.4 27.08.2013 *) Изменение: MIME-тип для расширения js изменён на diff --git a/auto/cc/conf b/auto/cc/conf index 8027b9805..edc6d74dd 100644 --- a/auto/cc/conf +++ b/auto/cc/conf @@ -43,6 +43,29 @@ if test -n "$CFLAGS"; then ngx_include_opt="-I" ;; + sunc) + + case "$NGX_MACHINE" in + + i86pc) + NGX_AUX=" src/os/unix/ngx_sunpro_x86.il" + ;; + + sun4u | sun4v) + NGX_AUX=" src/os/unix/ngx_sunpro_sparc64.il" + ;; + + esac + + case $CPU in + + amd64) + NGX_AUX=" src/os/unix/ngx_sunpro_amd64.il" + ;; + + esac + ;; + esac else diff --git a/auto/cc/owc b/auto/cc/owc index 22eb4c125..a063aa341 100644 --- a/auto/cc/owc +++ b/auto/cc/owc @@ -65,10 +65,10 @@ have=NGX_HAVE_C99_VARIADIC_MACROS . auto/have # the precompiled headers -CORE_DEPS="$CORE_DEPS $NGX_OBJS/ngx_config.pch" -NGX_PCH="$NGX_OBJS/ngx_config.pch" -NGX_BUILD_PCH="-fhq=$NGX_OBJS/ngx_config.pch" -NGX_USE_PCH="-fh=$NGX_OBJS/ngx_config.pch" +#CORE_DEPS="$CORE_DEPS $NGX_OBJS/ngx_config.pch" +#NGX_PCH="$NGX_OBJS/ngx_config.pch" +#NGX_BUILD_PCH="-fhq=$NGX_OBJS/ngx_config.pch" +#NGX_USE_PCH="-fh=$NGX_OBJS/ngx_config.pch" # the link flags, built target is NT GUI mode application diff --git a/auto/lib/openssl/conf b/auto/lib/openssl/conf index 528ee1794..a65815f63 100644 --- a/auto/lib/openssl/conf +++ b/auto/lib/openssl/conf @@ -33,6 +33,10 @@ if [ $OPENSSL != NONE ]; then CORE_LIBS="$CORE_LIBS $OPENSSL/.openssl/lib/libssl.a" CORE_LIBS="$CORE_LIBS $OPENSSL/.openssl/lib/libcrypto.a" CORE_LIBS="$CORE_LIBS $NGX_LIBDL" + + if [ "$NGX_PLATFORM" = win32 ]; then + CORE_LIBS="$CORE_LIBS -lgdi32 -lcrypt32 -lws2_32" + fi ;; esac diff --git a/auto/lib/pcre/conf b/auto/lib/pcre/conf index 345860053..939f01b77 100644 --- a/auto/lib/pcre/conf +++ b/auto/lib/pcre/conf @@ -73,6 +73,11 @@ if [ $PCRE != NONE ]; then *) have=NGX_PCRE . auto/have + + if [ "$NGX_PLATFORM" = win32 ]; then + have=PCRE_STATIC . auto/have + fi + CORE_DEPS="$CORE_DEPS $PCRE/pcre.h" LINK_DEPS="$LINK_DEPS $PCRE/.libs/libpcre.a" CORE_LIBS="$CORE_LIBS $PCRE/.libs/libpcre.a" diff --git a/auto/lib/pcre/make b/auto/lib/pcre/make index c50d12f9f..0a27a112c 100644 --- a/auto/lib/pcre/make +++ b/auto/lib/pcre/make @@ -23,14 +23,16 @@ case "$NGX_CC_NAME" in ngx_pcre=`echo \-DPCRE=\"$PCRE\" | sed -e "s/\//$ngx_regex_dirsep/g"` ;; -esac + *) + ngx_makefile= + ;; +esac -case "$NGX_PLATFORM" in - win32) +if [ -n "$ngx_makefile" ]; then - cat << END >> $NGX_MAKEFILE + cat << END >> $NGX_MAKEFILE `echo "$PCRE/pcre.lib: $PCRE/pcre.h $NGX_MAKEFILE" \ | sed -e "s/\//$ngx_regex_dirsep/g"` @@ -41,10 +43,9 @@ case "$NGX_PLATFORM" in END - ;; +else - *) - cat << END >> $NGX_MAKEFILE + cat << END >> $NGX_MAKEFILE $PCRE/pcre.h: $PCRE/Makefile @@ -60,6 +61,4 @@ $PCRE/.libs/libpcre.a: $PCRE/Makefile END - ;; - -esac +fi diff --git a/auto/lib/pcre/makefile.bcc b/auto/lib/pcre/makefile.bcc index 7230f3205..7a0f2beaf 100644 --- a/auto/lib/pcre/makefile.bcc +++ b/auto/lib/pcre/makefile.bcc @@ -13,8 +13,8 @@ pcre.lib: bcc32 -c $(CFLAGS) -I. $(PCREFLAGS) pcre_*.c - > pcre.lst - for %n in (*.obj) do @echo +%n & >> pcre.lst + copy /y nul pcre.lst + for %n in (*.obj) do @echo +%n ^^& >> pcre.lst echo + >> pcre.lst tlib pcre.lib @pcre.lst diff --git a/auto/lib/pcre/makefile.owc b/auto/lib/pcre/makefile.owc index 78f5257b3..122fd5b27 100644 --- a/auto/lib/pcre/makefile.owc +++ b/auto/lib/pcre/makefile.owc @@ -4,7 +4,7 @@ CFLAGS = -c -zq -bt=nt -ot -op -oi -oe -s -bm $(CPU_OPT) -PCREFLAGS = -DHAVE_CONFIG_H -DPCRE_STATIC -DPOSIX_MALLOC_THRESHOLD=10 \ +PCREFLAGS = -DHAVE_CONFIG_H -DPCRE_STATIC -DPOSIX_MALLOC_THRESHOLD=10 & -DSUPPORT_PCRE8 -DHAVE_MEMMOVE diff --git a/auto/lib/zlib/make b/auto/lib/zlib/make index 9401a1d1a..7875ef67f 100644 --- a/auto/lib/zlib/make +++ b/auto/lib/zlib/make @@ -24,6 +24,10 @@ case "$NGX_CC_NAME" in ngx_zlib=`echo \-DZLIB=\"$ZLIB\" | sed -e "s/\//$ngx_regex_dirsep/g"` ;; + *) + ngx_makefile= + ;; + esac @@ -33,13 +37,30 @@ done=NO case "$NGX_PLATFORM" in win32) - cat << END >> $NGX_MAKEFILE + + if [ -n "$ngx_makefile" ]; then + cat << END >> $NGX_MAKEFILE `echo "$ZLIB/zlib.lib: $NGX_MAKEFILE" | sed -e "s/\//$ngx_regex_dirsep/g"` \$(MAKE) -f auto/lib/zlib/$ngx_makefile $ngx_opt $ngx_zlib END + else + + cat << END >> $NGX_MAKEFILE + +$ZLIB/libz.a: $NGX_MAKEFILE + cd $ZLIB \\ + && \$(MAKE) distclean \\ + && \$(MAKE) -f win32/Makefile.gcc \\ + CFLAGS="$ZLIB_OPT" CC="\$(CC)" \\ + libz.a + +END + + fi + done=YES ;; diff --git a/auto/modules b/auto/modules index e710ae0ff..3feaf53e1 100644 --- a/auto/modules +++ b/auto/modules @@ -42,6 +42,7 @@ fi if [ $NGX_TEST_BUILD_EPOLL = YES ]; then have=NGX_HAVE_EPOLL . auto/have + have=NGX_HAVE_EPOLLRDHUP . auto/have have=NGX_HAVE_EVENTFD . auto/have have=NGX_TEST_BUILD_EPOLL . auto/have EVENT_MODULES="$EVENT_MODULES $EPOLL_MODULE" diff --git a/auto/os/linux b/auto/os/linux index c506d3dc3..19bf832ce 100644 --- a/auto/os/linux +++ b/auto/os/linux @@ -65,9 +65,41 @@ if [ $ngx_found = yes ]; then CORE_SRCS="$CORE_SRCS $EPOLL_SRCS" EVENT_MODULES="$EVENT_MODULES $EPOLL_MODULE" EVENT_FOUND=YES + + + # EPOLLRDHUP appeared in Linux 2.6.17, glibc 2.8 + + ngx_feature="EPOLLRDHUP" + ngx_feature_name="NGX_HAVE_EPOLLRDHUP" + ngx_feature_run=no + ngx_feature_incs="#include <sys/epoll.h>" + ngx_feature_path= + ngx_feature_libs= + ngx_feature_test="int efd = 0, fd = 0; + struct epoll_event ee; + ee.events = EPOLLIN|EPOLLRDHUP|EPOLLET; + ee.data.ptr = NULL; + epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ee)" + . auto/feature fi +# O_PATH and AT_EMPTY_PATH were introduced in 2.6.39, glibc 2.14 + +ngx_feature="O_PATH" +ngx_feature_name="NGX_HAVE_O_PATH" +ngx_feature_run=no +ngx_feature_incs="#include <sys/types.h> + #include <sys/stat.h> + #include <fcntl.h>" +ngx_feature_path= +ngx_feature_libs= +ngx_feature_test="int fd; struct stat sb; + fd = openat(AT_FDCWD, \".\", O_PATH|O_DIRECTORY|O_NOFOLLOW); + if (fstatat(fd, \"\", &sb, AT_EMPTY_PATH) != 0) return 1" +. auto/feature + + # sendfile() CC_AUX_FLAGS="$cc_aux_flags -D_GNU_SOURCE" diff --git a/auto/os/win32 b/auto/os/win32 index 21a54ba11..0b9b46187 100644 --- a/auto/os/win32 +++ b/auto/os/win32 @@ -9,10 +9,21 @@ CORE_INCS="$WIN32_INCS" CORE_DEPS="$WIN32_DEPS" CORE_SRCS="$WIN32_SRCS $IOCP_SRCS" OS_CONFIG="$WIN32_CONFIG" -CORE_LIBS="$CORE_LIBS advapi32.lib ws2_32.lib" NGX_ICONS="$NGX_WIN32_ICONS" SELECT_SRCS=$WIN32_SELECT_SRCS +case "$NGX_CC_NAME" in + + gcc) + CORE_LIBS="$CORE_LIBS -ladvapi32 -lws2_32" + ;; + + *) + CORE_LIBS="$CORE_LIBS advapi32.lib ws2_32.lib" + ;; + +esac + EVENT_MODULES="$EVENT_MODULES $IOCP_MODULE" EVENT_FOUND=YES @@ -330,7 +330,7 @@ ngx_feature_test="setsockopt(0, IPPROTO_TCP, TCP_DEFER_ACCEPT, NULL, 0)" . auto/feature -ngx_feature="TCP_KEEPIDLE, TCP_KEEPINTVL, TCP_KEEPCNT" +ngx_feature="TCP_KEEPIDLE" ngx_feature_name="NGX_HAVE_KEEPALIVE_TUNABLE" ngx_feature_run=no ngx_feature_incs="#include <sys/socket.h> diff --git a/src/core/nginx.h b/src/core/nginx.h index c2ecbfd86..7117a03ad 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1005004 -#define NGINX_VERSION "1.5.4" +#define nginx_version 1005005 +#define NGINX_VERSION "1.5.5" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c index e12d3efc0..28bf6ba06 100644 --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -297,7 +297,7 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle) continue; } - if (ls[i].fd != -1) { + if (ls[i].fd != (ngx_socket_t) -1) { continue; } @@ -312,7 +312,7 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle) s = ngx_socket(ls[i].sockaddr->sa_family, ls[i].type, 0); - if (s == -1) { + if (s == (ngx_socket_t) -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, ngx_socket_n " %V failed", &ls[i].addr_text); return NGX_ERROR; @@ -863,7 +863,7 @@ ngx_close_connection(ngx_connection_t *c) ngx_uint_t log_error, level; ngx_socket_t fd; - if (c->fd == -1) { + if (c->fd == (ngx_socket_t) -1) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed"); return; } diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c index 2c006bcb2..eb39ab253 100644 --- a/src/core/ngx_cycle.c +++ b/src/core/ngx_cycle.c @@ -543,7 +543,7 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) } } - if (nls[n].fd == -1) { + if (nls[n].fd == (ngx_socket_t) -1) { nls[n].open = 1; } } @@ -649,7 +649,7 @@ old_shm_zone_done: ls = old_cycle->listening.elts; for (i = 0; i < old_cycle->listening.nelts; i++) { - if (ls[i].remain || ls[i].fd == -1) { + if (ls[i].remain || ls[i].fd == (ngx_socket_t) -1) { continue; } @@ -813,7 +813,7 @@ failed: ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { - if (ls[i].fd == -1 || !ls[i].open) { + if (ls[i].fd == (ngx_socket_t) -1 || !ls[i].open) { continue; } diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c index 28e8871ec..7e6e921a3 100644 --- a/src/core/ngx_file.c +++ b/src/core/ngx_file.c @@ -359,9 +359,6 @@ ngx_conf_set_path_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NULL; } - path->len = 0; - path->manager = NULL; - path->loader = NULL; path->conf_file = cf->conf_file->file.name.data; path->line = cf->conf_file->line; @@ -402,7 +399,7 @@ ngx_conf_merge_path_value(ngx_conf_t *cf, ngx_path_t **path, ngx_path_t *prev, return NGX_CONF_OK; } - *path = ngx_palloc(cf->pool, sizeof(ngx_path_t)); + *path = ngx_pcalloc(cf->pool, sizeof(ngx_path_t)); if (*path == NULL) { return NGX_CONF_ERROR; } @@ -421,10 +418,6 @@ ngx_conf_merge_path_value(ngx_conf_t *cf, ngx_path_t **path, ngx_path_t *prev, + init->level[1] + (init->level[1] ? 1 : 0) + init->level[2] + (init->level[2] ? 1 : 0); - (*path)->manager = NULL; - (*path)->loader = NULL; - (*path)->conf_file = NULL; - if (ngx_add_path(cf, path) != NGX_OK) { return NGX_CONF_ERROR; } @@ -508,6 +501,14 @@ ngx_add_path(ngx_conf_t *cf, ngx_path_t **slot) if (p[i]->name.len == path->name.len && ngx_strcmp(p[i]->name.data, path->name.data) == 0) { + if (p[i]->data != path->data) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "the same path name \"%V\" " + "used in %s:%ui and", + &p[i]->name, p[i]->conf_file, p[i]->line); + return NGX_ERROR; + } + for (n = 0; n < 3; n++) { if (p[i]->level[n] != path->level[n]) { if (path->conf_file == NULL) { diff --git a/src/core/ngx_open_file_cache.c b/src/core/ngx_open_file_cache.c index b72af5ea0..4df2134b2 100644 --- a/src/core/ngx_open_file_cache.c +++ b/src/core/ngx_open_file_cache.c @@ -25,6 +25,10 @@ static void ngx_open_file_cache_cleanup(void *data); #if (NGX_HAVE_OPENAT) static ngx_fd_t ngx_openat_file_owner(ngx_fd_t at_fd, const u_char *name, ngx_int_t mode, ngx_int_t create, ngx_int_t access, ngx_log_t *log); +#if (NGX_HAVE_O_PATH) +static ngx_int_t ngx_file_o_path_info(ngx_fd_t fd, ngx_file_info_t *fi, + ngx_log_t *log); +#endif #endif static ngx_fd_t ngx_open_file_wrapper(ngx_str_t *name, ngx_open_file_info_t *of, ngx_int_t mode, ngx_int_t create, @@ -517,10 +521,17 @@ ngx_openat_file_owner(ngx_fd_t at_fd, const u_char *name, goto failed; } +#if (NGX_HAVE_O_PATH) + if (ngx_file_o_path_info(fd, &fi, log) == NGX_ERROR) { + err = ngx_errno; + goto failed; + } +#else if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) { err = ngx_errno; goto failed; } +#endif if (fi.st_uid != atfi.st_uid) { err = NGX_ELOOP; @@ -541,8 +552,63 @@ failed: return NGX_INVALID_FILE; } + +#if (NGX_HAVE_O_PATH) + +static ngx_int_t +ngx_file_o_path_info(ngx_fd_t fd, ngx_file_info_t *fi, ngx_log_t *log) +{ + static ngx_uint_t use_fstat = 1; + + /* + * In Linux 2.6.39 the O_PATH flag was introduced that allows to obtain + * a descriptor without actually opening file or directory. It requires + * less permissions for path components, but till Linux 3.6 fstat() returns + * EBADF on such descriptors, and fstatat() with the AT_EMPTY_PATH flag + * should be used instead. + * + * Three scenarios are handled in this function: + * + * 1) The kernel is newer than 3.6 or fstat() with O_PATH support was + * backported by vendor. Then fstat() is used. + * + * 2) The kernel is newer than 2.6.39 but older than 3.6. In this case + * the first call of fstat() returns EBADF and we fallback to fstatat() + * with AT_EMPTY_PATH which was introduced at the same time as O_PATH. + * + * 3) The kernel is older than 2.6.39 but nginx was build with O_PATH + * support. Since descriptors are opened with O_PATH|O_RDONLY flags + * and O_PATH is ignored by the kernel then the O_RDONLY flag is + * actually used. In this case fstat() just works. + */ + + if (use_fstat) { + if (ngx_fd_info(fd, fi) != NGX_FILE_ERROR) { + return NGX_OK; + } + + if (ngx_errno != NGX_EBADF) { + return NGX_ERROR; + } + + ngx_log_error(NGX_LOG_NOTICE, log, 0, + "fstat(O_PATH) failed with EBADF, " + "switching to fstatat(AT_EMPTY_PATH)"); + + use_fstat = 0; + } + + if (ngx_file_at_info(fd, "", fi, AT_EMPTY_PATH) != NGX_FILE_ERROR) { + return NGX_OK; + } + + return NGX_ERROR; +} + #endif +#endif /* NGX_HAVE_OPENAT */ + static ngx_fd_t ngx_open_file_wrapper(ngx_str_t *name, ngx_open_file_info_t *of, diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c index d59d0c471..d94477a9c 100644 --- a/src/core/ngx_resolver.c +++ b/src/core/ngx_resolver.c @@ -2221,7 +2221,7 @@ ngx_udp_connect(ngx_udp_connection_t *uc) ngx_log_debug1(NGX_LOG_DEBUG_EVENT, &uc->log, 0, "UDP socket %d", s); - if (s == -1) { + if (s == (ngx_socket_t) -1) { ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno, ngx_socket_n " failed"); return NGX_ERROR; diff --git a/src/core/ngx_slab.c b/src/core/ngx_slab.c index ae9d6f3fc..6d18abb72 100644 --- a/src/core/ngx_slab.c +++ b/src/core/ngx_slab.c @@ -440,7 +440,8 @@ ngx_slab_free_locked(ngx_slab_pool_t *pool, void *p) n = ((uintptr_t) p & (ngx_pagesize - 1)) >> shift; m = (uintptr_t) 1 << (n & (sizeof(uintptr_t) * 8 - 1)); n /= (sizeof(uintptr_t) * 8); - bitmap = (uintptr_t *) ((uintptr_t) p & ~(ngx_pagesize - 1)); + bitmap = (uintptr_t *) + ((uintptr_t) p & ~((uintptr_t) ngx_pagesize - 1)); if (bitmap[n] & m) { diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c index 3b392f7b2..d3ff36855 100644 --- a/src/core/ngx_string.c +++ b/src/core/ngx_string.c @@ -486,7 +486,7 @@ ngx_sprintf_num(u_char *buf, u_char *last, uint64_t ui64, u_char zero, if (hexadecimal == 0) { - if (ui64 <= NGX_MAX_UINT32_VALUE) { + if (ui64 <= (uint64_t) NGX_MAX_UINT32_VALUE) { /* * To divide 64-bit numbers and to find remainders diff --git a/src/event/modules/ngx_epoll_module.c b/src/event/modules/ngx_epoll_module.c index ee77d8e4a..f5f663179 100644 --- a/src/event/modules/ngx_epoll_module.c +++ b/src/event/modules/ngx_epoll_module.c @@ -25,6 +25,8 @@ #define EPOLLERR 0x008 #define EPOLLHUP 0x010 +#define EPOLLRDHUP 0x2000 + #define EPOLLET 0x80000000 #define EPOLLONESHOT 0x40000000 @@ -396,13 +398,13 @@ ngx_epoll_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags) if (event == NGX_READ_EVENT) { e = c->write; prev = EPOLLOUT; -#if (NGX_READ_EVENT != EPOLLIN) - events = EPOLLIN; +#if (NGX_READ_EVENT != EPOLLIN|EPOLLRDHUP) + events = EPOLLIN|EPOLLRDHUP; #endif } else { e = c->read; - prev = EPOLLIN; + prev = EPOLLIN|EPOLLRDHUP; #if (NGX_WRITE_EVENT != EPOLLOUT) events = EPOLLOUT; #endif @@ -466,7 +468,7 @@ ngx_epoll_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags) } else { e = c->read; - prev = EPOLLIN; + prev = EPOLLIN|EPOLLRDHUP; } if (e->active) { @@ -501,7 +503,7 @@ ngx_epoll_add_connection(ngx_connection_t *c) { struct epoll_event ee; - ee.events = EPOLLIN|EPOLLOUT|EPOLLET; + ee.events = EPOLLIN|EPOLLOUT|EPOLLET|EPOLLRDHUP; ee.data.ptr = (void *) ((uintptr_t) c | c->read->instance); ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, @@ -666,6 +668,12 @@ ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags) if ((revents & EPOLLIN) && rev->active) { +#if (NGX_HAVE_EPOLLRDHUP) + if (revents & EPOLLRDHUP) { + rev->pending_eof = 1; + } +#endif + if ((flags & NGX_POST_THREAD_EVENTS) && !rev->accept) { rev->posted_ready = 1; diff --git a/src/event/modules/ngx_select_module.c b/src/event/modules/ngx_select_module.c index ed71368e9..51690558e 100644 --- a/src/event/modules/ngx_select_module.c +++ b/src/event/modules/ngx_select_module.c @@ -288,7 +288,7 @@ ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_log_error(level, cycle->log, err, "select() failed"); - if (err == EBADF) { + if (err == NGX_EBADF) { ngx_select_repair_fd_sets(cycle); } diff --git a/src/event/modules/ngx_win32_select_module.c b/src/event/modules/ngx_win32_select_module.c index 0a02ffca0..eb5382d4e 100644 --- a/src/event/modules/ngx_win32_select_module.c +++ b/src/event/modules/ngx_win32_select_module.c @@ -148,8 +148,8 @@ ngx_select_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags) return NGX_ERROR; } - if ((event == NGX_READ_EVENT) && (max_read >= FD_SETSIZE) - || (event == NGX_WRITE_EVENT) && (max_write >= FD_SETSIZE)) + if ((event == NGX_READ_EVENT && max_read >= FD_SETSIZE) + || (event == NGX_WRITE_EVENT && max_write >= FD_SETSIZE)) { ngx_log_error(NGX_LOG_ERR, ev->log, 0, "maximum number of descriptors " diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h index 93c457c7b..530c9486c 100644 --- a/src/event/ngx_event.h +++ b/src/event/ngx_event.h @@ -69,13 +69,9 @@ struct ngx_event_s { unsigned delayed:1; - unsigned read_discarded:1; - - unsigned unexpected_eof:1; - unsigned deferred_accept:1; - /* the pending eof reported by kqueue or in aio chain operation */ + /* the pending eof reported by kqueue, epoll or in aio chain operation */ unsigned pending_eof:1; #if !(NGX_THREADS) @@ -353,6 +349,11 @@ extern ngx_event_actions_t ngx_event_actions; #define NGX_VNODE_EVENT 0 +#if (NGX_HAVE_EPOLL) && !(NGX_HAVE_EPOLLRDHUP) +#define EPOLLRDHUP 0 +#endif + + #if (NGX_HAVE_KQUEUE) #define NGX_READ_EVENT EVFILT_READ @@ -396,7 +397,7 @@ extern ngx_event_actions_t ngx_event_actions; #elif (NGX_HAVE_EPOLL) -#define NGX_READ_EVENT EPOLLIN +#define NGX_READ_EVENT (EPOLLIN|EPOLLRDHUP) #define NGX_WRITE_EVENT EPOLLOUT #define NGX_LEVEL_EVENT 0 diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c index e3f828da8..b1145446a 100644 --- a/src/event/ngx_event_accept.c +++ b/src/event/ngx_event_accept.c @@ -70,7 +70,7 @@ ngx_event_accept(ngx_event_t *ev) s = accept(lc->fd, (struct sockaddr *) sa, &socklen); #endif - if (s == -1) { + if (s == (ngx_socket_t) -1) { err = ngx_socket_errno; if (err == NGX_EAGAIN) { @@ -297,7 +297,7 @@ ngx_event_accept(ngx_event_t *ev) cidr = ecf->debug_connection.elts; for (i = 0; i < ecf->debug_connection.nelts; i++) { - if (cidr[i].family != c->sockaddr->sa_family) { + if (cidr[i].family != (ngx_uint_t) c->sockaddr->sa_family) { goto next; } diff --git a/src/event/ngx_event_connect.c b/src/event/ngx_event_connect.c index e6ae6564e..fddad0a92 100644 --- a/src/event/ngx_event_connect.c +++ b/src/event/ngx_event_connect.c @@ -31,7 +31,7 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc) ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pc->log, 0, "socket %d", s); - if (s == -1) { + if (s == (ngx_socket_t) -1) { ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno, ngx_socket_n " failed"); return NGX_ERROR; diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c index 50746e7ac..fedb604de 100644 --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -185,8 +185,10 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data) SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG); SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER); +#ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING /* this option allow a potential SSL 2.0 rollback (CAN-2005-2969) */ SSL_CTX_set_options(ssl->ctx, SSL_OP_MSIE_SSLV2_RSA_PADDING); +#endif SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLEAY_080_CLIENT_DH_BUG); SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_D5_BUG); @@ -363,6 +365,13 @@ ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, return NGX_ERROR; } + /* + * SSL_CTX_load_verify_locations() may leave errors in the error queue + * while returning success + */ + + ERR_clear_error(); + list = SSL_load_client_CA_file((char *) cert->data); if (list == NULL) { @@ -407,6 +416,13 @@ ngx_ssl_trusted_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, return NGX_ERROR; } + /* + * SSL_CTX_load_verify_locations() may leave errors in the error queue + * while returning success + */ + + ERR_clear_error(); + return NGX_OK; } diff --git a/src/event/ngx_event_pipe.c b/src/event/ngx_event_pipe.c index 4dfb88f6d..6f685a9ed 100644 --- a/src/event/ngx_event_pipe.c +++ b/src/event/ngx_event_pipe.c @@ -57,7 +57,7 @@ ngx_event_pipe(ngx_event_pipe_t *p, ngx_int_t do_write) do_write = 1; } - if (p->upstream->fd != -1) { + if (p->upstream->fd != (ngx_socket_t) -1) { rev = p->upstream->read; flags = (rev->eof || rev->error) ? NGX_CLOSE_EVENT : 0; @@ -74,7 +74,9 @@ ngx_event_pipe(ngx_event_pipe_t *p, ngx_int_t do_write) } } - if (p->downstream->fd != -1 && p->downstream->data == p->output_ctx) { + if (p->downstream->fd != (ngx_socket_t) -1 + && p->downstream->data == p->output_ctx) + { wev = p->downstream->write; if (ngx_handle_write_event(wev, p->send_lowat) != NGX_OK) { return NGX_ABORT; @@ -220,8 +222,8 @@ ngx_event_pipe_read_upstream(ngx_event_pipe_t *p) { /* - * if it is allowed, then save some bufs from r->in - * to a temporary file, and add them to a r->out chain + * if it is allowed, then save some bufs from p->in + * to a temporary file, and add them to a p->out chain */ rc = ngx_event_pipe_write_chain_to_temp_file(p); diff --git a/src/http/modules/ngx_http_image_filter_module.c b/src/http/modules/ngx_http_image_filter_module.c index 6d3f47dcb..cc41ef0d5 100644 --- a/src/http/modules/ngx_http_image_filter_module.c +++ b/src/http/modules/ngx_http_image_filter_module.c @@ -478,7 +478,12 @@ ngx_http_image_read(ngx_http_request_t *r, ngx_chain_t *in) "image buf: %uz", size); rest = ctx->image + ctx->length - p; - size = (rest < size) ? rest : size; + + if (size > rest) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "image filter: too big response"); + return NGX_ERROR; + } p = ngx_cpymem(p, b->pos, size); b->pos += size; diff --git a/src/http/modules/ngx_http_log_module.c b/src/http/modules/ngx_http_log_module.c index aa6a3fcee..7eb29b38a 100644 --- a/src/http/modules/ngx_http_log_module.c +++ b/src/http/modules/ngx_http_log_module.c @@ -780,7 +780,7 @@ ngx_http_log_request_time(ngx_http_request_t *r, u_char *buf, ((tp->sec - r->start_sec) * 1000 + (tp->msec - r->start_msec)); ms = ngx_max(ms, 0); - return ngx_sprintf(buf, "%T.%03M", ms / 1000, ms % 1000); + return ngx_sprintf(buf, "%T.%03M", (time_t) ms / 1000, ms % 1000); } diff --git a/src/http/modules/ngx_http_map_module.c b/src/http/modules/ngx_http_map_module.c index 13c8b97ff..3245e0413 100644 --- a/src/http/modules/ngx_http_map_module.c +++ b/src/http/modules/ngx_http_map_module.c @@ -131,7 +131,7 @@ ngx_http_map_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, } if (!value->valid) { - value = ngx_http_get_flushed_variable(r, (ngx_uint_t) value->data); + value = ngx_http_get_flushed_variable(r, (uintptr_t) value->data); if (value == NULL || value->not_found) { value = &ngx_http_variable_null_value; @@ -414,7 +414,7 @@ ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) var = ctx->var_values.elts; for (i = 0; i < ctx->var_values.nelts; i++) { - if (index == (ngx_int_t) var[i].data) { + if (index == (intptr_t) var[i].data) { var = &var[i]; goto found; } @@ -429,7 +429,7 @@ ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) var->no_cacheable = 0; var->not_found = 0; var->len = 0; - var->data = (u_char *) index; + var->data = (u_char *) (intptr_t) index; goto found; } diff --git a/src/http/modules/ngx_http_memcached_module.c b/src/http/modules/ngx_http_memcached_module.c index bfff1bfc2..aaa047e8f 100644 --- a/src/http/modules/ngx_http_memcached_module.c +++ b/src/http/modules/ngx_http_memcached_module.c @@ -520,7 +520,7 @@ ngx_http_memcached_filter(void *data, ssize_t bytes) return NGX_OK; } - last += u->length - NGX_HTTP_MEMCACHED_END; + last += (size_t) (u->length - NGX_HTTP_MEMCACHED_END); if (ngx_strncmp(last, ngx_http_memcached_end, b->last - last) != 0) { ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0, diff --git a/src/http/modules/ngx_http_mp4_module.c b/src/http/modules/ngx_http_mp4_module.c index f9281a371..c44dc52c9 100644 --- a/src/http/modules/ngx_http_mp4_module.c +++ b/src/http/modules/ngx_http_mp4_module.c @@ -157,7 +157,11 @@ typedef struct { #define ngx_mp4_atom_header(mp4) (mp4->buffer_pos - 8) #define ngx_mp4_atom_data(mp4) mp4->buffer_pos #define ngx_mp4_atom_data_size(t) (uint64_t) (sizeof(t) - 8) -#define ngx_mp4_atom_next(mp4, n) mp4->buffer_pos += n; mp4->offset += n + + +#define ngx_mp4_atom_next(mp4, n) \ + mp4->buffer_pos += (size_t) n; \ + mp4->offset += n #define ngx_mp4_set_atom_name(p, n1, n2, n3, n4) \ @@ -956,7 +960,7 @@ ngx_http_mp4_read_ftyp_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 ftyp atom"); if (atom_data_size > 1024 - || ngx_mp4_atom_data(mp4) + atom_data_size > mp4->buffer_end) + || ngx_mp4_atom_data(mp4) + (size_t) atom_data_size > mp4->buffer_end) { ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, "\"%s\" mp4 ftyp atom is too large:%uL", @@ -1129,7 +1133,7 @@ ngx_http_mp4_update_mdat_atom(ngx_http_mp4_file_t *mp4, off_t start_offset) atom_header = mp4->mdat_atom_header; - if ((uint64_t) atom_data_size > 0xffffffff) { + if ((uint64_t) atom_data_size > (uint64_t) 0xffffffff) { atom_size = 1; atom_header_size = sizeof(ngx_mp4_atom_header64_t); ngx_mp4_set_64value(atom_header + sizeof(ngx_mp4_atom_header_t), @@ -1304,7 +1308,7 @@ ngx_http_mp4_read_trak_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) trak->out[NGX_HTTP_MP4_TRAK_ATOM].buf = atom; - atom_end = mp4->buffer_pos + atom_data_size; + atom_end = mp4->buffer_pos + (size_t) atom_data_size; atom_file_end = mp4->offset + atom_data_size; rc = ngx_http_mp4_read_atom(mp4, ngx_http_mp4_trak_atoms, atom_data_size); diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c index a22ed0fcb..f5fd83d14 100644 --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -1712,7 +1712,7 @@ ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf) if (buf->last - buf->pos >= ctx->chunked.size) { - buf->pos += ctx->chunked.size; + buf->pos += (size_t) ctx->chunked.size; b->last = buf->pos; ctx->chunked.size = 0; @@ -1875,7 +1875,7 @@ ngx_http_proxy_non_buffered_chunked_filter(void *data, ssize_t bytes) b->tag = u->output.tag; if (buf->last - buf->pos >= ctx->chunked.size) { - buf->pos += ctx->chunked.size; + buf->pos += (size_t) ctx->chunked.size; b->last = buf->pos; ctx->chunked.size = 0; diff --git a/src/http/modules/ngx_http_referer_module.c b/src/http/modules/ngx_http_referer_module.c index 85b75ab3d..b417eb227 100644 --- a/src/http/modules/ngx_http_referer_module.c +++ b/src/http/modules/ngx_http_referer_module.c @@ -12,22 +12,18 @@ #define NGX_HTTP_REFERER_NO_URI_PART ((void *) 4) -#if !(NGX_PCRE) - -#define ngx_regex_t void - -#endif - typedef struct { ngx_hash_combined_t hash; #if (NGX_PCRE) ngx_array_t *regex; + ngx_array_t *server_name_regex; #endif ngx_flag_t no_referer; ngx_flag_t blocked_referer; + ngx_flag_t server_names; ngx_hash_keys_arrays_t *keys; @@ -41,10 +37,14 @@ static char * ngx_http_referer_merge_conf(ngx_conf_t *cf, void *parent, void *child); static char *ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -static char *ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys, - ngx_str_t *value, ngx_str_t *uri); -static char *ngx_http_add_regex_referer(ngx_conf_t *cf, - ngx_http_referer_conf_t *rlcf, ngx_str_t *name, ngx_regex_t *regex); +static ngx_int_t ngx_http_add_referer(ngx_conf_t *cf, + ngx_hash_keys_arrays_t *keys, ngx_str_t *value, ngx_str_t *uri); +static ngx_int_t ngx_http_add_regex_referer(ngx_conf_t *cf, + ngx_http_referer_conf_t *rlcf, ngx_str_t *name); +#if (NGX_PCRE) +static ngx_int_t ngx_http_add_regex_server_name(ngx_conf_t *cf, + ngx_http_referer_conf_t *rlcf, ngx_http_regex_t *regex); +#endif static int ngx_libc_cdecl ngx_http_cmp_referer_wildcards(const void *one, const void *two); @@ -117,6 +117,10 @@ ngx_http_referer_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, ngx_uint_t i, key; ngx_http_referer_conf_t *rlcf; u_char buf[256]; +#if (NGX_PCRE) + ngx_int_t rc; + ngx_str_t referer; +#endif rlcf = ngx_http_get_module_loc_conf(r, ngx_http_referer_module); @@ -125,6 +129,7 @@ ngx_http_referer_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, && rlcf->hash.wc_tail == NULL #if (NGX_PCRE) && rlcf->regex == NULL + && rlcf->server_name_regex == NULL #endif ) { @@ -173,12 +178,12 @@ valid_scheme: break; } - buf[i] = ngx_tolower(*p); - key = ngx_hash(key, buf[i++]); - if (i == 256) { goto invalid; } + + buf[i] = ngx_tolower(*p); + key = ngx_hash(key, buf[i++]); } uri = ngx_hash_find_combined(&rlcf->hash, key, buf, p - ref); @@ -189,10 +194,25 @@ valid_scheme: #if (NGX_PCRE) - if (rlcf->regex) { - ngx_int_t rc; - ngx_str_t referer; + if (rlcf->server_name_regex) { + referer.len = p - ref; + referer.data = buf; + + rc = ngx_regex_exec_array(rlcf->server_name_regex, &referer, + r->connection->log); + + if (rc == NGX_OK) { + goto valid; + } + + if (rc == NGX_ERROR) { + return rc; + } + + /* NGX_DECLINED */ + } + if (rlcf->regex) { referer.len = len; referer.data = ref; @@ -253,8 +273,17 @@ ngx_http_referer_create_conf(ngx_conf_t *cf) return NULL; } + /* + * set by ngx_pcalloc(): + * + * conf->hash = { NULL }; + * conf->server_names = 0; + * conf->keys = NULL; + */ + #if (NGX_PCRE) conf->regex = NGX_CONF_UNSET_PTR; + conf->server_name_regex = NGX_CONF_UNSET_PTR; #endif conf->no_referer = NGX_CONF_UNSET; @@ -272,13 +301,18 @@ ngx_http_referer_merge_conf(ngx_conf_t *cf, void *parent, void *child) ngx_http_referer_conf_t *prev = parent; ngx_http_referer_conf_t *conf = child; - ngx_hash_init_t hash; + ngx_uint_t n; + ngx_hash_init_t hash; + ngx_http_server_name_t *sn; + ngx_http_core_srv_conf_t *cscf; if (conf->keys == NULL) { conf->hash = prev->hash; #if (NGX_PCRE) ngx_conf_merge_ptr_value(conf->regex, prev->regex, NULL); + ngx_conf_merge_ptr_value(conf->server_name_regex, + prev->server_name_regex, NULL); #endif ngx_conf_merge_value(conf->no_referer, prev->no_referer, 0); ngx_conf_merge_value(conf->blocked_referer, prev->blocked_referer, 0); @@ -290,6 +324,33 @@ ngx_http_referer_merge_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_OK; } + if (conf->server_names == 1) { + cscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module); + + sn = cscf->server_names.elts; + for (n = 0; n < cscf->server_names.nelts; n++) { + +#if (NGX_PCRE) + if (sn[n].regex) { + + if (ngx_http_add_regex_server_name(cf, conf, sn[n].regex) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + + continue; + } +#endif + + if (ngx_http_add_referer(cf, conf->keys, &sn[n].name, NULL) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + } + } + if ((conf->no_referer == 1 || conf->blocked_referer == 1) && conf->keys->keys.nelts == 0 && conf->keys->dns_wc_head.nelts == 0 @@ -368,6 +429,8 @@ ngx_http_referer_merge_conf(ngx_conf_t *cf, void *parent, void *child) #if (NGX_PCRE) ngx_conf_merge_ptr_value(conf->regex, prev->regex, NULL); + ngx_conf_merge_ptr_value(conf->server_name_regex, prev->server_name_regex, + NULL); #endif if (conf->no_referer == NGX_CONF_UNSET) { @@ -391,10 +454,8 @@ ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) u_char *p; ngx_str_t *value, uri, name; - ngx_uint_t i, n; + ngx_uint_t i; ngx_http_variable_t *var; - ngx_http_server_name_t *sn; - ngx_http_core_srv_conf_t *cscf; ngx_str_set(&name, "invalid_referer"); @@ -438,48 +499,21 @@ ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) continue; } - ngx_str_null(&uri); - if (ngx_strcmp(value[i].data, "server_names") == 0) { - - cscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module); - - sn = cscf->server_names.elts; - for (n = 0; n < cscf->server_names.nelts; n++) { - -#if (NGX_PCRE) - if (sn[n].regex) { - - if (ngx_http_add_regex_referer(cf, rlcf, &sn[n].name, - sn[n].regex->regex) - != NGX_OK) - { - return NGX_CONF_ERROR; - } - - continue; - } -#endif - - if (ngx_http_add_referer(cf, rlcf->keys, &sn[n].name, &uri) - != NGX_OK) - { - return NGX_CONF_ERROR; - } - } - + rlcf->server_names = 1; continue; } if (value[i].data[0] == '~') { - if (ngx_http_add_regex_referer(cf, rlcf, &value[i], NULL) != NGX_OK) - { + if (ngx_http_add_regex_referer(cf, rlcf, &value[i]) != NGX_OK) { return NGX_CONF_ERROR; } continue; } + ngx_str_null(&uri); + p = (u_char *) ngx_strchr(value[i].data, '/'); if (p) { @@ -497,20 +531,20 @@ ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } -static char * +static ngx_int_t ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys, ngx_str_t *value, ngx_str_t *uri) { ngx_int_t rc; ngx_str_t *u; - if (uri->len == 0) { + if (uri == NULL || uri->len == 0) { u = NGX_HTTP_REFERER_NO_URI_PART; } else { u = ngx_palloc(cf->pool, sizeof(ngx_str_t)); if (u == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } *u = *uri; @@ -519,7 +553,7 @@ ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys, rc = ngx_hash_add_key(keys, value, u, NGX_HASH_WILDCARD_KEY); if (rc == NGX_OK) { - return NGX_CONF_OK; + return NGX_OK; } if (rc == NGX_DECLINED) { @@ -532,13 +566,13 @@ ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys, "conflicting parameter \"%V\"", value); } - return NGX_CONF_ERROR; + return NGX_ERROR; } -static char * +static ngx_int_t ngx_http_add_regex_referer(ngx_conf_t *cf, ngx_http_referer_conf_t *rlcf, - ngx_str_t *name, ngx_regex_t *regex) + ngx_str_t *name) { #if (NGX_PCRE) ngx_regex_elt_t *re; @@ -547,26 +581,19 @@ ngx_http_add_regex_referer(ngx_conf_t *cf, ngx_http_referer_conf_t *rlcf, if (name->len == 1) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "empty regex in \"%V\"", name); - return NGX_CONF_ERROR; + return NGX_ERROR; } if (rlcf->regex == NGX_CONF_UNSET_PTR) { rlcf->regex = ngx_array_create(cf->pool, 2, sizeof(ngx_regex_elt_t)); if (rlcf->regex == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } } re = ngx_array_push(rlcf->regex); if (re == NULL) { - return NGX_CONF_ERROR; - } - - if (regex) { - re->regex = regex; - re->name = name->data; - - return NGX_CONF_OK; + return NGX_ERROR; } name->len--; @@ -582,13 +609,13 @@ ngx_http_add_regex_referer(ngx_conf_t *cf, ngx_http_referer_conf_t *rlcf, if (ngx_regex_compile(&rc) != NGX_OK) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err); - return NGX_CONF_ERROR; + return NGX_ERROR; } re->regex = rc.regex; re->name = name->data; - return NGX_CONF_OK; + return NGX_OK; #else @@ -596,12 +623,42 @@ ngx_http_add_regex_referer(ngx_conf_t *cf, ngx_http_referer_conf_t *rlcf, "the using of the regex \"%V\" requires PCRE library", name); - return NGX_CONF_ERROR; + return NGX_ERROR; #endif } +#if (NGX_PCRE) + +static ngx_int_t +ngx_http_add_regex_server_name(ngx_conf_t *cf, ngx_http_referer_conf_t *rlcf, + ngx_http_regex_t *regex) +{ + ngx_regex_elt_t *re; + + if (rlcf->server_name_regex == NGX_CONF_UNSET_PTR) { + rlcf->server_name_regex = ngx_array_create(cf->pool, 2, + sizeof(ngx_regex_elt_t)); + if (rlcf->server_name_regex == NULL) { + return NGX_ERROR; + } + } + + re = ngx_array_push(rlcf->server_name_regex); + if (re == NULL) { + return NGX_ERROR; + } + + re->regex = regex->regex; + re->name = regex->name.data; + + return NGX_OK; +} + +#endif + + static int ngx_libc_cdecl ngx_http_cmp_referer_wildcards(const void *one, const void *two) { diff --git a/src/http/modules/ngx_http_upstream_ip_hash_module.c b/src/http/modules/ngx_http_upstream_ip_hash_module.c index 29c74fd54..0e5cf416a 100644 --- a/src/http/modules/ngx_http_upstream_ip_hash_module.c +++ b/src/http/modules/ngx_http_upstream_ip_hash_module.c @@ -174,7 +174,7 @@ ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc, void *data) for ( ;; ) { - for (i = 0; i < iphp->addrlen; i++) { + for (i = 0; i < (ngx_uint_t) iphp->addrlen; i++) { hash = (hash * 113 + iphp->addr[i]) % 6271; } diff --git a/src/http/modules/perl/ngx_http_perl_module.c b/src/http/modules/perl/ngx_http_perl_module.c index 90e32e80e..bf4d1fe9a 100644 --- a/src/http/modules/perl/ngx_http_perl_module.c +++ b/src/http/modules/perl/ngx_http_perl_module.c @@ -421,7 +421,7 @@ ngx_http_perl_ssi(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ssi_ctx, return NGX_ERROR; } - asv[0] = (SV *) i; + asv[0] = (SV *) (uintptr_t) i; for (i = 0; args[i]; i++) { asv[i + 1] = newSVpvn((char *) args[i]->data, args[i]->len); @@ -692,7 +692,7 @@ ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r, HV *nginx, SV *sub, if (args) { EXTEND(sp, (intptr_t) args[0]); - for (i = 1; i <= (ngx_uint_t) args[0]; i++) { + for (i = 1; i <= (uintptr_t) args[0]; i++) { PUSHs(sv_2mortal(args[i])); } } diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c index cf27683e6..7e46d1295 100644 --- a/src/http/ngx_http_file_cache.c +++ b/src/http/ngx_http_file_cache.c @@ -503,7 +503,7 @@ ngx_http_file_cache_read(ngx_http_request_t *r, ngx_http_cache_t *c) return NGX_DECLINED; } - if (h->body_start > c->body_start) { + if ((size_t) h->body_start > c->body_start) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, "cache file \"%s\" has too long header", c->file.name.data); diff --git a/src/http/ngx_http_header_filter_module.c b/src/http/ngx_http_header_filter_module.c index 707a81313..fc54836f6 100644 --- a/src/http/ngx_http_header_filter_module.c +++ b/src/http/ngx_http_header_filter_module.c @@ -92,10 +92,7 @@ static ngx_str_t ngx_http_status_lines[] = { ngx_string("411 Length Required"), ngx_string("412 Precondition Failed"), ngx_string("413 Request Entity Too Large"), - ngx_null_string, /* "414 Request-URI Too Large", but we never send it - * because we treat such requests as the HTTP/0.9 - * requests and send only a body without a header - */ + ngx_string("414 Request-URI Too Large"), ngx_string("415 Unsupported Media Type"), ngx_string("416 Requested Range Not Satisfiable"), @@ -270,6 +267,12 @@ ngx_http_header_filter(ngx_http_request_t *r) len += NGX_INT_T_LEN; status_line = NULL; } + + if (status_line && status_line->len == 0) { + status = r->headers_out.status; + len += NGX_INT_T_LEN; + status_line = NULL; + } } clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index ca738cbb6..1f6d246bc 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -571,6 +571,7 @@ ngx_http_create_request(ngx_connection_t *c) r->start_msec = tp->msec; r->method = NGX_HTTP_UNKNOWN; + r->http_version = NGX_HTTP_VERSION_10; r->headers_in.content_length_n = -1; r->headers_in.keep_alive_n = -1; @@ -2693,6 +2694,33 @@ ngx_http_test_reading(ngx_http_request_t *r) #endif +#if (NGX_HAVE_EPOLLRDHUP) + + if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) && rev->pending_eof) { + socklen_t len; + + rev->eof = 1; + c->error = 1; + + err = 0; + len = sizeof(ngx_err_t); + + /* + * BSDs and Linux return 0 and set a pending error in err + * Solaris returns -1 and sets errno + */ + + if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len) + == -1) + { + err = ngx_errno; + } + + goto closed; + } + +#endif + n = recv(c->fd, buf, 1, MSG_PEEK); if (n == 0) { @@ -3342,10 +3370,15 @@ ngx_http_free_request(ngx_http_request_t *r, ngx_int_t rc) return; } - for (cln = r->cleanup; cln; cln = cln->next) { + cln = r->cleanup; + r->cleanup = NULL; + + while (cln) { if (cln->handler) { cln->handler(cln->data); } + + cln = cln->next; } #if (NGX_STAT_STUB) diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c index fc3a1800d..dc1fcde1c 100644 --- a/src/http/ngx_http_request_body.c +++ b/src/http/ngx_http_request_body.c @@ -714,7 +714,7 @@ ngx_http_discard_request_body_filter(ngx_http_request_t *r, ngx_buf_t *b) size = b->last - b->pos; if ((off_t) size > rb->chunked->size) { - b->pos += rb->chunked->size; + b->pos += (size_t) rb->chunked->size; rb->chunked->size = 0; } else { @@ -753,7 +753,7 @@ ngx_http_discard_request_body_filter(ngx_http_request_t *r, ngx_buf_t *b) size = b->last - b->pos; if ((off_t) size > r->headers_in.content_length_n) { - b->pos += r->headers_in.content_length_n; + b->pos += (size_t) r->headers_in.content_length_n; r->headers_in.content_length_n = 0; } else { @@ -866,7 +866,7 @@ ngx_http_request_body_length_filter(ngx_http_request_t *r, ngx_chain_t *in) rb->rest -= size; } else { - cl->buf->pos += rb->rest; + cl->buf->pos += (size_t) rb->rest; rb->rest = 0; b->last = cl->buf->pos; b->last_buf = 1; @@ -972,7 +972,7 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in) size = cl->buf->last - cl->buf->pos; if ((off_t) size > rb->chunked->size) { - cl->buf->pos += rb->chunked->size; + cl->buf->pos += (size_t) rb->chunked->size; r->headers_in.content_length_n += rb->chunked->size; rb->chunked->size = 0; diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index 652222f8f..2321f6e97 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -1070,6 +1070,55 @@ ngx_http_upstream_check_broken_connection(ngx_http_request_t *r, #endif +#if (NGX_HAVE_EPOLLRDHUP) + + if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) && ev->pending_eof) { + socklen_t len; + + ev->eof = 1; + c->error = 1; + + err = 0; + len = sizeof(ngx_err_t); + + /* + * BSDs and Linux return 0 and set a pending error in err + * Solaris returns -1 and sets errno + */ + + if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len) + == -1) + { + err = ngx_errno; + } + + if (err) { + ev->error = 1; + } + + if (!u->cacheable && u->peer.connection) { + ngx_log_error(NGX_LOG_INFO, ev->log, err, + "epoll_wait() reported that client prematurely closed " + "connection, so upstream connection is closed too"); + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_CLIENT_CLOSED_REQUEST); + return; + } + + ngx_log_error(NGX_LOG_INFO, ev->log, err, + "epoll_wait() reported that client prematurely closed " + "connection"); + + if (u->peer.connection == NULL) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_CLIENT_CLOSED_REQUEST); + } + + return; + } + +#endif + n = recv(c->fd, buf, 1, MSG_PEEK); err = ngx_socket_errno; @@ -2105,6 +2154,8 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u) return; } + u->header_sent = 1; + if (u->upgrade) { ngx_http_upstream_upgrade(r, u); return; @@ -2131,8 +2182,6 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u) } } - u->header_sent = 1; - if (r->request_body && r->request_body->temp_file) { ngx_pool_run_cleanup_file(r->pool, r->request_body->temp_file->file.fd); r->request_body->temp_file->file.fd = NGX_INVALID_FILE; @@ -4309,7 +4358,7 @@ ngx_http_upstream_response_time_variable(ngx_http_request_t *r, ms = (ngx_msec_int_t) (state[i].response_sec * 1000 + state[i].response_msec); ms = ngx_max(ms, 0); - p = ngx_sprintf(p, "%d.%03d", ms / 1000, ms % 1000); + p = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000); } else { *p++ = '-'; diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c index 4138bda42..3ec038aef 100644 --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -1992,7 +1992,7 @@ ngx_http_variable_request_time(ngx_http_request_t *r, ((tp->sec - r->start_sec) * 1000 + (tp->msec - r->start_msec)); ms = ngx_max(ms, 0); - v->len = ngx_sprintf(p, "%T.%03M", ms / 1000, ms % 1000) - p; + v->len = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000) - p; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; diff --git a/src/os/unix/ngx_errno.h b/src/os/unix/ngx_errno.h index 1497c5f2f..6d1a4889a 100644 --- a/src/os/unix/ngx_errno.h +++ b/src/os/unix/ngx_errno.h @@ -50,6 +50,7 @@ typedef int ngx_err_t; #define NGX_EILSEQ EILSEQ #define NGX_ENOMOREFILES 0 #define NGX_ELOOP ELOOP +#define NGX_EBADF EBADF #if (NGX_HAVE_OPENAT) #define NGX_EMLINK EMLINK diff --git a/src/os/unix/ngx_files.h b/src/os/unix/ngx_files.h index 4e3ed7db4..df759df52 100644 --- a/src/os/unix/ngx_files.h +++ b/src/os/unix/ngx_files.h @@ -91,6 +91,9 @@ typedef struct { #elif defined(O_EXEC) #define NGX_FILE_SEARCH (O_EXEC|NGX_FILE_DIRECTORY) +#elif (NGX_HAVE_O_PATH) +#define NGX_FILE_SEARCH (O_PATH|O_RDONLY|NGX_FILE_DIRECTORY) + #else #define NGX_FILE_SEARCH (O_RDONLY|NGX_FILE_DIRECTORY) #endif diff --git a/src/os/unix/ngx_readv_chain.c b/src/os/unix/ngx_readv_chain.c index c2c21b407..8836c817d 100644 --- a/src/os/unix/ngx_readv_chain.c +++ b/src/os/unix/ngx_readv_chain.c @@ -129,6 +129,7 @@ ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain) "%d available bytes", rev->available); #endif + rev->ready = 0; rev->eof = 1; rev->available = 0; } diff --git a/src/os/unix/ngx_recv.c b/src/os/unix/ngx_recv.c index 1640cdb27..86675dfdd 100644 --- a/src/os/unix/ngx_recv.c +++ b/src/os/unix/ngx_recv.c @@ -80,6 +80,7 @@ ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size) * even if kqueue reported about available data */ + rev->ready = 0; rev->eof = 1; rev->available = 0; } |