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>
diff --git a/src/fcgi-app.c b/src/fcgi-app.c
index 412584c..4174a07 100644
--- a/src/fcgi-app.c
+++ b/src/fcgi-app.c
@@ -477,7 +477,7 @@
   rewrite_err:
 	_HA_ATOMIC_ADD(&sess->fe->fe_counters.failed_rewrites, 1);
 	_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);
diff --git a/src/http_act.c b/src/http_act.c
index ed4fce1..ed403a7 100644
--- a/src/http_act.c
+++ b/src/http_act.c
@@ -124,7 +124,7 @@
 	_HA_ATOMIC_ADD(&sess->fe->fe_counters.failed_rewrites, 1);
 	if (s->flags & SF_BE_ASSIGNED)
 		_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);
@@ -253,7 +253,7 @@
 	_HA_ATOMIC_ADD(&sess->fe->fe_counters.failed_rewrites, 1);
 	if (s->flags & SF_BE_ASSIGNED)
 		_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);
@@ -329,7 +329,7 @@
 		_HA_ATOMIC_ADD(&sess->fe->fe_counters.failed_rewrites, 1);
 		if (s->flags & SF_BE_ASSIGNED)
 			_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);
@@ -1256,7 +1256,7 @@
 	_HA_ATOMIC_ADD(&sess->fe->fe_counters.failed_rewrites, 1);
 	if (s->flags & SF_BE_ASSIGNED)
 		_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);
@@ -1369,7 +1369,7 @@
 	_HA_ATOMIC_ADD(&sess->fe->fe_counters.failed_rewrites, 1);
 	if (s->flags & SF_BE_ASSIGNED)
 		_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);
diff --git a/src/http_ana.c b/src/http_ana.c
index f9dbfb1..a1dd807 100644
--- a/src/http_ana.c
+++ b/src/http_ana.c
@@ -437,14 +437,14 @@
 	if (!(s->flags & SF_ERR_MASK))
 		s->flags |= SF_ERR_INTERNAL;
 	_HA_ATOMIC_ADD(&sess->fe->fe_counters.internal_errors, 1);
-	if (sess->listener->counters)
+	if (sess->listener && sess->listener->counters)
 		_HA_ATOMIC_ADD(&sess->listener->counters->internal_errors, 1);
 	goto return_prx_cond;
 
  return_bad_req:
 	txn->status = 400;
 	_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);
 	/* fall through */
 
@@ -655,7 +655,7 @@
 	_HA_ATOMIC_ADD(&sess->fe->fe_counters.denied_req, 1);
 	if (s->flags & SF_BE_ASSIGNED)
 		_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;
 
@@ -671,7 +671,7 @@
 	_HA_ATOMIC_ADD(&sess->fe->fe_counters.denied_req, 1);
 	if (s->flags & SF_BE_ASSIGNED)
 		_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_err;
 
@@ -682,14 +682,14 @@
 	_HA_ATOMIC_ADD(&sess->fe->fe_counters.internal_errors, 1);
 	if (s->flags & SF_BE_ASSIGNED)
 		_HA_ATOMIC_ADD(&s->be->be_counters.internal_errors, 1);
-	if (sess->listener->counters)
+	if (sess->listener && sess->listener->counters)
 		_HA_ATOMIC_ADD(&sess->listener->counters->internal_errors, 1);
 	goto return_prx_err;
 
  return_bad_req:
 	txn->status = 400;
 	_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);
 	/* fall through */
 
@@ -923,7 +923,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);
 
@@ -946,14 +946,14 @@
 	_HA_ATOMIC_ADD(&sess->fe->fe_counters.internal_errors, 1);
 	if (s->flags & SF_BE_ASSIGNED)
 		_HA_ATOMIC_ADD(&s->be->be_counters.internal_errors, 1);
-	if (sess->listener->counters)
+	if (sess->listener && sess->listener->counters)
 		_HA_ATOMIC_ADD(&sess->listener->counters->internal_errors, 1);
 	goto return_prx_cond;
 
  return_bad_req: /* let's centralize all bad requests */
 	txn->status = 400;
 	_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);
 	/* fall through */
 
@@ -1076,7 +1076,7 @@
 		if (!(s->flags & SF_ERR_MASK))
 			s->flags |= SF_ERR_CLITO;
 		_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);
 		goto return_prx_cond;
 	}
