]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: peers: Wrong "server_name" decoding.
authorFrédéric Lécaille <flecaille@haproxy.com>
Wed, 5 Jun 2019 08:20:09 +0000 (10:20 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 5 Jun 2019 11:36:34 +0000 (13:36 +0200)
This patch fixes a bug which does not occur at this time because the "server_name"
stick-table data type is the last one (see STKTABLE_DT_SERVER_NAME). It was introduced
by this commit: "MINOR: peers: Make peers protocol support new "server_name" data type".

Indeed when receiving STD_T_DICT stick-table data type we first decode the length
of these data, then we decode the ID of this dictionary entry. To know if there
is remaining data to parse, we check if we have reached the end of the current data,
relying on <msg_end> variable. But <msg_end> is at the end of the entire message!

So this patch computes the correct end of the current STD_T_DICT before doing
anything else with it.

Nothing to backport.

src/peers.c

index bece5a6a58d9c9d277d732bab836b191b807f654..f3a465d32e1b97006f6f6f9f23f63a163d5122b2 100644 (file)
@@ -1440,17 +1440,22 @@ static int peer_treat_updatemsg(struct appctx *appctx, struct peer *p, int updt,
                        unsigned int id;
                        struct dict_entry *de;
                        struct dcache *dc;
+                       char *end;
 
                        data_len = decoded_int;
                        if (*msg_cur + data_len > msg_end)
                                goto malformed_unlock;
 
-                       id = intdecode(msg_cur, msg_end);
+                       /* Compute the end of the current data, <msg_end> being at the end of
+                        * the entire message.
+                        */
+                       end = *msg_cur + data_len;
+                       id = intdecode(msg_cur, end);
                        if (!*msg_cur || !id)
                                goto malformed_unlock;
 
                        dc = p->dcache;
-                       if (*msg_cur == msg_end) {
+                       if (*msg_cur == end) {
                                /* Dictionary entry key without value. */
                                if (id > dc->max_entries)
                                        break;
@@ -1459,8 +1464,8 @@ static int peer_treat_updatemsg(struct appctx *appctx, struct peer *p, int updt,
                        }
                        else {
                                chunk = get_trash_chunk();
-                               value_len = intdecode(msg_cur, msg_end);
-                               if (!*msg_cur || *msg_cur + value_len > msg_end ||
+                               value_len = intdecode(msg_cur, end);
+                               if (!*msg_cur || *msg_cur + value_len > end ||
                                        unlikely(value_len + 1 >= chunk->size))
                                        goto malformed_unlock;