Hello community, here is the log from the commit of package haproxy for openSUSE:Factory checked in at 2016-09-09 10:20:52 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/haproxy (Old) and /work/SRC/openSUSE:Factory/.haproxy.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "haproxy" Changes: -------- --- /work/SRC/openSUSE:Factory/haproxy/haproxy.changes 2016-08-03 11:43:12.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.haproxy.new/haproxy.changes 2016-09-09 10:20:53.000000000 +0200 @@ -1,0 +2,28 @@ +Thu Sep 1 07:16:13 UTC 2016 - kgronlund@suse.com + +- Update to 1.6.9 + - MINOR: cli: allow the semi-colon to be escaped on the CLI + - BUG/MINOR: payload: fix SSLv2 version parser + - BUG/MAJOR: stream: properly mark the server address as unset on connect retry + - DOC: Updated 51Degrees readme. + - BUG/MAJOR: stick-counters: possible crash when using sc_trackers with wrong table + - BUG/MINOR: peers: empty chunks after a resync. + - BUG/MINOR: peers: some updates are pushed twice after a resync. + - MINOR: sample: use smp_make_rw() in upper/lower converters + - BUG/MEDIUM: stick-table: properly convert binary samples to keys + - BUG/MEDIUM: stick-tables: do not fail on string keys with no allocated size + - BUG/MAJOR: server: the "sni" directive could randomly cause trouble + - MINOR: sample: provide smp_is_rw() and smp_make_rw() + - MINOR: sample: implement smp_is_safe() and smp_make_safe() + - BUG/MEDIUM: samples: make smp_dup() always duplicate the sample + - BUG/MAJOR: compression: initialize avail_in/next_in even during flush + - BUILD: make proto_tcp.c compatible with musl library + - DOC: minor typo fixes to improve HTML parsing by haproxy-dconv + - BUG/MEDIUM: stream-int: completely detach connection on connect error + - BUG/MEDIUM: lua: somme HTTP manipulation functions are called without valid requests + - DOC: lua: remove old functions + - BUG/MINOR: peers: Fix peers data decoding issue + - BUG/MEDIUM: lua: the function txn_done() from action wrapper can crash + - BUG/MEDIUM: lua: the function txn_done() from sample fetches can crash + +------------------------------------------------------------------- Old: ---- haproxy-1.6.7.tar.gz New: ---- haproxy-1.6.9.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ haproxy.spec ++++++ --- /var/tmp/diff_new_pack.Ri1yui/_old 2016-09-09 10:20:54.000000000 +0200 +++ /var/tmp/diff_new_pack.Ri1yui/_new 2016-09-09 10:20:54.000000000 +0200 @@ -41,7 +41,7 @@ %bcond_without apparmor Name: haproxy -Version: 1.6.7 +Version: 1.6.9 Release: 0 # # ++++++ haproxy-1.6.7.tar.gz -> haproxy-1.6.9.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.6.7/CHANGELOG new/haproxy-1.6.9/CHANGELOG --- old/haproxy-1.6.7/CHANGELOG 2016-07-13 19:57:01.000000000 +0200 +++ new/haproxy-1.6.9/CHANGELOG 2016-08-30 23:20:16.000000000 +0200 @@ -1,6 +1,33 @@ ChangeLog : =========== +2016/08/30 : 1.6.9 + - DOC: Updated 51Degrees readme. + - BUG/MAJOR: stream: properly mark the server address as unset on connect retry + - BUG/MINOR: payload: fix SSLv2 version parser + - MINOR: cli: allow the semi-colon to be escaped on the CLI + +2016/08/14 : 1.6.8 + - BUG/MEDIUM: lua: the function txn_done() from sample fetches can crash + - BUG/MEDIUM: lua: the function txn_done() from action wrapper can crash + - BUG/MINOR: peers: Fix peers data decoding issue + - DOC: lua: remove old functions + - BUG/MEDIUM: lua: somme HTTP manipulation functions are called without valid requests + - BUG/MEDIUM: stream-int: completely detach connection on connect error + - DOC: minor typo fixes to improve HTML parsing by haproxy-dconv + - BUILD: make proto_tcp.c compatible with musl library + - BUG/MAJOR: compression: initialize avail_in/next_in even during flush + - BUG/MEDIUM: samples: make smp_dup() always duplicate the sample + - MINOR: sample: implement smp_is_safe() and smp_make_safe() + - MINOR: sample: provide smp_is_rw() and smp_make_rw() + - BUG/MAJOR: server: the "sni" directive could randomly cause trouble + - BUG/MEDIUM: stick-tables: do not fail on string keys with no allocated size + - BUG/MEDIUM: stick-table: properly convert binary samples to keys + - MINOR: sample: use smp_make_rw() in upper/lower converters + - BUG/MINOR: peers: some updates are pushed twice after a resync. + - BUG/MINOR: peers: empty chunks after a resync. + - BUG/MAJOR: stick-counters: possible crash when using sc_trackers with wrong table + 2016/07/13 : 1.6.7 - MINOR: new function my_realloc2 = realloc + free upon failure - CLEANUP: fixed some usages of realloc leading to memory leak diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.6.7/README new/haproxy-1.6.9/README --- old/haproxy-1.6.7/README 2016-07-13 19:57:01.000000000 +0200 +++ new/haproxy-1.6.9/README 2016-08-30 23:20:16.000000000 +0200 @@ -3,7 +3,7 @@ ---------------------- version 1.6 willy tarreau - 2016/07/13 + 2016/08/30 1) How to build it @@ -295,7 +295,7 @@ In order to enable 51Degrees download the 51Degrees source code from the official github repository : - git clone https://github.com/51Degrees/Device-Detection + git clone https://github.com/51Degrees/Device-Detection -b v3.2.5 then run 'make' with USE_51DEGREES and 51DEGREES_SRC set. Both 51DEGREES_INC and 51DEGREES_LIB may additionally be used to force specific different paths diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.6.7/VERDATE new/haproxy-1.6.9/VERDATE --- old/haproxy-1.6.7/VERDATE 2016-07-13 19:57:01.000000000 +0200 +++ new/haproxy-1.6.9/VERDATE 2016-08-30 23:20:16.000000000 +0200 @@ -1,2 +1,2 @@ $Format:%ci$ -2016/07/13 +2016/08/30 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.6.7/VERSION new/haproxy-1.6.9/VERSION --- old/haproxy-1.6.7/VERSION 2016-07-13 19:57:01.000000000 +0200 +++ new/haproxy-1.6.9/VERSION 2016-08-30 23:20:16.000000000 +0200 @@ -1 +1 @@ -1.6.7 +1.6.9 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.6.7/doc/configuration.txt new/haproxy-1.6.9/doc/configuration.txt --- old/haproxy-1.6.7/doc/configuration.txt 2016-07-13 19:57:01.000000000 +0200 +++ new/haproxy-1.6.9/doc/configuration.txt 2016-08-30 23:20:16.000000000 +0200 @@ -4,7 +4,7 @@ ---------------------- version 1.6 willy tarreau - 2016/07/13 + 2016/08/30 This document covers the configuration language as implemented in the version @@ -4278,20 +4278,19 @@ - server's weight is applied from previous running process unless it has has changed between previous and new configuration files. - Example 1: + Example: Minimal configuration - Minimal configuration: + global + stats socket /tmp/socket + server-state-file /tmp/server_state + + defaults + load-server-state-from-file global + + backend bk + server s1 127.0.0.1:22 check weight 11 + server s2 127.0.0.1:22 check weight 12 - global - stats socket /tmp/socket - server-state-file /tmp/server_state - - defaults - load-server-state-from-file global - - backend bk - server s1 127.0.0.1:22 check weight 11 - server s2 127.0.0.1:22 check weight 12 Then one can run : @@ -4304,9 +4303,7 @@ 1 bk 1 s1 127.0.0.1 2 0 11 11 4 6 3 4 6 0 0 1 bk 2 s2 127.0.0.1 2 0 12 12 4 6 3 4 6 0 0 - Example 2: - - Minimal configuration: + Example: Minimal configuration global stats socket /tmp/socket @@ -4319,6 +4316,7 @@ server s1 127.0.0.1:22 check weight 11 server s2 127.0.0.1:22 check weight 12 + Then one can run : socat /tmp/socket - <<< "show servers state bk" > /etc/haproxy/states/bk @@ -5044,7 +5042,7 @@ the frontend or the backend does not specify it, it wants the addition to be mandatory, so it wins. - Examples : + Example : # Public HTTP address also used by stunnel on the same machine frontend www mode http @@ -10507,7 +10505,9 @@ Supported in default-server: Yes - Example: server s1 app1.domain.com:80 resolvers mydns resolve-prefer ipv6 + Example: + + server s1 app1.domain.com:80 resolvers mydns resolve-prefer ipv6 resolvers <id> Points to an existing "resolvers" section to resolve current server's @@ -10519,9 +10519,11 @@ Supported in default-server: No - Example: server s1 app1.domain.com:80 check resolvers mydns + Example: + + server s1 app1.domain.com:80 check resolvers mydns - See also chapter 5.3 + See also section 5.3 send-proxy The "send-proxy" parameter enforces use of the PROXY protocol over any @@ -10835,7 +10837,7 @@ <time> : time related to the event. It follows the HAProxy time format. <time> is expressed in milliseconds. -Example of a resolvers section (with default values): + Example: resolvers mydns nameserver dns1 10.0.0.1:53 @@ -14254,7 +14256,6 @@ 15 '{' captured_response_headers* '}' {} 16 '"' http_request '"' "GET /index.html HTTP/1.1" - Detailed fields description : - "client_ip" is the IP address of the client which initiated the TCP connection to haproxy. If the connection was accepted on a UNIX socket diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.6.7/doc/lua-api/index.rst new/haproxy-1.6.9/doc/lua-api/index.rst --- old/haproxy-1.6.7/doc/lua-api/index.rst 2016-07-13 19:57:01.000000000 +0200 +++ new/haproxy-1.6.9/doc/lua-api/index.rst 2016-08-30 23:20:16.000000000 +0200 @@ -856,32 +856,6 @@ :param string replace: The replacement value. :see: HTTP.req_replace_header() -.. js:function:: HTTP.req_replace_value(http, name, regex, replace) - - Works like "HTTP.req_replace_header()" except that it matches the regex - against every comma-delimited value of the header field "name" instead of the - entire header. - - :param class_http http: The related http object. - :param string name: The header name. - :param string regex: The match regular expression. - :param string replace: The replacement value. - :see: HTTP.req_replace_header() - :see: HTTP.res_replace_value() - -.. js:function:: HTTP.res_replace_value(http, name, regex, replace) - - Works like "HTTP.res_replace_header()" except that it matches the regex - against every comma-delimited value of the header field "name" instead of the - entire header. - - :param class_http http: The related http object. - :param string name: The header name. - :param string regex: The match regular expression. - :param string replace: The replacement value. - :see: HTTP.res_replace_header() - :see: HTTP.req_replace_value() - .. js:function:: HTTP.req_set_method(http, method) Rewrites the request method with the parameter "method". @@ -1100,6 +1074,11 @@ session. It can be used when a critical error is detected or to terminate processing after some data have been returned to the client (eg: a redirect). + *Warning*: It not make sense to call this function from sample-fetches. In + this case the behaviour of this one is the same than core.done(): it quit + the Lua execution. The transaction is really aborted only from an action + registered function. + :param class_txn txn: The class txn object containing the data. .. js:function:: TXN.set_loglevel(txn, loglevel) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.6.7/doc/management.txt new/haproxy-1.6.9/doc/management.txt --- old/haproxy-1.6.7/doc/management.txt 2016-07-13 19:57:01.000000000 +0200 +++ new/haproxy-1.6.9/doc/management.txt 2016-08-30 23:20:16.000000000 +0200 @@ -1056,6 +1056,9 @@ # echo "show info;show stat;show table" | socat /var/run/haproxy stdio +If a command needs to use a semi-colon (eg: in a value), it must be preceeded +by a backslash (''). + The interactive mode displays a prompt ('>') and waits for commands to be entered on the line, then processes them, and displays the prompt again to wait for a new command. This mode is entered via the "prompt" command which must be diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.6.7/examples/haproxy.spec new/haproxy-1.6.9/examples/haproxy.spec --- old/haproxy-1.6.7/examples/haproxy.spec 2016-07-13 19:57:01.000000000 +0200 +++ new/haproxy-1.6.9/examples/haproxy.spec 2016-08-30 23:20:16.000000000 +0200 @@ -1,6 +1,6 @@ Summary: HA-Proxy is a TCP/HTTP reverse proxy for high availability environments Name: haproxy -Version: 1.6.7 +Version: 1.6.9 Release: 1 License: GPL Group: System Environment/Daemons @@ -74,6 +74,12 @@ %attr(0755,root,root) %config %{_sysconfdir}/rc.d/init.d/%{name} %changelog +* Tue Aug 30 2016 Willy Tarreau <w@1wt.eu> +- updated to 1.6.9 + +* Sun Aug 14 2016 Willy Tarreau <w@1wt.eu> +- updated to 1.6.8 + * Wed Jul 13 2016 Willy Tarreau <w@1wt.eu> - updated to 1.6.7 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.6.7/include/proto/sample.h new/haproxy-1.6.9/include/proto/sample.h --- old/haproxy-1.6.7/include/proto/sample.h 2016-07-13 19:57:01.000000000 +0200 +++ new/haproxy-1.6.9/include/proto/sample.h 2016-08-30 23:20:16.000000000 +0200 @@ -74,4 +74,92 @@ return smp; } + +/* Returns 1 if a sample may be safely used. It performs a few checks on the + * string length versus size, same for the binary version, and ensures that + * strings are properly terminated by a zero. If this last point is not granted + * but the string is not const, then the \0 is appended. Otherwise it returns 0, + * meaning the caller may need to call smp_dup() before going further. + */ +static inline +int smp_is_safe(struct sample *smp) +{ + switch (smp->data.type) { + case SMP_T_STR: + if ((smp->data.u.str.len < 0) || + (smp->data.u.str.size && smp->data.u.str.len >= smp->data.u.str.size)) + return 0; + + if (smp->data.u.str.str[smp->data.u.str.len] == 0) + return 1; + + if (!smp->data.u.str.size || (smp->flags & SMP_F_CONST)) + return 0; + + smp->data.u.str.str[smp->data.u.str.len] = 0; + return 1; + + case SMP_T_BIN: + return (smp->data.u.str.len >= 0) && + (!smp->data.u.str.size || smp->data.u.str.len <= smp->data.u.str.size); + + default: + return 1; + } +} + +/* checks that a sample may freely be used, or duplicates it to normalize it. + * Returns 1 on success, 0 if the sample must not be used. The function also + * checks for NULL to simplify the calling code. + */ +static inline +int smp_make_safe(struct sample *smp) +{ + return smp && (smp_is_safe(smp) || smp_dup(smp)); +} + +/* Returns 1 if a sample may be safely modified in place. It performs a few + * checks on the string length versus size, same for the binary version, and + * ensures that strings are properly terminated by a zero, and of course that + * the size is allocate and that the SMP_F_CONST flag is not set. If only the + * trailing zero is missing, it is appended. Otherwise it returns 0, meaning + * the caller may need to call smp_dup() before going further. + */ +static inline +int smp_is_rw(struct sample *smp) +{ + if (smp->flags & SMP_F_CONST) + return 0; + + switch (smp->data.type) { + case SMP_T_STR: + if (!smp->data.u.str.size || + smp->data.u.str.len < 0 || + smp->data.u.str.len >= smp->data.u.str.size) + return 0; + + if (smp->data.u.str.str[smp->data.u.str.len] != 0) + smp->data.u.str.str[smp->data.u.str.len] = 0; + return 1; + + case SMP_T_BIN: + return smp->data.u.str.size && + smp->data.u.str.len >= 0 && + smp->data.u.str.len <= smp->data.u.str.size; + + default: + return 1; + } +} + +/* checks that a sample may freely be modified, or duplicates it to normalize + * it and make it R/W. Returns 1 on success, 0 if the sample must not be used. + * The function also checks for NULL to simplify the calling code. + */ +static inline +int smp_make_rw(struct sample *smp) +{ + return smp && (smp_is_rw(smp) || smp_dup(smp)); +} + #endif /* _PROTO_SAMPLE_H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.6.7/include/types/hlua.h new/haproxy-1.6.9/include/types/hlua.h --- old/haproxy-1.6.7/include/types/hlua.h 2016-07-13 19:57:01.000000000 +0200 +++ new/haproxy-1.6.9/include/types/hlua.h 2016-08-30 23:20:16.000000000 +0200 @@ -28,10 +28,13 @@ #define HLUA_WAKEREQWR 0x00000008 #define HLUA_EXIT 0x00000010 #define HLUA_MUST_GC 0x00000020 +#define HLUA_STOP 0x00000040 #define HLUA_F_AS_STRING 0x01 #define HLUA_F_MAY_USE_HTTP 0x02 +#define HLUA_TXN_NOTERM 0x00000001 + enum hlua_exec { HLUA_E_OK = 0, HLUA_E_AGAIN, /* LUA yield, must resume the stack execution later, when @@ -104,6 +107,7 @@ struct stream *s; struct proxy *p; int dir; /* SMP_OPT_DIR_{REQ,RES} */ + int flags; }; /* This struct contains the applet context. */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.6.7/include/types/sample.h new/haproxy-1.6.9/include/types/sample.h --- old/haproxy-1.6.7/include/types/sample.h 2016-07-13 19:57:01.000000000 +0200 +++ new/haproxy-1.6.9/include/types/sample.h 2016-08-30 23:20:16.000000000 +0200 @@ -236,6 +236,12 @@ void *a[8]; /* any array of up to 8 pointers */ }; +/* Note: the strings below make use of chunks. Chunks may carry an allocated + * size in addition to the length. The size counts from the beginning (str) + * to the end. If the size is unknown, it MUST be zero, in which case the + * sample will automatically be duplicated when a change larger than <len> has + * to be performed. Thus it is safe to always set size to zero. + */ struct meth { enum http_meth_t meth; struct chunk str; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.6.7/src/backend.c new/haproxy-1.6.9/src/backend.c --- old/haproxy-1.6.7/src/backend.c 2016-07-13 19:57:01.000000000 +0200 +++ new/haproxy-1.6.9/src/backend.c 2016-08-30 23:20:16.000000000 +0200 @@ -1217,12 +1217,7 @@ /* restore the pointers */ b_adv(s->req.buf, rewind); - if (smp) { - /* get write access to terminate with a zero */ - smp_dup(smp); - if (smp->data.u.str.len >= smp->data.u.str.size) - smp->data.u.str.len = smp->data.u.str.size - 1; - smp->data.u.str.str[smp->data.u.str.len] = 0; + if (smp_make_safe(smp)) { ssl_sock_set_servername(srv_conn, smp->data.u.str.str); srv_conn->flags |= CO_FL_PRIVATE; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.6.7/src/compression.c new/haproxy-1.6.9/src/compression.c --- old/haproxy-1.6.7/src/compression.c 2016-07-13 19:57:01.000000000 +0200 +++ new/haproxy-1.6.9/src/compression.c 2016-08-30 23:20:16.000000000 +0200 @@ -784,6 +784,8 @@ int out_len = 0; z_stream *strm = &comp_ctx->strm; + strm->next_in = NULL; + strm->avail_in = 0; strm->next_out = (unsigned char *)bi_end(out); strm->avail_out = out->size - buffer_len(out); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.6.7/src/dumpstats.c new/haproxy-1.6.9/src/dumpstats.c --- old/haproxy-1.6.7/src/dumpstats.c 2016-07-13 19:57:01.000000000 +0200 +++ new/haproxy-1.6.9/src/dumpstats.c 2016-08-30 23:20:16.000000000 +0200 @@ -2435,15 +2435,20 @@ continue; } - /* seek for a possible semi-colon. If we find one, we - * replace it with an LF and skip only this part. + /* seek for a possible unescaped semi-colon. If we find + * one, we replace it with an LF and skip only this part. */ - for (len = 0; len < reql; len++) + for (len = 0; len < reql; len++) { + if (trash.str[len] == '\') { + len++; + continue; + } if (trash.str[len] == ';') { trash.str[len] = '\n'; reql = len + 1; break; } + } /* now it is time to check that we have a full line, * remove the trailing \n and possibly \r, then cut the diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.6.7/src/hlua.c new/haproxy-1.6.9/src/hlua.c --- old/haproxy-1.6.7/src/hlua.c 2016-07-13 19:57:01.000000000 +0200 +++ new/haproxy-1.6.9/src/hlua.c 2016-08-30 23:20:16.000000000 +0200 @@ -4164,6 +4164,10 @@ if (!htxn->s->txn) return 1; + /* Check if a valid response is parsed */ + if (unlikely(msg->msg_state < HTTP_MSG_BODY)) + return 1; + /* Build array of headers. */ old_idx = 0; cur_next = msg->chn->buf->p + hdr_idx_first_pos(&htxn->s->txn->hdr_idx); @@ -4278,6 +4282,10 @@ const char *value = MAY_LJMP(luaL_checkstring(L, 4)); struct my_regex re; + /* Check if a valid response is parsed */ + if (unlikely(msg->msg_state < HTTP_MSG_BODY)) + return 0; + if (!regex_comp(reg, &re, 1, 1, NULL)) WILL_LJMP(luaL_argerror(L, 3, "invalid regex")); @@ -4336,6 +4344,10 @@ struct hdr_ctx ctx; struct http_txn *txn = htxn->s->txn; + /* Check if a valid response is parsed */ + if (unlikely(msg->msg_state < HTTP_MSG_BODY)) + return 0; + ctx.idx = 0; while (http_find_header2(name, len, msg->chn->buf->p, &txn->hdr_idx, &ctx)) http_remove_header2(msg, &txn->hdr_idx, &ctx); @@ -4373,6 +4385,10 @@ const char *value = MAY_LJMP(luaL_checklstring(L, 3, &value_len)); char *p; + /* Check if a valid message is parsed */ + if (unlikely(msg->msg_state < HTTP_MSG_BODY)) + return 0; + /* Check length. */ trash.len = value_len + name_len + 2; if (trash.len > trash.size) @@ -4443,6 +4459,12 @@ size_t name_len; const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len)); + /* Check if a valid request is parsed */ + if (unlikely(htxn->s->txn->req.msg_state < HTTP_MSG_BODY)) { + lua_pushboolean(L, 0); + return 1; + } + lua_pushboolean(L, http_replace_req_line(0, name, name_len, htxn->p, htxn->s) != -1); return 1; } @@ -4453,6 +4475,13 @@ struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1)); size_t name_len; const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len)); + + /* Check if a valid request is parsed */ + if (unlikely(htxn->s->txn->req.msg_state < HTTP_MSG_BODY)) { + lua_pushboolean(L, 0); + return 1; + } + lua_pushboolean(L, http_replace_req_line(1, name, name_len, htxn->p, htxn->s) != -1); return 1; } @@ -4464,6 +4493,12 @@ size_t name_len; const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len)); + /* Check if a valid request is parsed */ + if (unlikely(htxn->s->txn->req.msg_state < HTTP_MSG_BODY)) { + lua_pushboolean(L, 0); + return 1; + } + /* Check length. */ if (name_len > trash.size - 1) { lua_pushboolean(L, 0); @@ -4487,6 +4522,12 @@ size_t name_len; const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len)); + /* Check if a valid request is parsed */ + if (unlikely(htxn->s->txn->req.msg_state < HTTP_MSG_BODY)) { + lua_pushboolean(L, 0); + return 1; + } + lua_pushboolean(L, http_replace_req_line(3, name, name_len, htxn->p, htxn->s) != -1); return 1; } @@ -4497,6 +4538,10 @@ struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1)); unsigned int code = MAY_LJMP(luaL_checkinteger(L, 2)); + /* Check if a valid response is parsed */ + if (unlikely(htxn->s->txn->rsp.msg_state < HTTP_MSG_BODY)) + return 0; + http_set_status(code, htxn->s); return 0; } @@ -4610,7 +4655,7 @@ * return 0 if the stack does not contains free slots, * otherwise it returns 1. */ -static int hlua_txn_new(lua_State *L, struct stream *s, struct proxy *p, int dir) +static int hlua_txn_new(lua_State *L, struct stream *s, struct proxy *p, int dir, int flags) { struct hlua_txn *htxn; @@ -4630,6 +4675,7 @@ htxn->s = s; htxn->p = p; htxn->dir = dir; + htxn->flags = flags; /* Create the "f" field that contains a list of fetches. */ lua_pushstring(L, "f"); @@ -4818,10 +4864,21 @@ __LJMP static int hlua_txn_done(lua_State *L) { struct hlua_txn *htxn; + struct hlua *hlua; struct channel *ic, *oc; MAY_LJMP(check_args(L, 1, "close")); htxn = MAY_LJMP(hlua_checktxn(L, 1)); + hlua = hlua_gethlua(L); + + /* If the flags NOTERM is set, we cannot terminate the http + * session, so we just end the execution of the current + * lua code. + */ + if (htxn->flags & HLUA_TXN_NOTERM) { + WILL_LJMP(hlua_done(L)); + return 0; + } ic = &htxn->s->req; oc = &htxn->s->res; @@ -4856,6 +4913,7 @@ ic->analysers = 0; + hlua->flags |= HLUA_STOP; WILL_LJMP(hlua_done(L)); return 0; } @@ -5264,7 +5322,8 @@ lua_rawgeti(stream->hlua.T, LUA_REGISTRYINDEX, fcn->function_ref); /* push arguments in the stack. */ - if (!hlua_txn_new(stream->hlua.T, stream, smp->px, smp->opt & SMP_OPT_DIR)) { + if (!hlua_txn_new(stream->hlua.T, stream, smp->px, smp->opt & SMP_OPT_DIR, + HLUA_TXN_NOTERM)) { SEND_ERR(smp->px, "Lua sample-fetch '%s': full stack.\n", fcn->name); RESET_SAFE_LJMP(stream->hlua.T); return 0; @@ -5505,7 +5564,7 @@ lua_rawgeti(s->hlua.T, LUA_REGISTRYINDEX, rule->arg.hlua_rule->fcn.function_ref); /* Create and and push object stream in the stack. */ - if (!hlua_txn_new(s->hlua.T, s, px, dir)) { + if (!hlua_txn_new(s->hlua.T, s, px, dir, 0)) { SEND_ERR(px, "Lua function '%s': full stack.\n", rule->arg.hlua_rule->fcn.name); RESET_SAFE_LJMP(s->hlua.T); @@ -5538,6 +5597,8 @@ case HLUA_E_OK: if (!hlua_check_proto(s, dir)) return ACT_RET_ERR; + if (s->hlua.flags & HLUA_STOP) + return ACT_RET_STOP; return ACT_RET_CONT; /* yield. */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.6.7/src/payload.c new/haproxy-1.6.9/src/payload.c --- old/haproxy-1.6.7/src/payload.c 2016-07-13 19:57:01.000000000 +0200 +++ new/haproxy-1.6.9/src/payload.c 2016-08-30 23:20:16.000000000 +0200 @@ -435,7 +435,7 @@ /* long header format : 14 bits for length + pad length */ rlen = ((data[0] & 0x3F) << 8) | data[1]; plen = data[2]; - bleft -= 3; data += 2; + bleft -= 3; data += 3; } if (*data != 0x01) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.6.7/src/peers.c new/haproxy-1.6.9/src/peers.c --- old/haproxy-1.6.7/src/peers.c 2016-07-13 19:57:01.000000000 +0200 +++ new/haproxy-1.6.9/src/peers.c 2016-08-30 23:20:16.000000000 +0200 @@ -225,7 +225,7 @@ } i += (uint64_t)msg[idx] << (4 + 7*(idx-1)); } - while (msg[idx] > 128); + while (msg[idx] >= 128); *str = (char *)&msg[idx+1]; return i; } @@ -886,6 +886,7 @@ curpeer->confirm++; } else if (msg_head[1] == PEER_MSG_CTRL_RESYNCCONFIRM) { + struct shared_table *st; /* If stopping state */ if (stopping) { @@ -894,6 +895,10 @@ appctx->st0 = PEER_SESS_ST_END; goto switchstate; } + for (st = curpeer->tables; st; st = st->next) { + st->update = st->last_pushed = st->teaching_origin; + st->flags = 0; + } /* reset teaching flags to 0 */ curpeer->flags &= PEER_TEACH_RESET; @@ -1224,25 +1229,6 @@ } - /* Confirm finished or partial messages */ - while (curpeer->confirm) { - unsigned char msg[2]; - - /* There is a confirm messages to send */ - msg[0] = PEER_MSG_CLASS_CONTROL; - msg[1] = PEER_MSG_CTRL_RESYNCCONFIRM; - - /* message to buffer */ - repl = bi_putblk(si_ic(si), (char *)msg, sizeof(msg)); - if (repl <= 0) { - /* no more write possible */ - if (repl == -1) - goto full; - appctx->st0 = PEER_SESS_ST_END; - goto switchstate; - } - curpeer->confirm--; - } /* Need to request a resync */ @@ -1491,9 +1477,6 @@ /* push local updates */ if (!eb || eb->key > st->teaching_origin) { st->flags |= SHTABLE_F_TEACH_STAGE2; - eb = eb32_first(&st->table->updates); - if (eb) - st->last_pushed = eb->key - 1; break; } @@ -1550,6 +1533,26 @@ curpeer->flags |= PEER_F_TEACH_FINISHED; } + /* Confirm finished or partial messages */ + while (curpeer->confirm) { + unsigned char msg[2]; + + /* There is a confirm messages to send */ + msg[0] = PEER_MSG_CLASS_CONTROL; + msg[1] = PEER_MSG_CTRL_RESYNCCONFIRM; + + /* message to buffer */ + repl = bi_putblk(si_ic(si), (char *)msg, sizeof(msg)); + if (repl <= 0) { + /* no more write possible */ + if (repl == -1) + goto full; + appctx->st0 = PEER_SESS_ST_END; + goto switchstate; + } + curpeer->confirm--; + } + /* noting more to do */ goto out; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.6.7/src/proto_tcp.c new/haproxy-1.6.9/src/proto_tcp.c --- old/haproxy-1.6.7/src/proto_tcp.c 2016-07-13 19:57:01.000000000 +0200 +++ new/haproxy-1.6.9/src/proto_tcp.c 2016-08-30 23:20:16.000000000 +0200 @@ -10,6 +10,11 @@ * */ +/* this is to have tcp_info defined on systems using musl + * library, such as Alpine Linux + */ +#define _GNU_SOURCE + #include <ctype.h> #include <errno.h> #include <fcntl.h> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.6.7/src/sample.c new/haproxy-1.6.9/src/sample.c --- old/haproxy-1.6.7/src/sample.c 2016-07-13 19:57:01.000000000 +0200 +++ new/haproxy-1.6.9/src/sample.c 2016-08-30 23:20:16.000000000 +0200 @@ -637,7 +637,12 @@ return 1; } -/* This function duplicates data and removes the flag "const". */ +/* This function inconditionally duplicates data and removes the "const" flag. + * For strings and binary blocks, it also provides a known allocated size with + * a length that is capped to the size, and ensures a trailing zero is always + * appended for strings. This is necessary for some operations which may + * require to extend the length. It returns 0 if it fails, 1 on success. + */ int smp_dup(struct sample *smp) { struct chunk *trash; @@ -645,8 +650,6 @@ /* If the const flag is not set, we don't need to duplicate the * pattern as it can be modified in place. */ - if (!(smp->flags & SMP_F_CONST)) - return 1; switch (smp->data.type) { case SMP_T_BOOL: @@ -656,11 +659,24 @@ case SMP_T_IPV6: /* These type are not const. */ break; + case SMP_T_STR: + trash = get_trash_chunk(); + trash->len = smp->data.u.str.len; + if (trash->len > trash->size - 1) + trash->len = trash->size - 1; + + memcpy(trash->str, smp->data.u.str.str, trash->len); + trash->str[trash->len] = 0; + smp->data.u.str = *trash; + break; + case SMP_T_BIN: - /* Duplicate data. */ trash = get_trash_chunk(); - trash->len = smp->data.u.str.len < trash->size ? smp->data.u.str.len : trash->size; + trash->len = smp->data.u.str.len; + if (trash->len > trash->size) + trash->len = trash->size; + memcpy(trash->str, smp->data.u.str.str, trash->len); smp->data.u.str = *trash; break; @@ -1458,10 +1474,7 @@ { int i; - if (!smp_dup(smp)) - return 0; - - if (!smp->data.u.str.size) + if (!smp_make_rw(smp)) return 0; for (i = 0; i < smp->data.u.str.len; i++) { @@ -1475,10 +1488,7 @@ { int i; - if (!smp_dup(smp)) - return 0; - - if (!smp->data.u.str.size) + if (!smp_make_rw(smp)) return 0; for (i = 0; i < smp->data.u.str.len; i++) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.6.7/src/stick_table.c new/haproxy-1.6.9/src/stick_table.c --- old/haproxy-1.6.7/src/stick_table.c 2016-07-13 19:57:01.000000000 +0200 +++ new/haproxy-1.6.9/src/stick_table.c 2016-08-30 23:20:16.000000000 +0200 @@ -496,15 +496,8 @@ break; case SMP_T_STR: - /* Must be NULL terminated. */ - if (smp->data.u.str.len >= smp->data.u.str.size || - smp->data.u.str.str[smp->data.u.str.len] != '\0') { - if (!smp_dup(smp)) - return NULL; - if (smp->data.u.str.len >= smp->data.u.str.size) - return NULL; - smp->data.u.str.str[smp->data.u.str.len] = '\0'; - } + if (!smp_make_safe(smp)) + return NULL; static_table_key->key = smp->data.u.str.str; static_table_key->key_len = smp->data.u.str.len; break; @@ -512,6 +505,9 @@ case SMP_T_BIN: if (smp->data.u.str.len < t->key_size) { /* This type needs padding with 0. */ + if (!smp_make_rw(smp)) + return NULL; + if (smp->data.u.str.size < t->key_size) if (!smp_dup(smp)) return NULL; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.6.7/src/stream.c new/haproxy-1.6.9/src/stream.c --- old/haproxy-1.6.7/src/stream.c 2016-07-13 19:57:01.000000000 +0200 +++ new/haproxy-1.6.9/src/stream.c 2016-08-30 23:20:16.000000000 +0200 @@ -547,7 +547,6 @@ struct stream_interface *si = &s->si[1]; struct channel *req = &s->req; struct channel *rep = &s->res; - struct connection *srv_conn = __objt_conn(si->end); /* If we got an error, or if nothing happened and the connection timed * out, we must give up. The CER state handler will take care of retry @@ -567,7 +566,8 @@ si->exp = TICK_ETERNITY; si->state = SI_ST_CER; - conn_force_close(srv_conn); + si_release_endpoint(si); + s->flags &= ~SF_ADDR_SET; if (si->err_type) return 0; @@ -3297,7 +3297,7 @@ smp->flags = SMP_F_VOL_TEST; smp->data.type = SMP_T_SINT; - smp->data.u.sint = stkctr_entry(stkctr)->ref_cnt; + smp->data.u.sint = stkctr_entry(stkctr) ? stkctr_entry(stkctr)->ref_cnt : 0; return 1; }