Hello community,

here is the log from the commit of package haproxy for openSUSE:Factory checked 
in at 2016-06-14 23:07:07
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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-05-19 
12:15:08.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.haproxy.new/haproxy.changes     2016-06-14 
23:07:09.000000000 +0200
@@ -1,0 +2,19 @@
+Thu Jun  9 12:48:27 UTC 2016 - mrueck...@suse.de
+
+- pull patches from git to fix some important issues (bsc#983972) (bsc#983974):
+  0001-BUG-MAJOR-fix-listening-IP-address-storage-for-front.patch
+  0002-BUG-MINOR-fix-listening-IP-address-storage-for-front.patch
+  0003-DOC-Fix-typo-so-fetch-is-properly-parsed-by-Cyril-s-.patch
+  0004-BUG-MAJOR-http-fix-breakage-of-reqdeny-causing-rando.patch
+  0005-BUG-MEDIUM-stick-tables-fix-breakage-in-table-conver.patch
+  0006-BUG-MEDIUM-dns-unbreak-DNS-resolver-after-header-fix.patch
+  0007-BUILD-fix-build-on-Solaris-11.patch
+  0008-CLEANUP-connection-fix-double-negation-on-memcmp.patch
+  0009-BUG-MEDIUM-stats-show-servers-state-may-show-an-serv.patch
+  0010-BUG-MEDIUM-fix-risk-of-segfault-with-show-tls-keys.patch
+  0011-BUG-MEDIUM-sticktables-segfault-in-some-configuratio.patch
+  0012-BUG-MEDIUM-lua-converters-doesn-t-work.patch
+  0013-BUG-MINOR-http-add-header-header-name-copied-twice.patch
+  0014-BUG-MEDIUM-http-add-header-buffer-overwritten.patch
+
+-------------------------------------------------------------------

New:
----
  0001-BUG-MAJOR-fix-listening-IP-address-storage-for-front.patch
  0002-BUG-MINOR-fix-listening-IP-address-storage-for-front.patch
  0003-DOC-Fix-typo-so-fetch-is-properly-parsed-by-Cyril-s-.patch
  0004-BUG-MAJOR-http-fix-breakage-of-reqdeny-causing-rando.patch
  0005-BUG-MEDIUM-stick-tables-fix-breakage-in-table-conver.patch
  0006-BUG-MEDIUM-dns-unbreak-DNS-resolver-after-header-fix.patch
  0007-BUILD-fix-build-on-Solaris-11.patch
  0008-CLEANUP-connection-fix-double-negation-on-memcmp.patch
  0009-BUG-MEDIUM-stats-show-servers-state-may-show-an-serv.patch
  0010-BUG-MEDIUM-fix-risk-of-segfault-with-show-tls-keys.patch
  0011-BUG-MEDIUM-sticktables-segfault-in-some-configuratio.patch
  0012-BUG-MEDIUM-lua-converters-doesn-t-work.patch
  0013-BUG-MINOR-http-add-header-header-name-copied-twice.patch
  0014-BUG-MEDIUM-http-add-header-buffer-overwritten.patch

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ haproxy.spec ++++++
--- /var/tmp/diff_new_pack.qUmh2P/_old  2016-06-14 23:07:10.000000000 +0200
+++ /var/tmp/diff_new_pack.qUmh2P/_new  2016-06-14 23:07:10.000000000 +0200
@@ -74,6 +74,20 @@
 Patch1:         haproxy-1.6.0_config_haproxy_user.patch
 Patch2:         haproxy-1.6.0-makefile_lib.patch
 Patch3:         haproxy-1.6.0-sec-options.patch
+Patch11:        0001-BUG-MAJOR-fix-listening-IP-address-storage-for-front.patch
+Patch12:        0002-BUG-MINOR-fix-listening-IP-address-storage-for-front.patch
+Patch13:        0003-DOC-Fix-typo-so-fetch-is-properly-parsed-by-Cyril-s-.patch
+Patch14:        0004-BUG-MAJOR-http-fix-breakage-of-reqdeny-causing-rando.patch
+Patch15:        0005-BUG-MEDIUM-stick-tables-fix-breakage-in-table-conver.patch
+Patch16:        0006-BUG-MEDIUM-dns-unbreak-DNS-resolver-after-header-fix.patch
+Patch17:        0007-BUILD-fix-build-on-Solaris-11.patch
+Patch18:        0008-CLEANUP-connection-fix-double-negation-on-memcmp.patch
+Patch19:        0009-BUG-MEDIUM-stats-show-servers-state-may-show-an-serv.patch
+Patch20:        0010-BUG-MEDIUM-fix-risk-of-segfault-with-show-tls-keys.patch
+Patch21:        0011-BUG-MEDIUM-sticktables-segfault-in-some-configuratio.patch
+Patch22:        0012-BUG-MEDIUM-lua-converters-doesn-t-work.patch
+Patch23:        0013-BUG-MINOR-http-add-header-header-name-copied-twice.patch
+Patch24:        0014-BUG-MEDIUM-http-add-header-buffer-overwritten.patch
 #
 Source99:       haproxy-rpmlintrc
 #
@@ -107,6 +121,20 @@
 %patch1 -p1
 %patch2
 %patch3
+%patch11 -p1
+%patch12 -p1
+%patch13 -p1
+%patch14 -p1
+%patch15 -p1
+%patch16 -p1
+%patch17 -p1
+%patch18 -p1
+%patch19 -p1
+%patch20 -p1
+%patch21 -p1
+%patch22 -p1
+%patch23 -p1
+%patch24 -p1
 
 %build
 %{__make} \

++++++ 0001-BUG-MAJOR-fix-listening-IP-address-storage-for-front.patch ++++++
>From 66dd99c4c9d828c2c2f7295b7db66f7ff6f2fa8e Mon Sep 17 00:00:00 2001
From: Vincent Bernat <vinc...@bernat.im>
Date: Wed, 18 May 2016 16:17:44 +0200
Subject: [PATCH 01/14] BUG/MAJOR: fix listening IP address storage for
 frontends

When compiled with GCC 6, the IP address specified for a frontend was
ignored and HAProxy was listening on all addresses instead. This is
caused by an incomplete copy of a "struct sockaddr_storage".

With the GNU Libc, "struct sockaddr_storage" is defined as this:

    struct sockaddr_storage
      {
        sa_family_t ss_family;
        unsigned long int __ss_align;
        char __ss_padding[(128 - (2 * sizeof (unsigned long int)))];
      };

Doing an aggregate copy (ss1 = ss2) is different than using memcpy():
only members of the aggregate have to be copied. Notably, padding can be
or not be copied. In GCC 6, some optimizations use this fact and if a
"struct sockaddr_storage" contains a "struct sockaddr_in", the port and
the address are part of the padding (between sa_family and __ss_align)
and can be not copied over.

Therefore, we replace any aggregate copy by a memcpy(). There is another
place using the same pattern. We also fix a function receiving a "struct
sockaddr_storage" by copy instead of by reference. Since it only needs a
read-only copy, the function is converted to request a reference.

(cherry picked from commit 6e61589573f49b20a7184c9d297af1fc7d9184d8)
---
 include/proto/proto_http.h |  2 +-
 src/cfgparse.c             |  2 +-
 src/connection.c           |  2 +-
 src/hlua.c                 |  2 +-
 src/proto_http.c           | 12 ++++++------
 src/proto_tcp.c            |  2 +-
 6 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/include/proto/proto_http.h b/include/proto/proto_http.h
index a1b0cb3..4ed96e3 100644
--- a/include/proto/proto_http.h
+++ b/include/proto/proto_http.h
@@ -110,7 +110,7 @@ void http_set_status(unsigned int status, struct stream *s);
 int http_transform_header_str(struct stream* s, struct http_msg *msg, const 
char* name,
                               unsigned int name_len, const char *str, struct 
my_regex *re,
                               int action);
-void inet_set_tos(int fd, struct sockaddr_storage from, int tos);
+void inet_set_tos(int fd, const struct sockaddr_storage *from, int tos);
 void http_perform_server_redirect(struct stream *s, struct stream_interface 
*si);
 void http_return_srv_error(struct stream *s, struct stream_interface *si);
 void http_capture_bad_message(struct error_snapshot *es, struct stream *s,
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 97ec2e1..c118bd4 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -285,7 +285,7 @@ int str2listener(char *str, struct proxy *curproxy, struct 
bind_conf *bind_conf,
                }
 
                /* OK the address looks correct */
-               ss = *ss2;
+               memcpy(&ss, ss2, sizeof(ss));
 
                for (; port <= end; port++) {
                        l = (struct listener *)calloc(1, sizeof(struct 
listener));
diff --git a/src/connection.c b/src/connection.c
index b926e9f..991cae3 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -744,7 +744,7 @@ int make_proxy_line_v2(char *buf, int buf_len, struct 
server *srv, struct connec
        const char pp2_signature[] = PP2_SIGNATURE;
        int ret = 0;
        struct proxy_hdr_v2 *hdr = (struct proxy_hdr_v2 *)buf;
-       struct sockaddr_storage null_addr = {0};
+       struct sockaddr_storage null_addr = { .ss_family = 0 };
        struct sockaddr_storage *src = &null_addr;
        struct sockaddr_storage *dst = &null_addr;
 
diff --git a/src/hlua.c b/src/hlua.c
index 5ea3a83..edd288d 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -4790,7 +4790,7 @@ __LJMP static int hlua_txn_set_tos(lua_State *L)
        tos = MAY_LJMP(luaL_checkinteger(L, 2));
 
        if ((cli_conn = objt_conn(htxn->s->sess->origin)) && 
conn_ctrl_ready(cli_conn))
-               inet_set_tos(cli_conn->t.sock.fd, cli_conn->addr.from, tos);
+               inet_set_tos(cli_conn->t.sock.fd, &cli_conn->addr.from, tos);
 
        return 0;
 }
diff --git a/src/proto_http.c b/src/proto_http.c
index 9de1a17..59cd5d2 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -3403,15 +3403,15 @@ int http_handle_stats(struct stream *s, struct channel 
*req)
 /* Sets the TOS header in IPv4 and the traffic class header in IPv6 packets
  * (as per RFC3260 #4 and BCP37 #4.2 and #5.2).
  */
-void inet_set_tos(int fd, struct sockaddr_storage from, int tos)
+void inet_set_tos(int fd, const struct sockaddr_storage *from, int tos)
 {
 #ifdef IP_TOS
-       if (from.ss_family == AF_INET)
+       if (from->ss_family == AF_INET)
                setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
 #endif
 #ifdef IPV6_TCLASS
-       if (from.ss_family == AF_INET6) {
-               if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 
*)&from)->sin6_addr))
+       if (from->ss_family == AF_INET6) {
+               if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 
*)from)->sin6_addr))
                        /* v4-mapped addresses need IP_TOS */
                        setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
                else
