BUG/MEDIUM: session: NULL dereference possible when accessing the listener

When implementing a client applet, a NULL dereference was encountered on
the error path which increment the counters.

Indeed, the counters incremented are the one in the listener which does
not exist in the case of client applets, so in sess->listener->counters,
listener is NULL.

This patch fixes the access to the listener structure when accessing
from a sesssion, most of the access are the counters in error paths.

Must be backported as far as 1.8.

(cherry picked from commit 36119de182154b1f87e0cdf4bd1efba9e2e64113)
[wt: minor ctx adjustments in http_ana and mux_h1]
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 656730d92f1c3afaed0baf67911d4ee055528e2e)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 35054f1d6cc549dbd53832d551f7f9f446a0d18d)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 946e55d8ebc06f22c774f3439c4c9034c267dde6)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
diff --git a/src/proto_htx.c b/src/proto_htx.c
index 117d1ba..9ac9ffa 100644
--- a/src/proto_htx.c
+++ b/src/proto_htx.c
@@ -438,7 +438,7 @@
 	txn->req.msg_state = HTTP_MSG_ERROR;
 	htx_reply_and_close(s, txn->status, htx_error_message(s));
 	_HA_ATOMIC_ADD(&sess->fe->fe_counters.failed_req, 1);
-	if (sess->listener->counters)
+	if (sess->listener && sess->listener->counters)
 		_HA_ATOMIC_ADD(&sess->listener->counters->failed_req, 1);
 
  return_prx_cond:
@@ -679,7 +679,7 @@
 	_HA_ATOMIC_ADD(&sess->fe->fe_counters.denied_req, 1);
 	if (sess->fe != s->be)
 		_HA_ATOMIC_ADD(&s->be->be_counters.denied_req, 1);
-	if (sess->listener->counters)
+	if (sess->listener && sess->listener->counters)
 		_HA_ATOMIC_ADD(&sess->listener->counters->denied_req, 1);
 	goto done_without_exp;
 
@@ -698,7 +698,7 @@
 	_HA_ATOMIC_ADD(&sess->fe->fe_counters.denied_req, 1);
 	if (sess->fe != s->be)
 		_HA_ATOMIC_ADD(&s->be->be_counters.denied_req, 1);
-	if (sess->listener->counters)
+	if (sess->listener && sess->listener->counters)
 		_HA_ATOMIC_ADD(&sess->listener->counters->denied_req, 1);
 	goto return_prx_cond;
 
@@ -709,7 +709,7 @@
 	htx_reply_and_close(s, txn->status, htx_error_message(s));
 
 	_HA_ATOMIC_ADD(&sess->fe->fe_counters.failed_req, 1);
-	if (sess->listener->counters)
+	if (sess->listener && sess->listener->counters)
 		_HA_ATOMIC_ADD(&sess->listener->counters->failed_req, 1);
 
  return_prx_cond:
@@ -949,7 +949,7 @@
 	 * in case we previously disabled it, otherwise we might cause
 	 * the client to delay further data.
 	 */
-	if ((sess->listener->options & LI_O_NOQUICKACK) &&
+	if (sess->listener && (sess->listener->options & LI_O_NOQUICKACK) &&
 	    (htx_get_tail_type(htx) != HTX_BLK_EOM))
 		conn_set_quickack(cli_conn, 1);
 
@@ -972,7 +972,7 @@
 	htx_reply_and_close(s, txn->status, htx_error_message(s));
 
 	_HA_ATOMIC_ADD(&sess->fe->fe_counters.failed_req, 1);
-	if (sess->listener->counters)
+	if (sess->listener && sess->listener->counters)
 		_HA_ATOMIC_ADD(&sess->listener->counters->failed_req, 1);
 
 	if (!(s->flags & SF_ERR_MASK))
@@ -1125,7 +1125,7 @@
  return_err_msg:
 	req->analysers &= AN_REQ_FLT_END;
 	_HA_ATOMIC_ADD(&sess->fe->fe_counters.failed_req, 1);
-	if (sess->listener->counters)
+	if (sess->listener && sess->listener->counters)
 		_HA_ATOMIC_ADD(&sess->listener->counters->failed_req, 1);
 	return 0;
 }
@@ -1370,7 +1370,7 @@
 
   return_bad_req:
 	_HA_ATOMIC_ADD(&sess->fe->fe_counters.failed_req, 1);
-	if (sess->listener->counters)
+	if (sess->listener && sess->listener->counters)
 		_HA_ATOMIC_ADD(&sess->listener->counters->failed_req, 1);
 	if (!(s->flags & SF_ERR_MASK))
 		s->flags |= SF_ERR_CLICL;
@@ -1965,7 +1965,7 @@
 
 			_HA_ATOMIC_ADD(&s->be->be_counters.denied_resp, 1);
 			_HA_ATOMIC_ADD(&sess->fe->fe_counters.denied_resp, 1);
-			if (sess->listener->counters)
+			if (sess->listener && sess->listener->counters)
 				_HA_ATOMIC_ADD(&sess->listener->counters->denied_resp, 1);
 			goto return_srv_prx_502;
 		}
@@ -2121,7 +2121,7 @@
 
 		_HA_ATOMIC_ADD(&s->be->be_counters.denied_resp, 1);
 		_HA_ATOMIC_ADD(&sess->fe->fe_counters.denied_resp, 1);
-		if (sess->listener->counters)
+		if (sess->listener && sess->listener->counters)
 			_HA_ATOMIC_ADD(&sess->listener->counters->denied_resp, 1);
 
 		ha_alert("Blocking cacheable cookie in response from instance %s, server %s.\n",
@@ -3013,7 +3013,7 @@
 					_HA_ATOMIC_ADD(&sess->fe->fe_counters.failed_rewrites, 1);
 					if (sess->fe != s->be)
 						_HA_ATOMIC_ADD(&s->be->be_counters.failed_rewrites, 1);
-					if (sess->listener->counters)
+					if (sess->listener && sess->listener->counters)
 						_HA_ATOMIC_ADD(&sess->listener->counters->failed_rewrites, 1);
 				}
 				free_trash_chunk(replace);
@@ -3352,7 +3352,7 @@
 					_HA_ATOMIC_ADD(&sess->fe->fe_counters.failed_rewrites, 1);
 					if (sess->fe != s->be)
 						_HA_ATOMIC_ADD(&s->be->be_counters.failed_rewrites, 1);
-					if (sess->listener->counters)
+					if (sess->listener && sess->listener->counters)
 						_HA_ATOMIC_ADD(&sess->listener->counters->failed_rewrites, 1);
 					if (objt_server(s->target))
 						_HA_ATOMIC_ADD(&objt_server(s->target)->counters.failed_rewrites, 1);