BUG/MAJOR: stick-tables: do not try to index a server name for applets

Since commit 03cdf55e6 ("MINOR: stream: Stickiness server lookup by name.")
in 2.0-dev6, server names may be used instead of their IDs, in order to
perform stickiness. However the commit above may end up trying to insert
an empty server name in the dictionary when the server is an applet
instead, resulting in an immediate segfault. This is typically what
happens when a "stick-store" rule is present in a backend featuring a
"stats" directive. As there doesn't seem to be an easy way around it,
it seems to imply that "stick-store" is not much used anymore.

The solution here is to only try to insert non-null keys into the
dictionary. The patch moves the check of the key type before the
first lock so that the test on the key can be performed under the lock
instead of locking twice (the patch is more readable with diff -b).

Note that before 2.4, there's no <key> variable there as it was
introduced by commit 92149f9a8 ("MEDIUM: stick-tables: Add srvkey
option to stick-table"), but the __objt_server(s->target)->id still
needs to be tested.

This needs to be backported as far as 2.0.

(cherry picked from commit bc7c207f745bf6406b38139b98cb5b8c794e13f0)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 603c54d9fac48e932bb71cf1cc1e8df29df36fae)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit fb5ddb2c2653b94093fbaf6bad9f95a0da90b0e5)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
diff --git a/src/stream.c b/src/stream.c
index c241642..f545c10 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -1448,24 +1448,25 @@
 		}
 		s->store[i].ts = NULL;
 
-		HA_RWLOCK_WRLOCK(STK_SESS_LOCK, &ts->lock);
-		ptr = __stktable_data_ptr(t, ts, STKTABLE_DT_SERVER_ID);
-		stktable_data_cast(ptr, server_id) = __objt_server(s->target)->puid;
-		HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock);
-
 		if (t->server_key_type == STKTABLE_SRV_NAME)
 			key = __objt_server(s->target)->id;
 		else if (t->server_key_type == STKTABLE_SRV_ADDR)
 			key = __objt_server(s->target)->addr_node.key;
 		else
-			continue;
+			key = NULL;
 
 		HA_RWLOCK_WRLOCK(STK_SESS_LOCK, &ts->lock);
-		de = dict_insert(&server_key_dict, key);
-		if (de) {
-			ptr = __stktable_data_ptr(t, ts, STKTABLE_DT_SERVER_KEY);
-			stktable_data_cast(ptr, server_key) = de;
+		ptr = __stktable_data_ptr(t, ts, STKTABLE_DT_SERVER_ID);
+		stktable_data_cast(ptr, std_t_sint) = __objt_server(s->target)->puid;
+
+		if (key) {
+			de = dict_insert(&server_key_dict, key);
+			if (de) {
+				ptr = __stktable_data_ptr(t, ts, STKTABLE_DT_SERVER_KEY);
+				stktable_data_cast(ptr, server_key) = de;
+			}
 		}
+
 		HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock);
 
 		stktable_touch_local(t, ts, 1);