BUG/MAJOR: samples: check smp->strm before using it

Since commit 6879ad3 ("MEDIUM: sample: fill the struct sample with the
session, proxy and stream pointers") merged in 1.6-dev2, the sample
contains the pointer to the stream and sample fetch functions as well
as converters use it heavily.

The problem is that earlier commit 87b0966 ("REORG/MAJOR: session:
rename the "session" entity to "stream"") had split the session and
stream resulting in the possibility for smp->strm to be NULL before
the stream was initialized. This is what happens in tcp-request
connection rulesets, as discovered by Baptiste.

The sample fetch functions must now check that smp->strm is valid
before using it. An alternative could consist in using a dummy stream
with nothing in it to avoid some checks but it would only result in
deferring them to the next step anyway, and making it harder to detect
that a stream is valid or the dummy one.

There is still an issue with variables which requires a complete
independant fix. They use strm->sess to find the session with strm
possibly NULL and passed as an argument. All call places indirectly
use smp->strm to build strm. So the problem is there but the API needs
to be changed to remove this duplicate argument that makes it much
harder to know what pointer to use.

This fix must be backported to 1.6, as well as the next one fixing
variables.
diff --git a/src/backend.c b/src/backend.c
index 4503d0e..2c94299 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -1671,6 +1671,9 @@
 static int
 smp_fetch_be_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
+	if (!smp->strm)
+		return 0;
+
 	smp->flags = SMP_F_VOL_TXN;
 	smp->data.type = SMP_T_SINT;
 	smp->data.u.sint = smp->strm->be->uuid;
@@ -1681,6 +1684,9 @@
 static int
 smp_fetch_srv_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
+	if (!smp->strm)
+		return 0;
+
 	if (!objt_server(smp->strm->target))
 		return 0;
 
diff --git a/src/flt_http_comp.c b/src/flt_http_comp.c
index 46abe52..6bbf6a1 100644
--- a/src/flt_http_comp.c
+++ b/src/flt_http_comp.c
@@ -893,7 +893,7 @@
 smp_fetch_res_comp(const struct arg *args, struct sample *smp, const char *kw,
 		   void *private)
 {
-	struct http_txn *txn = smp->strm->txn;
+	struct http_txn *txn = smp->strm ? smp->strm->txn : NULL;
 
 	smp->data.type = SMP_T_BOOL;
 	smp->data.u.sint = (txn && (txn->rsp.flags & HTTP_MSGF_COMPRESSING));
@@ -907,7 +907,7 @@
 smp_fetch_res_comp_algo(const struct arg *args, struct sample *smp,
 			const char *kw, void *private)
 {
-	struct http_txn   *txn = smp->strm->txn;
+	struct http_txn   *txn = smp->strm ? smp->strm->txn : NULL;
 	struct filter     *filter;
 	struct comp_state *st;
 
diff --git a/src/hlua.c b/src/hlua.c
index ea800ee..9291517 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -5163,6 +5163,9 @@
 	struct hlua_function *fcn = (struct hlua_function *)private;
 	struct stream *stream = smp->strm;
 
+	if (!stream)
+		return 0;
+
 	/* In the execution wrappers linked with a stream, the
 	 * Lua context can be not initialized. This behavior
 	 * permits to save performances because a systematic
@@ -5254,7 +5257,8 @@
 
 /* Wrapper called by HAProxy to execute a sample-fetch. this wrapper
  * doesn't allow "yield" functions because the HAProxy engine cannot
- * resume sample-fetches.
+ * resume sample-fetches. This function will be called by the sample
+ * fetch engine to call lua-based fetch operations.
  */
 static int hlua_sample_fetch_wrapper(const struct arg *arg_p, struct sample *smp,
                                      const char *kw, void *private)
@@ -5262,6 +5266,9 @@
 	struct hlua_function *fcn = (struct hlua_function *)private;
 	struct stream *stream = smp->strm;
 
+	if (!stream)
+		return 0;
+
 	/* In the execution wrappers linked with a stream, the
 	 * Lua context can be not initialized. This behavior
 	 * permits to save performances because a systematic
diff --git a/src/payload.c b/src/payload.c
index 710ed4c..620ebe4 100644
--- a/src/payload.c
+++ b/src/payload.c
@@ -46,6 +46,9 @@
 {
 	struct channel *chn;
 
+	if (!smp->strm)
+		return 0;
+
 	chn = ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? &smp->strm->res : &smp->strm->req;
 	if (!chn->buf)
 		return 0;
@@ -68,6 +71,9 @@
 	struct channel *chn;
 	unsigned char *data;
 
+	if (!smp->strm)
+		goto not_ssl_hello;
+
 	chn = ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? &smp->strm->res : &smp->strm->req;
 	if (!chn->buf)
 		goto not_ssl_hello;
@@ -201,6 +207,9 @@
 	struct channel *chn;
 	unsigned char *data;
 
+	if (!smp->strm)
+		goto not_ssl_hello;
+
 	chn = ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? &smp->strm->res : &smp->strm->req;
 	if (!chn->buf)
 		goto not_ssl_hello;
@@ -322,6 +331,9 @@
 	struct channel *chn;
 	const unsigned char *data;
 
+	if (!smp->strm)
+		goto not_ssl_hello;
+
 	chn = ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? &smp->strm->res : &smp->strm->req;
 	if (!chn->buf)
 		goto not_ssl_hello;
@@ -386,8 +398,12 @@
 {
 	int version, bleft, msg_len;
 	const unsigned char *data;
-	struct channel *req = &smp->strm->req;
+	struct channel *req;
+
+	if (!smp->strm)
+		return 0;
 
+	req = &smp->strm->req;
 	if (!req->buf)
 		return 0;
 
@@ -527,6 +543,9 @@
 	struct channel *chn;
 	unsigned char *data;
 
+	if (!smp->strm)
+		goto not_ssl_hello;
+
 	chn = ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? &smp->strm->res : &smp->strm->req;
 	if (!chn->buf)
 		goto not_ssl_hello;
@@ -751,6 +770,9 @@
 int
 smp_fetch_rdp_cookie(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
+	if (!smp->strm)
+		return 0;
+
 	return fetch_rdp_cookie_name(smp->strm, smp, args ? args->data.str.str : NULL, args ? args->data.str.len : 0);
 }
 
@@ -786,6 +808,9 @@
 	/* by default buf offset == len offset + len size */
 	/* buf offset could be absolute or relative to len offset + len size if prefixed by + or - */
 
+	if (!smp->strm)
+		return 0;
+
 	chn = ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? &smp->strm->res : &smp->strm->req;
 	if (!chn->buf)
 		return 0;
@@ -836,6 +861,9 @@
 	unsigned int buf_size = arg_p[1].data.sint;
 	struct channel *chn;
 
+	if (!smp->strm)
+		return 0;
+
 	chn = ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? &smp->strm->res : &smp->strm->req;
 	if (!chn->buf)
 		return 0;
diff --git a/src/proto_http.c b/src/proto_http.c
index fbed31e..0be6228 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -9786,14 +9786,13 @@
 	struct http_txn *txn;
 	struct http_msg *msg;
 
-	/* Note: this function may only be used from places where
-	 * http_init_txn() has already been done, and implies that <s>,
-	 * <txn>, and <hdr_idx.v> are properly set. An extra check protects
-	 * against an eventual mistake in the fetch capability matrix.
+	/* Note: it is possible that <s> is NULL when called before stream
+	 * initialization (eg: tcp-request connection), so this function is the
+	 * one responsible for guarding against this case for all HTTP users.
 	 */
-
 	if (!s)
 		return 0;
+
 	if (!s->txn) {
 		if (unlikely(!http_alloc_txn(s)))
 			return 0; /* not enough memory */
@@ -9911,10 +9910,11 @@
 smp_fetch_meth(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
 	int meth;
-	struct http_txn *txn = smp->strm->txn;
+	struct http_txn *txn;
 
 	CHECK_HTTP_MESSAGE_FIRST_PERM();
 
+	txn = smp->strm->txn;
 	meth = txn->meth;
 	smp->data.type = SMP_T_METH;
 	smp->data.u.meth.meth = meth;
@@ -9963,12 +9963,13 @@
 static int
 smp_fetch_rqver(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct http_txn *txn = smp->strm->txn;
+	struct http_txn *txn;
 	char *ptr;
 	int len;
 
 	CHECK_HTTP_MESSAGE_FIRST();
 
+	txn = smp->strm->txn;
 	len = txn->req.sl.rq.v_l;
 	ptr = txn->req.chn->buf->p + txn->req.sl.rq.v;
 
@@ -10041,7 +10042,6 @@
 static int
 smp_fetch_body(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct http_txn *txn = smp->strm->txn;
 	struct http_msg *msg;
 	unsigned long len;
 	unsigned long block1;
@@ -10051,9 +10051,9 @@
 	CHECK_HTTP_MESSAGE_FIRST();
 
 	if ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_REQ)
-		msg = &txn->req;
+		msg = &smp->strm->txn->req;
 	else
-		msg = &txn->rsp;
+		msg = &smp->strm->txn->rsp;
 
 	len  = http_body_bytes(msg);
 	body = b_ptr(msg->chn->buf, -http_data_rewind(msg));
@@ -10089,15 +10089,14 @@
 static int
 smp_fetch_body_len(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct http_txn *txn = smp->strm->txn;
 	struct http_msg *msg;
 
 	CHECK_HTTP_MESSAGE_FIRST();
 
 	if ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_REQ)
-		msg = &txn->req;
+		msg = &smp->strm->txn->req;
 	else
-		msg = &txn->rsp;
+		msg = &smp->strm->txn->rsp;
 
 	smp->data.type = SMP_T_SINT;
 	smp->data.u.sint = http_body_bytes(msg);
@@ -10114,15 +10113,14 @@
 static int
 smp_fetch_body_size(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct http_txn *txn = smp->strm->txn;
 	struct http_msg *msg;
 
 	CHECK_HTTP_MESSAGE_FIRST();
 
 	if ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_REQ)
-		msg = &txn->req;
+		msg = &smp->strm->txn->req;
 	else
-		msg = &txn->rsp;
+		msg = &smp->strm->txn->rsp;
 
 	smp->data.type = SMP_T_SINT;
 	smp->data.u.sint = msg->body_len;
@@ -11503,7 +11501,6 @@
 static int
 smp_fetch_body_param(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct http_txn *txn = smp->strm->txn;
 	struct http_msg *msg;
 	unsigned long len;
 	unsigned long block1;
@@ -11525,9 +11522,9 @@
 		CHECK_HTTP_MESSAGE_FIRST();
 
 		if ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_REQ)
-			msg = &txn->req;
+			msg = &smp->strm->txn->req;
 		else
-			msg = &txn->rsp;
+			msg = &smp->strm->txn->rsp;
 
 		len  = http_body_bytes(msg);
 		body = b_ptr(msg->chn->buf, -http_data_rewind(msg));
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index 264da0c..393ec36 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -4574,7 +4574,7 @@
 smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
 	int back_conn = (kw[4] == 'b') ? 1 : 0;
-	struct connection *conn = objt_conn(smp->strm->si[back_conn].end);
+	struct connection *conn = smp->strm ? objt_conn(smp->strm->si[back_conn].end) : NULL;
 
 	smp->data.type = SMP_T_BOOL;
 	smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
@@ -4621,8 +4621,10 @@
 	int back_conn = (kw[4] == 'b') ? 1 : 0;
 	struct connection *conn;
 
-	smp->flags = 0;
+	if (!smp->strm)
+		return 0;
 
+	smp->flags = 0;
 	conn = objt_conn(smp->strm->si[back_conn].end);
 	if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
 		return 0;
@@ -4650,6 +4652,9 @@
 	struct connection *conn;
 	int sint;
 
+	if (!smp->strm)
+		return 0;
+
 	smp->flags = 0;
 
 	conn = objt_conn(smp->strm->si[back_conn].end);
@@ -4675,6 +4680,9 @@
 	int back_conn = (kw[4] == 'b') ? 1 : 0;
 	struct connection *conn;
 
+	if (!smp->strm)
+		return 0;
+
 	smp->flags = 0;
 
 	conn = objt_conn(smp->strm->si[back_conn].end);
@@ -4696,6 +4704,9 @@
 {
 	struct connection *conn;
 
+	if (!smp->strm)
+		return 0;
+
 	smp->flags = SMP_F_CONST;
 	smp->data.type = SMP_T_STR;
 
@@ -4720,6 +4731,9 @@
 {
 	struct connection *conn;
 
+	if (!smp->strm)
+		return 0;
+
 	smp->flags = SMP_F_CONST;
 	smp->data.type = SMP_T_STR;
 
@@ -4748,6 +4762,9 @@
 	int back_conn = (kw[4] == 'b') ? 1 : 0;
 	struct connection *conn;
 
+	if (!smp->strm)
+		return 0;
+
 	smp->flags = 0;
 
 	conn = objt_conn(smp->strm->si[back_conn].end);
@@ -4777,6 +4794,9 @@
 	SSL_SESSION *ssl_sess;
 	struct connection *conn;
 
+	if (!smp->strm)
+		return 0;
+
 	smp->flags = SMP_F_CONST;
 	smp->data.type = SMP_T_BIN;
 
@@ -4804,6 +4824,9 @@
 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
 	struct connection *conn;
 
+	if (!smp->strm)
+		return 0;
+
 	smp->flags = SMP_F_CONST;
 	smp->data.type = SMP_T_STR;
 
@@ -4831,6 +4854,9 @@
 	int finished_len;
 	struct chunk *finished_trash;
 
+	if (!smp->strm)
+		return 0;
+
 	smp->flags = 0;
 
 	conn = objt_conn(smp->strm->si[back_conn].end);
diff --git a/src/stream.c b/src/stream.c
index 7c10158..b8ed572 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -2817,6 +2817,9 @@
 static int
 smp_fetch_sc_tracked(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
+	if (!smp->strm)
+		return 0;
+
 	smp->flags = SMP_F_VOL_TEST;
 	smp->data.type = SMP_T_BOOL;
 	smp->data.u.sint = !!smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
@@ -2831,8 +2834,12 @@
 static int
 smp_fetch_sc_get_gpt0(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct stkctr *stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
+	struct stkctr *stkctr;
 
+	if (!smp->strm)
+		return 0;
+
+	stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
 	if (!stkctr)
 		return 0;
 
@@ -2857,8 +2864,12 @@
 static int
 smp_fetch_sc_get_gpc0(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct stkctr *stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
+	struct stkctr *stkctr;
+
+	if (!smp->strm)
+		return 0;
 
+	stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
 	if (!stkctr)
 		return 0;
 
@@ -2883,8 +2894,12 @@
 static int
 smp_fetch_sc_gpc0_rate(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct stkctr *stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
+	struct stkctr *stkctr;
+
+	if (!smp->strm)
+		return 0;
 
+	stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
 	if (!stkctr)
 		return 0;
 
@@ -2908,8 +2923,12 @@
 static int
 smp_fetch_sc_inc_gpc0(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct stkctr *stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
+	struct stkctr *stkctr;
+
+	if (!smp->strm)
+		return 0;
 
+	stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
 	if (!stkctr)
 		return 0;
 
@@ -2951,8 +2970,12 @@
 static int
 smp_fetch_sc_clr_gpc0(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct stkctr *stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
+	struct stkctr *stkctr;
 
+	if (!smp->strm)
+		return 0;
+
+	stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
 	if (!stkctr)
 		return 0;
 
@@ -2982,8 +3005,12 @@
 static int
 smp_fetch_sc_conn_cnt(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct stkctr *stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
+	struct stkctr *stkctr;
 
+	if (!smp->strm)
+		return 0;
+
+	stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
 	if (!stkctr)
 		return 0;
 
@@ -3006,8 +3033,12 @@
 static int
 smp_fetch_sc_conn_rate(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct stkctr *stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
+	struct stkctr *stkctr;
+
+	if (!smp->strm)
+		return 0;
 
+	stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
 	if (!stkctr)
 		return 0;
 
@@ -3073,8 +3104,12 @@
 static int
 smp_fetch_sc_conn_cur(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct stkctr *stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
+	struct stkctr *stkctr;
+
+	if (!smp->strm)
+		return 0;
 
+	stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
 	if (!stkctr)
 		return 0;
 
@@ -3097,8 +3132,12 @@
 static int
 smp_fetch_sc_sess_cnt(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct stkctr *stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
+	struct stkctr *stkctr;
+
+	if (!smp->strm)
+		return 0;
 
+	stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
 	if (!stkctr)
 		return 0;
 
@@ -3120,8 +3159,12 @@
 static int
 smp_fetch_sc_sess_rate(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct stkctr *stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
+	struct stkctr *stkctr;
 
+	if (!smp->strm)
+		return 0;
+
+	stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
 	if (!stkctr)
 		return 0;
 
@@ -3145,8 +3188,12 @@
 static int
 smp_fetch_sc_http_req_cnt(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct stkctr *stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
+	struct stkctr *stkctr;
 
+	if (!smp->strm)
+		return 0;
+
+	stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
 	if (!stkctr)
 		return 0;
 
@@ -3169,8 +3216,12 @@
 static int
 smp_fetch_sc_http_req_rate(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct stkctr *stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
+	struct stkctr *stkctr;
+
+	if (!smp->strm)
+		return 0;
 
+	stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
 	if (!stkctr)
 		return 0;
 
@@ -3194,8 +3245,12 @@
 static int
 smp_fetch_sc_http_err_cnt(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct stkctr *stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
+	struct stkctr *stkctr;
+
+	if (!smp->strm)
+		return 0;
 
+	stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
 	if (!stkctr)
 		return 0;
 
@@ -3218,8 +3273,12 @@
 static int
 smp_fetch_sc_http_err_rate(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct stkctr *stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
+	struct stkctr *stkctr;
+
+	if (!smp->strm)
+		return 0;
 
+	stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
 	if (!stkctr)
 		return 0;
 
@@ -3243,8 +3302,12 @@
 static int
 smp_fetch_sc_kbytes_in(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct stkctr *stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
+	struct stkctr *stkctr;
 
+	if (!smp->strm)
+		return 0;
+
+	stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
 	if (!stkctr)
 		return 0;
 
@@ -3267,8 +3330,12 @@
 static int
 smp_fetch_sc_bytes_in_rate(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct stkctr *stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
+	struct stkctr *stkctr;
 
+	if (!smp->strm)
+		return 0;
+
+	stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
 	if (!stkctr)
 		return 0;
 
@@ -3292,8 +3359,12 @@
 static int
 smp_fetch_sc_kbytes_out(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct stkctr *stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
+	struct stkctr *stkctr;
+
+	if (!smp->strm)
+		return 0;
 
+	stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
 	if (!stkctr)
 		return 0;
 
@@ -3316,8 +3387,12 @@
 static int
 smp_fetch_sc_bytes_out_rate(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct stkctr *stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
+	struct stkctr *stkctr;
+
+	if (!smp->strm)
+		return 0;
 
+	stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
 	if (!stkctr)
 		return 0;
 
@@ -3340,8 +3415,12 @@
 static int
 smp_fetch_sc_trackers(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct stkctr *stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
+	struct stkctr *stkctr;
+
+	if (!smp->strm)
+		return 0;
 
+	stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
 	if (!stkctr)
 		return 0;