@@ -1112,14 +1112,14 @@
 	_HA_ATOMIC_ADD(&sess->fe->fe_counters.internal_errors, 1);
 	if (s->flags & SF_BE_ASSIGNED)
 		_HA_ATOMIC_ADD(&s->be->be_counters.internal_errors, 1);
-	if (sess->listener->counters)
+	if (sess->listener && sess->listener->counters)
 		_HA_ATOMIC_ADD(&sess->listener->counters->internal_errors, 1);
 	goto return_prx_cond;
 
  return_bad_req: /* let's centralize all bad requests */
 	txn->status = 400;
 	_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);
 	/* fall through */
 
@@ -1351,7 +1351,7 @@
   return_cli_abort:
 	_HA_ATOMIC_ADD(&sess->fe->fe_counters.cli_aborts, 1);
 	_HA_ATOMIC_ADD(&s->be->be_counters.cli_aborts, 1);
-	if (sess->listener->counters)
+	if (sess->listener && sess->listener->counters)
 		_HA_ATOMIC_ADD(&sess->listener->counters->cli_aborts, 1);
 	if (objt_server(s->target))
 		_HA_ATOMIC_ADD(&__objt_server(s->target)->counters.cli_aborts, 1);
@@ -1363,7 +1363,7 @@
   return_srv_abort:
 	_HA_ATOMIC_ADD(&sess->fe->fe_counters.srv_aborts, 1);
 	_HA_ATOMIC_ADD(&s->be->be_counters.srv_aborts, 1);
-	if (sess->listener->counters)
+	if (sess->listener && sess->listener->counters)
 		_HA_ATOMIC_ADD(&sess->listener->counters->srv_aborts, 1);
 	if (objt_server(s->target))
 		_HA_ATOMIC_ADD(&__objt_server(s->target)->counters.srv_aborts, 1);
@@ -1377,7 +1377,7 @@
 		s->flags |= SF_ERR_INTERNAL;
 	_HA_ATOMIC_ADD(&sess->fe->fe_counters.internal_errors, 1);
 	_HA_ATOMIC_ADD(&s->be->be_counters.internal_errors, 1);
-	if (sess->listener->counters)
+	if (sess->listener && sess->listener->counters)
 		_HA_ATOMIC_ADD(&sess->listener->counters->internal_errors, 1);
 	if (objt_server(s->target))
 		_HA_ATOMIC_ADD(&__objt_server(s->target)->counters.internal_errors, 1);
@@ -1386,7 +1386,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);
 	status = 400;
 	/* fall through */