@@ -3577,7 +3577,7 @@ resume_execution:
 
                case ACT_HTTP_SET_TOS:
                        if ((cli_conn = objt_conn(sess->origin)) && 
conn_ctrl_ready(cli_conn))
-                               inet_set_tos(cli_conn->t.sock.fd, 
cli_conn->addr.from, rule->arg.tos);
+                               inet_set_tos(cli_conn->t.sock.fd, 
&cli_conn->addr.from, rule->arg.tos);
                        break;
 
                case ACT_HTTP_SET_MARK:
@@ -3860,7 +3860,7 @@ resume_execution:
 
                case ACT_HTTP_SET_TOS:
                        if ((cli_conn = objt_conn(sess->origin)) && 
conn_ctrl_ready(cli_conn))
-                               inet_set_tos(cli_conn->t.sock.fd, 
cli_conn->addr.from, rule->arg.tos);
+                               inet_set_tos(cli_conn->t.sock.fd, 
&cli_conn->addr.from, rule->arg.tos);
                        break;
 
                case ACT_HTTP_SET_MARK:
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index cce0acb..59cfea2 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -435,7 +435,7 @@ int tcp_connect_server(struct connection *conn, int data, 
int delack)
                        struct sockaddr_storage sa;
 
                        ret = 1;
-                       sa = src->source_addr;
+                       memcpy(&sa, &src->source_addr, sizeof(sa));
 
                        do {
                                /* note: in case of retry, we may have to 
release a previously
-- 
2.6.6

++++++ 0002-BUG-MINOR-fix-listening-IP-address-storage-for-front.patch ++++++
>From 254646083703fba5cc86cba31118e20f45784ce6 Mon Sep 17 00:00:00 2001
From: Vincent Bernat <vinc...@bernat.im>
Date: Thu, 19 May 2016 11:29:43 +0200
Subject: [PATCH 02/14] BUG/MINOR: fix listening IP address storage for
 frontends (cont)

Commit 6e6158 was incomplete. There was an additional aggregate copy
that may trigger a similar case in the future.

(cherry picked from commit 6e46ff11e9c0d0b9266226ad911362c8a62ee458)
---
 src/cfgparse.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/cfgparse.c b/src/cfgparse.c
index c118bd4..b0f837e 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -296,7 +296,7 @@ int str2listener(char *str, struct proxy *curproxy, struct 
bind_conf *bind_conf,
                        l->bind_conf = bind_conf;
 
                        l->fd = fd;
-                       l->addr = ss;
+                       memcpy(&l->addr, &ss, sizeof(ss));
                        l->xprt = &raw_sock;
                        l->state = LI_INIT;
 
-- 
2.6.6

++++++ 0003-DOC-Fix-typo-so-fetch-is-properly-parsed-by-Cyril-s-.patch ++++++
>From 0c60f3790d6f177f123d4ae63d5f17868c789d12 Mon Sep 17 00:00:00 2001
From: Nenad Merdanovic <nmer...@anine.io>
Date: Tue, 17 May 2016 03:31:21 +0200
Subject: [PATCH 03/14] DOC: Fix typo so fetch is properly parsed by Cyril's
 converter

Signed-off-by: Nenad Merdanovic <nmer...@anine.io>
(cherry picked from commit 1516fe31dddc9f50a8783db496072ea67db0adde)
---
 doc/configuration.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/doc/configuration.txt b/doc/configuration.txt
index 38bde30..d51d741 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -13043,7 +13043,7 @@ ssl_fc_has_sni : boolean
   that the SSL library is build with support for TLS extensions enabled (check
   haproxy -vv).
 
-ssl_fc_is_resumed: boolean
+ssl_fc_is_resumed : boolean
   Returns true if the SSL/TLS session has been resumed through the use of
   SSL session cache or TLS tickets.
 
-- 
2.6.6

++++++ 0004-BUG-MAJOR-http-fix-breakage-of-reqdeny-causing-rando.patch ++++++
>From 60f01f8c89e4fb2723d5a9f2046286e699567e0b Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w...@1wt.eu>
Date: Wed, 25 May 2016 16:23:59 +0200
Subject: [PATCH 04/14] BUG/MAJOR: http: fix breakage of "reqdeny" causing
 random crashes

Commit 108b1dd ("MEDIUM: http: configurable http result codes for
http-request deny") introduced in 1.6-dev2 was incomplete. It introduced
a new field "rule_deny_status" into struct http_txn, which is filled only
by actions "http-request deny" and "http-request tarpit". It's then used
in the deny code path to emit the proper error message, but is used
uninitialized when the deny comes from a "reqdeny" rule, causing random
behaviours ranging from returning a 200, an empty response, or crashing
the process. Often upon startup only 200 was returned but after the fields
are used the crash happens. This can be sped up using -dM.

There's no need at all for storing this status in the http_txn struct
anyway since it's used immediately after being set. Let's store it in
a temporary variable instead which is passed as an argument to function
http_req_get_intercept_rule().

As an extra benefit, removing it from struct http_txn reduced the size
of this struct by 8 bytes.

This fix must be backported to 1.6 where the bug was detected. Special
thanks to Falco Schmutz for his detailed report including an exploitable
core and a reproducer.
(cherry picked from commit 58727ec088e55f739b146cff3baa955f8d1b2a3e)
---
 include/types/proto_http.h |  1 -
 src/proto_http.c           | 21 +++++++++++++--------
 2 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/include/types/proto_http.h b/include/types/proto_http.h
index e5e9667..c3a73ef 100644
--- a/include/types/proto_http.h
+++ b/include/types/proto_http.h
@@ -362,7 +362,6 @@ struct http_txn {
        unsigned int flags;             /* transaction flags */
        enum http_meth_t meth;          /* HTTP method */
        /* 1 unused byte here */
-       short rule_deny_status;         /* HTTP status from rule when denying */
        short status;                   /* HTTP status from the server, 
negative if from proxy */
 
        char *uri;                      /* first line if log needed, NULL 
otherwise */
diff --git a/src/proto_http.c b/src/proto_http.c
index 59cd5d2..6eac62b 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -3490,10 +3490,12 @@ static int http_transform_header(struct stream* s, 
struct http_msg *msg,
  * further processing of the request (auth, deny, ...), and defaults to
  * HTTP_RULE_RES_STOP if it executed all rules or stopped on an allow, or
  * HTTP_RULE_RES_CONT if the last rule was reached. It may set the TX_CLTARPIT
- * on txn->flags if it encounters a tarpit rule.
+ * on txn->flags if it encounters a tarpit rule. If <deny_status> is not NULL
+ * and a deny/tarpit rule is matched, it will be filled with this rule's deny
+ * status.
  */
 enum rule_result
-http_req_get_intercept_rule(struct proxy *px, struct list *rules, struct 
stream *s)
+http_req_get_intercept_rule(struct proxy *px, struct list *rules, struct 
stream *s, int *deny_status)
 {
        struct session *sess = strm_sess(s);
        struct http_txn *txn = s->txn;
@@ -3539,12 +3541,14 @@ resume_execution:
                        return HTTP_RULE_RES_STOP;
 
                case ACT_ACTION_DENY:
-                       txn->rule_deny_status = rule->deny_status;
+                       if (deny_status)
+                               *deny_status = rule->deny_status;
                        return HTTP_RULE_RES_DENY;
 
                case ACT_HTTP_REQ_TARPIT:
                        txn->flags |= TX_CLTARPIT;
-                       txn->rule_deny_status = rule->deny_status;
+                       if (deny_status)
+                               *deny_status = rule->deny_status;
                        return HTTP_RULE_RES_DENY;
 
                case ACT_HTTP_REQ_AUTH:
@@ -4303,6 +4307,7 @@ int http_process_req_common(struct stream *s, struct 
channel *req, int an_bit, s
        struct redirect_rule *rule;
        struct cond_wordlist *wl;
        enum rule_result verdict;
+       int deny_status = HTTP_ERR_403;
 
        if (unlikely(msg->msg_state < HTTP_MSG_BODY)) {
                /* we need more data */
@@ -4323,7 +4328,7 @@ int http_process_req_common(struct stream *s, struct 
channel *req, int an_bit, s
 
        /* evaluate http-request rules */
        if (!LIST_ISEMPTY(&px->http_req_rules)) {
-               verdict = http_req_get_intercept_rule(px, &px->http_req_rules, 
s);
+               verdict = http_req_get_intercept_rule(px, &px->http_req_rules, 
s, &deny_status);
 
                switch (verdict) {
                case HTTP_RULE_RES_YIELD: /* some data miss, call the function 
later. */
@@ -4369,7 +4374,7 @@ int http_process_req_common(struct stream *s, struct 
channel *req, int an_bit, s
 
                /* parse the whole stats request and extract the relevant 
information */
                http_handle_stats(s, req);
-               verdict = http_req_get_intercept_rule(px, 
&px->uri_auth->http_req_rules, s);
+               verdict = http_req_get_intercept_rule(px, 
&px->uri_auth->http_req_rules, s, &deny_status);
                /* not all actions implemented: deny, allow, auth */
 
                if (verdict == HTTP_RULE_RES_DENY) /* stats http-request deny */
@@ -4500,9 +4505,9 @@ int http_process_req_common(struct stream *s, struct 
channel *req, int an_bit, s
                manage_client_side_cookies(s, req);
 
        txn->flags |= TX_CLDENY;
-       txn->status = http_err_codes[txn->rule_deny_status];
+       txn->status = http_err_codes[deny_status];
        s->logs.tv_request = now;
-       stream_int_retnclose(&s->si[0], http_error_message(s, 
txn->rule_deny_status));
+       stream_int_retnclose(&s->si[0], http_error_message(s, deny_status));
        stream_inc_http_err_ctr(s);
        sess->fe->fe_counters.denied_req++;
        if (sess->fe != s->be)
-- 
2.6.6

++++++ 0005-BUG-MEDIUM-stick-tables-fix-breakage-in-table-conver.patch ++++++
>From 5a009af68013ac3f08fd08dad27b5d8ad038724c Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w...@1wt.eu>
Date: Wed, 25 May 2016 17:07:56 +0200
Subject: [PATCH 05/14] BUG/MEDIUM: stick-tables: fix breakage in table
 converters

Baptiste reported that the table_conn_rate() converter would always
return zero in 1.6.5. In fact, commit bc8c404 ("MAJOR: stick-tables:
use sample types in place of dedicated types") broke all stick-table
converters because smp_to_stkey() now returns a pointer to the sample
instead of holding a copy of the key, and the converters used to
reinitialize the sample prior to performing the lookup. Only
"in_table()" continued to work.

The construct is still fragile, so some comments were added to a few
function to clarify their impacts. It's also worth noting that there
is no point anymore in forcing these converters to take a string on
input, but that will be changed in another commit.

The bug was introduced in 1.6-dev4, this fix must be backported to 1.6.
(cherry picked from commit f0c730a0ac21a64af666ffa32a336db2c6f56d1b)
---
 src/stick_table.c | 56 +++++++++++++++++++++++++++++++++++++------------------
 1 file changed, 38 insertions(+), 18 deletions(-)

diff --git a/src/stick_table.c b/src/stick_table.c
index e5bb168..3e816b2 100644
--- a/src/stick_table.c
+++ b/src/stick_table.c
@@ -461,6 +461,8 @@ int stktable_parse_type(char **args, int *myidx, unsigned 
long *type, size_t *ke
 }
 
 /* Prepares a stktable_key from a sample <smp> to search into table <t>.
+ * Note that the sample *is* modified and that the returned key may point
+ * to it, so the sample must not be modified afterwards before the lookup.
  * Returns NULL if the sample could not be converted (eg: no matching type),
  * otherwise a pointer to the static stktable_key filled with what is needed
  * for the lookup.
@@ -700,11 +702,12 @@ static int sample_conv_table_bytes_in_rate(const struct 
arg *arg_p, struct sampl
        if (!key)
                return 0;
 
+       ts = stktable_lookup_key(t, key);
+
        smp->flags = SMP_F_VOL_TEST;
        smp->data.type = SMP_T_SINT;
        smp->data.u.sint = 0;
 
-       ts = stktable_lookup_key(t, key);
        if (!ts) /* key not present */
                return 1;
 
@@ -736,11 +739,12 @@ static int sample_conv_table_conn_cnt(const struct arg 
*arg_p, struct sample *sm
        if (!key)
                return 0;
 
+       ts = stktable_lookup_key(t, key);
+
        smp->flags = SMP_F_VOL_TEST;
        smp->data.type = SMP_T_SINT;
        smp->data.u.sint = 0;
 
-       ts = stktable_lookup_key(t, key);
        if (!ts) /* key not present */
                return 1;
 
@@ -771,11 +775,12 @@ static int sample_conv_table_conn_cur(const struct arg 
*arg_p, struct sample *sm
        if (!key)
                return 0;
 
+       ts = stktable_lookup_key(t, key);
+
        smp->flags = SMP_F_VOL_TEST;
        smp->data.type = SMP_T_SINT;
        smp->data.u.sint = 0;
 
-       ts = stktable_lookup_key(t, key);
        if (!ts) /* key not present */
                return 1;
 
@@ -806,11 +811,12 @@ static int sample_conv_table_conn_rate(const struct arg 
*arg_p, struct sample *s
        if (!key)
                return 0;
 
+       ts = stktable_lookup_key(t, key);
+
        smp->flags = SMP_F_VOL_TEST;
        smp->data.type = SMP_T_SINT;
        smp->data.u.sint = 0;
 
-       ts = stktable_lookup_key(t, key);
        if (!ts) /* key not present */
                return 1;
 
@@ -842,11 +848,12 @@ static int sample_conv_table_bytes_out_rate(const struct 
arg *arg_p, struct samp
        if (!key)
                return 0;
 
+       ts = stktable_lookup_key(t, key);
+
        smp->flags = SMP_F_VOL_TEST;
        smp->data.type = SMP_T_SINT;
        smp->data.u.sint = 0;
 
-       ts = stktable_lookup_key(t, key);
        if (!ts) /* key not present */
                return 1;
 
@@ -878,11 +885,12 @@ static int sample_conv_table_gpt0(const struct arg 
*arg_p, struct sample *smp, v
        if (!key)
                return 0;
 
+       ts = stktable_lookup_key(t, key);
+
        smp->flags = SMP_F_VOL_TEST;
        smp->data.type = SMP_T_SINT;
        smp->data.u.sint = 0;
 
-       ts = stktable_lookup_key(t, key);
        if (!ts) /* key not present */
                return 1;
 
@@ -913,11 +921,12 @@ static int sample_conv_table_gpc0(const struct arg 
*arg_p, struct sample *smp, v
        if (!key)
                return 0;
 
+       ts = stktable_lookup_key(t, key);
+
        smp->flags = SMP_F_VOL_TEST;
        smp->data.type = SMP_T_SINT;
        smp->data.u.sint = 0;
 
-       ts = stktable_lookup_key(t, key);
        if (!ts) /* key not present */
                return 1;
 
@@ -948,11 +957,12 @@ static int sample_conv_table_gpc0_rate(const struct arg 
*arg_p, struct sample *s
        if (!key)
                return 0;
 
+       ts = stktable_lookup_key(t, key);
+
        smp->flags = SMP_F_VOL_TEST;
        smp->data.type = SMP_T_SINT;
        smp->data.u.sint = 0;
 
-       ts = stktable_lookup_key(t, key);
        if (!ts) /* key not present */
                return 1;
 
@@ -984,11 +994,12 @@ static int sample_conv_table_http_err_cnt(const struct 
arg *arg_p, struct sample
        if (!key)
                return 0;
 
+       ts = stktable_lookup_key(t, key);
+
        smp->flags = SMP_F_VOL_TEST;
        smp->data.type = SMP_T_SINT;
        smp->data.u.sint = 0;
 
-       ts = stktable_lookup_key(t, key);
        if (!ts) /* key not present */
                return 1;
 
@@ -1019,11 +1030,12 @@ static int sample_conv_table_http_err_rate(const struct 
arg *arg_p, struct sampl
        if (!key)
                return 0;
 
+       ts = stktable_lookup_key(t, key);
+
        smp->flags = SMP_F_VOL_TEST;
        smp->data.type = SMP_T_SINT;
        smp->data.u.sint = 0;
 
-       ts = stktable_lookup_key(t, key);
        if (!ts) /* key not present */
                return 1;
 
@@ -1055,11 +1067,12 @@ static int sample_conv_table_http_req_cnt(const struct 
arg *arg_p, struct sample
        if (!key)
                return 0;
 
+       ts = stktable_lookup_key(t, key);
+
        smp->flags = SMP_F_VOL_TEST;
        smp->data.type = SMP_T_SINT;
        smp->data.u.sint = 0;
 
-       ts = stktable_lookup_key(t, key);
        if (!ts) /* key not present */
                return 1;
 
@@ -1090,11 +1103,12 @@ static int sample_conv_table_http_req_rate(const struct 
arg *arg_p, struct sampl
        if (!key)
                return 0;
 
+       ts = stktable_lookup_key(t, key);
+
        smp->flags = SMP_F_VOL_TEST;
        smp->data.type = SMP_T_SINT;
        smp->data.u.sint = 0;
 
-       ts = stktable_lookup_key(t, key);
        if (!ts) /* key not present */
                return 1;
 
@@ -1126,11 +1140,12 @@ static int sample_conv_table_kbytes_in(const struct arg 
*arg_p, struct sample *s
        if (!key)
                return 0;
 
+       ts = stktable_lookup_key(t, key);
+
        smp->flags = SMP_F_VOL_TEST;
        smp->data.type = SMP_T_SINT;
        smp->data.u.sint = 0;
 
-       ts = stktable_lookup_key(t, key);
        if (!ts) /* key not present */
                return 1;
 
@@ -1161,11 +1176,12 @@ static int sample_conv_table_kbytes_out(const struct 
arg *arg_p, struct sample *
        if (!key)
                return 0;
 
+       ts = stktable_lookup_key(t, key);
+
        smp->flags = SMP_F_VOL_TEST;
        smp->data.type = SMP_T_SINT;
        smp->data.u.sint = 0;
 
-       ts = stktable_lookup_key(t, key);
        if (!ts) /* key not present */
                return 1;
 
@@ -1196,11 +1212,12 @@ static int sample_conv_table_server_id(const struct arg 
*arg_p, struct sample *s
        if (!key)
                return 0;
 
+       ts = stktable_lookup_key(t, key);
+
        smp->flags = SMP_F_VOL_TEST;
        smp->data.type = SMP_T_SINT;
        smp->data.u.sint = 0;
 
-       ts = stktable_lookup_key(t, key);
        if (!ts) /* key not present */
                return 1;
 
@@ -1231,11 +1248,12 @@ static int sample_conv_table_sess_cnt(const struct arg 
*arg_p, struct sample *sm
        if (!key)
                return 0;
 
+       ts = stktable_lookup_key(t, key);
+
        smp->flags = SMP_F_VOL_TEST;
        smp->data.type = SMP_T_SINT;
        smp->data.u.sint = 0;
 
-       ts = stktable_lookup_key(t, key);
        if (!ts) /* key not present */
                return 1;
 
@@ -1266,11 +1284,12 @@ static int sample_conv_table_sess_rate(const struct arg 
*arg_p, struct sample *s
        if (!key)
                return 0;
 
+       ts = stktable_lookup_key(t, key);
+
        smp->flags = SMP_F_VOL_TEST;
        smp->data.type = SMP_T_SINT;
        smp->data.u.sint = 0;
 
-       ts = stktable_lookup_key(t, key);
        if (!ts) /* key not present */
                return 1;
 
@@ -1301,11 +1320,12 @@ static int sample_conv_table_trackers(const struct arg 
*arg_p, struct sample *sm
        if (!key)
                return 0;
 
+       ts = stktable_lookup_key(t, key);
+
        smp->flags = SMP_F_VOL_TEST;
        smp->data.type = SMP_T_SINT;
        smp->data.u.sint = 0;
 
-       ts = stktable_lookup_key(t, key);
        if (ts)
                smp->data.u.sint = ts->ref_cnt;
 
-- 
2.6.6

++++++ 0006-BUG-MEDIUM-dns-unbreak-DNS-resolver-after-header-fix.patch ++++++
>From 5f60de08667c3472d95cc20b87753e9fd8520057 Mon Sep 17 00:00:00 2001
From: Lukas Tribus <luky...@hotmail.com>
Date: Wed, 25 May 2016 22:15:11 +0200
Subject: [PATCH 06/14] BUG/MEDIUM: dns: unbreak DNS resolver after header fix

DNS requests (using the internal resolver) are corrupted since commit
e2f84977165a ("BUG/MINOR: dns: fix DNS header definition").

Fix it by defining the struct in network byte order, while complying
with RFC 2535, section 6.1.

First reported by Eduard Vopicka on discourse.

This must be backported to 1.6 (1.6.5 is affected).
(cherry picked from commit f2ebcb47cbf2af36236fde807c0c21a22d7c1e79)
---
 include/types/dns.h | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/include/types/dns.h b/include/types/dns.h
index e3d2f6b..15fc01b 100644
--- a/include/types/dns.h
+++ b/include/types/dns.h
@@ -58,16 +58,16 @@
 /* DNS request or response header structure */
 struct dns_header {
        unsigned short  id:16;          /* identifier */
-       unsigned char   qr :1;          /* query/response 0: query, 1: response 
*/
-       unsigned char   opcode :4;      /* operation code */
-       unsigned char   aa :1;          /* authoritative answer 0: no, 1: yes */
-       unsigned char   tc :1;          /* truncation 0:no, 1: yes */
        unsigned char   rd :1;          /* recursion desired 0: no, 1: yes */
-       unsigned char   ra :1;          /* recursion available 0: no, 1: yes */
-       unsigned char   z :1;           /* not used */
-       unsigned char   ad :1;          /* authentic data */
-       unsigned char   cd :1;          /* checking disabled */
+       unsigned char   tc :1;          /* truncation 0:no, 1: yes */
+       unsigned char   aa :1;          /* authoritative answer 0: no, 1: yes */
+       unsigned char   opcode :4;      /* operation code */
+       unsigned char   qr :1;          /* query/response 0: query, 1: response 
*/
        unsigned char   rcode :4;       /* response code */
+       unsigned char   cd :1;          /* checking disabled */
+       unsigned char   ad :1;          /* authentic data */
+       unsigned char   z :1;           /* not used */
+       unsigned char   ra :1;          /* recursion available 0: no, 1: yes */
        unsigned short  qdcount :16;    /* question count */
        unsigned short  ancount :16;    /* answer count */
        unsigned short  nscount :16;    /* authority count */
-- 
2.6.6

++++++ 0007-BUILD-fix-build-on-Solaris-11.patch ++++++
>From a71fda4bf6c3e57997a3873a8bdb2b295b2299a2 Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w...@1wt.eu>
Date: Fri, 20 May 2016 06:29:59 +0200
Subject: [PATCH 07/14] BUILD: fix build on Solaris 11

htonll()/ntohll() already exist on Solaris 11 with a different declaration,
causing a build error as reported by Jonathan Fisher. They used to exist on
OSX with a #define which allowed us to detect them. It was a bad idea to give
these functions a name subject to conflicts like this. Simply rename them
my_htonll()/my_ntohll() to definitely get rid of the conflict.

This patch must be backported to 1.6.

(cherry picked from commit 5f6e9054b920b9952baa9860c6ead1039c66e940)
---
 include/common/standard.h | 10 +++-------
 src/sample.c              |  2 +-
 2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/include/common/standard.h b/include/common/standard.h
index 2cc9f45..88776df 100644
--- a/include/common/standard.h
+++ b/include/common/standard.h
@@ -1009,8 +1009,7 @@ static inline unsigned char utf8_return_length(unsigned 
char code)
  * the whole code is optimized out. In little endian, with a decent compiler,
  * a few bswap and 2 shifts are left, which is the minimum acceptable.
  */
-#ifndef htonll
-static inline unsigned long long htonll(unsigned long long a)
+static inline unsigned long long my_htonll(unsigned long long a)
 {
        union {
                struct {
@@ -1021,15 +1020,12 @@ static inline unsigned long long htonll(unsigned long 
long a)
        } w = { .by64 = a };
        return ((unsigned long long)htonl(w.by32.w1) << 32) | htonl(w.by32.w2);
 }
-#endif
 
 /* Turns 64-bit value <a> from network byte order to host byte order. */
-#ifndef ntohll
-static inline unsigned long long ntohll(unsigned long long a)
+static inline unsigned long long my_ntohll(unsigned long long a)
 {
-       return htonll(a);
+       return my_htonll(a);
 }
-#endif
 
 /* returns a 64-bit a timestamp with the finest resolution available. The
  * unit is intentionally not specified. It's mostly used to compare dates.
diff --git a/src/sample.c b/src/sample.c
index ecea85e..527ff62 100644
--- a/src/sample.c
+++ b/src/sample.c
@@ -765,7 +765,7 @@ static int c_int2bin(struct sample *smp)
 {
        struct chunk *chk = get_trash_chunk();
 
-       *(unsigned long long int *)chk->str = htonll(smp->data.u.sint);
+       *(unsigned long long int *)chk->str = my_htonll(smp->data.u.sint);
        chk->len = 8;
 
        smp->data.u.str = *chk;
-- 
2.6.6

++++++ 0008-CLEANUP-connection-fix-double-negation-on-memcmp.patch ++++++
>From c4809151b4c9ccc312cb451e99fd556e867242fc Mon Sep 17 00:00:00 2001
From: David CARLIER <devne...@gmail.com>
Date: Thu, 24 Mar 2016 09:22:36 +0000
Subject: [PATCH 08/14] CLEANUP: connection: fix double negation on memcmp()

Nothing harmful in here, just clarify that it applies to the whole
expression.

(cherry picked from commit 42ff05e2d3d10e8a1e070e66e8883c5eabe196d7)
---
 src/connection.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/connection.c b/src/connection.c
index 991cae3..5515188 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -385,7 +385,7 @@ int conn_recv_proxy(struct connection *conn, int flag)
        if (trash.len < 9) /* shortest possible line */
                goto missing;
 
-       if (!memcmp(line, "TCP4 ", 5) != 0) {
+       if (memcmp(line, "TCP4 ", 5) == 0) {
                u32 src3, dst3, sport, dport;
 
                line += 5;
@@ -426,7 +426,7 @@ int conn_recv_proxy(struct connection *conn, int flag)
                ((struct sockaddr_in *)&conn->addr.to)->sin_port          = 
htons(dport);
                conn->flags |= CO_FL_ADDR_FROM_SET | CO_FL_ADDR_TO_SET;
        }
-       else if (!memcmp(line, "TCP6 ", 5) != 0) {
+       else if (memcmp(line, "TCP6 ", 5) == 0) {
                u32 sport, dport;
                char *src_s;
                char *dst_s, *sport_s, *dport_s;
-- 
2.6.6

++++++ 0009-BUG-MEDIUM-stats-show-servers-state-may-show-an-serv.patch ++++++
>From 4cb6ccc835ce0c2c874e9868a62a981278b510f7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cyril=20Bont=C3=A9?= <cyril.bo...@free.fr>
Date: Fri, 27 May 2016 00:06:45 +0200
Subject: [PATCH 09/14] BUG/MEDIUM: stats: show servers state may show an
 servers from another backend

Olivier Doucet reported that "show servers state" was producing an invalid
output with some configurations where nbproc > 1.

Indeed, commit 76a99784f4 fixed some issues but unfortunately introduced a
regression when a backend bound to the same process as the stats socket and a
previous backend is bound to another one.

For example :
  global
    daemon
    nbproc 2
    stats socket /var/run/haproxy-1.sock process 1
    stats socket /var/run/haproxy-2.sock process 2

  listen proc1
    bind 127.0.0.1:9001
    bind-process 1
    server WRONG 127.0.0.1:80

  listen proc2
    bind 127.0.0.1:9002
    bind-process 2
    server RIGHT 127.0.0.1:80

Requesting "show servers state" on /var/run/haproxy-2.sock was producing a line
like :
3 proc2 1 WRONG 127.0.0.1 2 0 1 1 4 1 0 2 0 0 0 0

whereas the line below was awaited :
3 proc2 1 RIGHT 127.0.0.1 2 0 1 1 5 1 0 2 0 0 0 0

This was caused by the initialization of the server loop too early, before the
bind_proc filtering whereas it should be done after.

This fix should be backported to 1.6, where the regression has unfortunately
been backported.

(cherry picked from commit d55bd7a6a934387cdc5df7ad3fbc2718dc3a724e)
---
 src/dumpstats.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/dumpstats.c b/src/dumpstats.c
index b9f5719..4614cf2 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -2755,6 +2755,9 @@ static int dump_servers_state(struct stream_interface 
*si, struct chunk *buf)
        if (appctx->ctx.server_state.px->bind_proc && 
!(appctx->ctx.server_state.px->bind_proc & (1UL << (relative_pid - 1))))
                return 1;
 
+       if (!appctx->ctx.server_state.sv)
+               appctx->ctx.server_state.sv = appctx->ctx.server_state.px->srv;
+
        for (; appctx->ctx.server_state.sv != NULL; appctx->ctx.server_state.sv 
= srv->next) {
                srv = appctx->ctx.server_state.sv;
                srv_addr[0] = '\0';
@@ -2857,8 +2860,6 @@ static int stats_dump_servers_state_to_buffer(struct 
stream_interface *si)
 
        for (; appctx->ctx.server_state.px != NULL; appctx->ctx.server_state.px 
= curproxy->next) {
                curproxy = appctx->ctx.server_state.px;
-               if (!appctx->ctx.server_state.sv)
-                       appctx->ctx.server_state.sv = 
appctx->ctx.server_state.px->srv;
                /* servers are only in backends */
                if (curproxy->cap & PR_CAP_BE) {
                        if (!dump_servers_state(si, &trash))
-- 
2.6.6

++++++ 0010-BUG-MEDIUM-fix-risk-of-segfault-with-show-tls-keys.patch ++++++
>From ff8957a6f44061594b0e2456de172b7c9f453a3f Mon Sep 17 00:00:00 2001
From: William Lallemand <wlallem...@haproxy.com>
Date: Fri, 20 May 2016 17:28:07 +0200
Subject: [PATCH 10/14] BUG/MEDIUM: fix risk of segfault with "show tls-keys"

The reference to the tls_keys_ref was not deleted from the
tlskeys_reference linked list.

When the SSL is malconfigured, it can lead to an access to freed memory
during a "show tls-keys" on the admin socked.
(cherry picked from commit 7bba4ccfb68b2fc0e76f51bcca7cdcb1388c4023)
---
 src/cfgparse.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/cfgparse.c b/src/cfgparse.c
index b0f837e..7025b6a 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -8728,6 +8728,7 @@ out_uri_auth_compat:
                        if(bind_conf->keys_ref) {
                                free(bind_conf->keys_ref->filename);
                                free(bind_conf->keys_ref->tlskeys);
+                               LIST_DEL(&bind_conf->keys_ref->list);
                                free(bind_conf->keys_ref);
                        }
 #endif /* USE_OPENSSL */
-- 
2.6.6

++++++ 0011-BUG-MEDIUM-sticktables-segfault-in-some-configuratio.patch ++++++
>From 4693e2302271252044038c9be38487fb16218e5b Mon Sep 17 00:00:00 2001
From: Thierry Fournier <thierry.fourn...@ozon.io>
Date: Mon, 6 Jun 2016 18:28:05 +0200
Subject: [PATCH 11/14] BUG/MEDIUM: sticktables: segfault in some configuration
 error cases

When a stick table is tracked, and another one is used later on the
configuration, a segfault occurs.

The function "smp_create_src_stkctr" can return a NULL value, and
its value is not tested, so one other function try to dereference
a NULL pointer. This patch just add a verification of the NULL
pointer.

The problem is reproduced with this configuration:

   listen www
       mode http
       bind :12345
       tcp-request content track-sc0 src table IPv4
       http-request allow if { sc0_inc_gpc0(IPv6) gt 0 }
       server dummy 127.0.0.1:80
   backend IPv4
       stick-table type ip size 10 expire 60s store gpc0
   backend IPv6
       stick-table type ipv6 size 10 expire 60s store gpc0

Thank to kabef...@gmail.com for the bug report.

This patch must be backported in the 1.6 and 1.5 version.
(cherry picked from commit 6fc340ff07171bb85d11d835fa4158bbdef240a0)
---
 src/stream.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/stream.c b/src/stream.c
index 4ba8010..d80efa5 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -2855,7 +2855,7 @@ smp_fetch_sc_inc_gpc0(const struct arg *args, struct 
sample *smp, const char *kw
        if (stkctr_entry(stkctr) == NULL)
                stkctr = smp_create_src_stkctr(smp->sess, smp->strm, args, kw);
 
-       if (stkctr_entry(stkctr) != NULL) {
+       if (stkctr && stkctr_entry(stkctr)) {
                void *ptr1,*ptr2;
 
                /* First, update gpc0_rate if it's tracked. Second, update its
-- 
2.6.6

++++++ 0012-BUG-MEDIUM-lua-converters-doesn-t-work.patch ++++++
>From 7e3cfc9e48673314f7b970a054339306cef20928 Mon Sep 17 00:00:00 2001
From: Thierry Fournier <thierry.fourn...@ozon.io>
Date: Fri, 27 May 2016 16:35:01 +0200
Subject: [PATCH 12/14] BUG/MEDIUM: lua: converters doesn't work

The number of arguments pushed in the stack are false, so we try to execute a
function out of the stack. This function is always a nil pointer, so the
following message is displayed.

   Lua converter 'testconv': runtime error: attempt to call a nil value.

Thanks Michael Ezzell for the repporting.

This patch must be backported in the 1.6 version.
(cherry picked from commit 4a53bfdc1de46c78a23eabdefc4b418cff7d0403)
---
 src/hlua.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/hlua.c b/src/hlua.c
index edd288d..185c4c1 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -5167,7 +5167,7 @@ static int hlua_sample_conv_wrapper(const struct arg 
*arg_p, struct sample *smp,
                        return 0;
                }
                hlua_smp2lua(stream->hlua.T, smp);
-               stream->hlua.nargs = 2;
+               stream->hlua.nargs = 1;
 
                /* push keywords in the stack. */
                if (arg_p) {
-- 
2.6.6

++++++ 0013-BUG-MINOR-http-add-header-header-name-copied-twice.patch ++++++
>From d281d68d3aa010f7e1a635c92ab486f7f2c666b9 Mon Sep 17 00:00:00 2001
From: Thierry Fournier <thierry.fourn...@ozon.io>
Date: Wed, 1 Jun 2016 13:36:20 +0200
Subject: [PATCH 13/14] BUG/MINOR: http: add-header: header name copied twice

The header name is copied two time in the buffer. The first copy is a 
printf-like
function writing the name and the http separators in the buffer, and the second
form is a memcopy. This seems to be inherited from some changes. This patch
removes the printf like, format.

This patch must be backported in 1.6 and 1.5 versions
(cherry picked from commit 53c1a9b7cb8f3fe79b5492218363b6c0ff608fc1)
---
 src/proto_http.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/proto_http.c b/src/proto_http.c
index 6eac62b..0d9dd31 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -3615,7 +3615,6 @@ resume_execution:
 
                case ACT_HTTP_SET_HDR:
                case ACT_HTTP_ADD_HDR:
-                       chunk_printf(&trash, "%s: ", rule->arg.hdr_add.name);
                        memcpy(trash.str, rule->arg.hdr_add.name, 
rule->arg.hdr_add.name_len);
                        trash.len = rule->arg.hdr_add.name_len;
                        trash.str[trash.len++] = ':';
-- 
2.6.6

++++++ 0014-BUG-MEDIUM-http-add-header-buffer-overwritten.patch ++++++
>From f5cb61d3224df4075e2ce3172733a25a1fab7fca Mon Sep 17 00:00:00 2001
From: Thierry Fournier <thierry.fourn...@ozon.io>
Date: Wed, 1 Jun 2016 13:35:36 +0200
Subject: [PATCH 14/14] BUG/MEDIUM: http: add-header: buffer overwritten

If we use the action "http-request add-header" with a Lua sample-fetch or
converter, and the Lua function calls one of the Lua log function, the
header name is corrupted, it contains an extract of the last loggued data.

This is due to an overwrite of the trash buffer, because his scope is not
respected in the "add-header" function. The scope of the trash buffer must
be limited to the function using it. The build_logline() function can
execute a lot of other function which can use the trash buffer.

This patch fix the usage of the trash buffer. It limits the scope of this
global buffer to the local function, we build first the header value using
build_logline, and after we store the header name.

Thanks Michael Ezzell for the repporting.

This patch must be backported in 1.6 version
(cherry picked from commit 4b788f7d349ddde3f70f063b7394529eac6ab678)
---
 src/proto_http.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/src/proto_http.c b/src/proto_http.c
index 0d9dd31..fd1f108 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -3504,6 +3504,7 @@ http_req_get_intercept_rule(struct proxy *px, struct list 
*rules, struct stream
        struct hdr_ctx ctx;
        const char *auth_realm;
        int act_flags = 0;
+       int len;
 
        /* If "the current_rule_list" match the executed rule list, we are in
         * resume condition. If a resume is needed it is always in the action
@@ -3615,11 +3616,18 @@ resume_execution:
 
                case ACT_HTTP_SET_HDR:
                case ACT_HTTP_ADD_HDR:
+                       /* The scope of the trash buffer must be limited to 
this function. The
+                        * build_logline() function can execute a lot of other 
function which
+                        * can use the trash buffer. So for limiting the scope 
of this global
+                        * buffer, we build first the header value using 
build_logline, and
+                        * after we store the header name.
+                        */
+                       len = rule->arg.hdr_add.name_len + 2,
+                       len += build_logline(s, trash.str + len, trash.size - 
len, &rule->arg.hdr_add.fmt);
                        memcpy(trash.str, rule->arg.hdr_add.name, 
rule->arg.hdr_add.name_len);
-                       trash.len = rule->arg.hdr_add.name_len;
-                       trash.str[trash.len++] = ':';
-                       trash.str[trash.len++] = ' ';
-                       trash.len += build_logline(s, trash.str + trash.len, 
trash.size - trash.len, &rule->arg.hdr_add.fmt);
+                       trash.str[rule->arg.hdr_add.name_len] = ':';
+                       trash.str[rule->arg.hdr_add.name_len + 1] = ' ';
+                       trash.len = len;
 
                        if (rule->action == ACT_HTTP_SET_HDR) {
                                /* remove all occurrences of the header */
-- 
2.6.6


Reply via email to