@@ -1594,7 +1594,7 @@
 		else if ((rep->flags & CF_SHUTR) && ((s->req.flags & (CF_SHUTR|CF_SHUTW)) == (CF_SHUTR|CF_SHUTW))) {
 			_HA_ATOMIC_ADD(&sess->fe->fe_counters.cli_aborts, 1);
 			_HA_ATOMIC_ADD(&s->be->be_counters.cli_aborts, 1);
-			if (sess->listener->counters)
+			if (sess->listener && sess->listener->counters)
 				_HA_ATOMIC_ADD(&sess->listener->counters->cli_aborts, 1);
 			if (objt_server(s->target))
 				_HA_ATOMIC_ADD(&__objt_server(s->target)->counters.cli_aborts, 1);
@@ -1867,7 +1867,7 @@
  return_int_err:
 	_HA_ATOMIC_ADD(&sess->fe->fe_counters.internal_errors, 1);
 	_HA_ATOMIC_ADD(&s->be->be_counters.internal_errors, 1);
-	if (sess->listener->counters)
+	if (sess->listener && sess->listener->counters)
 		_HA_ATOMIC_ADD(&sess->listener->counters->internal_errors, 1);
 	if (objt_server(s->target))
 		_HA_ATOMIC_ADD(&__objt_server(s->target)->counters.internal_errors, 1);
@@ -2167,7 +2167,7 @@
  deny:
 	_HA_ATOMIC_ADD(&sess->fe->fe_counters.denied_resp, 1);
 	_HA_ATOMIC_ADD(&s->be->be_counters.denied_resp, 1);
-	if (sess->listener->counters)
+	if (sess->listener && sess->listener->counters)
 		_HA_ATOMIC_ADD(&sess->listener->counters->denied_resp, 1);
 	if (objt_server(s->target))
 		_HA_ATOMIC_ADD(&__objt_server(s->target)->counters.denied_resp, 1);
@@ -2433,7 +2433,7 @@
   return_srv_abort:
 	_HA_ATOMIC_ADD(&sess->fe->fe_counters.srv_aborts, 1);
 	_HA_ATOMIC_ADD(&s->be->be_counters.srv_aborts, 1);
-	if (sess->listener->counters)
+	if (sess->listener && sess->listener->counters)
 		_HA_ATOMIC_ADD(&sess->listener->counters->srv_aborts, 1);
 	if (objt_server(s->target))
 		_HA_ATOMIC_ADD(&__objt_server(s->target)->counters.srv_aborts, 1);
@@ -2444,7 +2444,7 @@
   return_cli_abort:
 	_HA_ATOMIC_ADD(&sess->fe->fe_counters.cli_aborts, 1);
 	_HA_ATOMIC_ADD(&s->be->be_counters.cli_aborts, 1);
-	if (sess->listener->counters)
+	if (sess->listener && sess->listener->counters)
 		_HA_ATOMIC_ADD(&sess->listener->counters->cli_aborts, 1);
 	if (objt_server(s->target))
 		_HA_ATOMIC_ADD(&__objt_server(s->target)->counters.cli_aborts, 1);
@@ -2455,7 +2455,7 @@
   return_int_err:
 	_HA_ATOMIC_ADD(&sess->fe->fe_counters.internal_errors, 1);
 	_HA_ATOMIC_ADD(&s->be->be_counters.internal_errors, 1);
-	if (sess->listener->counters)
+	if (sess->listener && sess->listener->counters)
 		_HA_ATOMIC_ADD(&sess->listener->counters->internal_errors, 1);
 	if (objt_server(s->target))
 		_HA_ATOMIC_ADD(&__objt_server(s->target)->counters.internal_errors, 1);
@@ -4486,7 +4486,7 @@
 			txn->rsp.msg_state = HTTP_MSG_ERROR;
 			_HA_ATOMIC_ADD(&strm_sess(s)->fe->fe_counters.cli_aborts, 1);
 			_HA_ATOMIC_ADD(&s->be->be_counters.cli_aborts, 1);
-			if (strm_sess(s)->listener->counters)
+			if (strm_sess(s)->listener && strm_sess(s)->listener->counters)
 				_HA_ATOMIC_ADD(&strm_sess(s)->listener->counters->cli_aborts, 1);
 			if (objt_server(s->target))
 				_HA_ATOMIC_ADD(&__objt_server(s->target)->counters.cli_aborts, 1);
diff --git a/src/tcp_act.c b/src/tcp_act.c
index 601bb53..a92c9bb 100644
--- a/src/tcp_act.c
+++ b/src/tcp_act.c
@@ -225,7 +225,7 @@
 	}
 
 	_HA_ATOMIC_ADD(&sess->fe->fe_counters.denied_req, 1);
-	if (sess->listener->counters)
+	if (sess->listener && sess->listener->counters)
 		_HA_ATOMIC_ADD(&sess->listener->counters->denied_req, 1);
 
 	return ACT_RET_ABRT;
diff --git a/src/tcp_rules.c b/src/tcp_rules.c
index d5fce26..d83f10e 100644
--- a/src/tcp_rules.c
+++ b/src/tcp_rules.c
@@ -373,7 +373,7 @@
   deny:
 	_HA_ATOMIC_ADD(&s->sess->fe->fe_counters.denied_resp, 1);
 	_HA_ATOMIC_ADD(&s->be->be_counters.denied_resp, 1);
-	if (s->sess->listener->counters)
+	if (s->sess->listener && s->sess->listener->counters)
 		_HA_ATOMIC_ADD(&s->sess->listener->counters->denied_resp, 1);
 	if (objt_server(s->target))
 		_HA_ATOMIC_ADD(&__objt_server(s->target)->counters.denied_resp, 1);
@@ -382,7 +382,7 @@
  internal:
 	_HA_ATOMIC_ADD(&s->sess->fe->fe_counters.internal_errors, 1);
 	_HA_ATOMIC_ADD(&s->be->be_counters.internal_errors, 1);
-	if (s->sess->listener->counters)
+	if (s->sess->listener && s->sess->listener->counters)
 		_HA_ATOMIC_ADD(&s->sess->listener->counters->internal_errors, 1);
 	if (objt_server(s->target))
 		_HA_ATOMIC_ADD(&__objt_server(s->target)->counters.internal_errors, 1);