]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MAJOR: samples: check smp->strm before using it
authorWilly Tarreau <w@1wt.eu>
Thu, 10 Mar 2016 10:47:01 +0000 (11:47 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 10 Mar 2016 15:42:58 +0000 (16:42 +0100)
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.

include/types/sample.h
src/backend.c
src/flt_http_comp.c
src/hlua.c
src/payload.c
src/proto_http.c
src/ssl_sock.c
src/stream.c

index 83b7a9b6b6baba8788fdb71a8919175b957f4b68..4a46be836ee27086987fbc0e629aefb0235ae6d8 100644 (file)
@@ -270,7 +270,7 @@ struct sample {
         */
        struct proxy *px;
        struct session *sess;
-       struct stream *strm;
+       struct stream *strm; /* WARNING! MAY BE NULL! (eg: tcp-request connection) */
        unsigned int opt; /* fetch options (SMP_OPT_*) */
 };
 
index 4503d0efb75f9805b3f330ba91630a3296d257bb..2c9429975d51afe5dcb73f273ce9909eda0759fb 100644 (file)
@@ -1671,6 +1671,9 @@ smp_fetch_connslots(const struct arg *args, struct sample *smp, const char *kw,
 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 @@ smp_fetch_be_id(const struct arg *args, struct sample *smp, const char *kw, void
 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;
 
index 46abe5277eee09bf291966c3a1fd714c5a60ef6a..6bbf6a1a14bdf295cc80115150f8bc104e28f6e0 100644 (file)
@@ -893,7 +893,7 @@ static int
 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 @@ static int
 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;
 
index ea800ee39801c8aa2996b65b9efcba1eaf917944..9291517b129c2edfa7a6be202492ef7ff65de115 100644 (file)
@@ -5163,6 +5163,9 @@ static int hlua_sample_conv_wrapper(const struct arg *arg_p, struct sample *smp,
        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 @@ static int hlua_sample_conv_wrapper(const struct arg *arg_p, struct sample *smp,
 
 /* 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 @@ static int hlua_sample_fetch_wrapper(const struct arg *arg_p, struct sample *smp
        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
index 710ed4c027ec3437246f08d8e65e2263d9c555c5..620ebe4346e2cc9a05de0083015e9f5b2cc1f0b7 100644 (file)
@@ -46,6 +46,9 @@ smp_fetch_len(const struct arg *args, struct sample *smp, const char *kw, void *
 {
        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 @@ smp_fetch_req_ssl_st_ext(const struct arg *args, struct sample *smp, const char
        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 @@ smp_fetch_req_ssl_ec_ext(const struct arg *args, struct sample *smp, const char
        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 @@ smp_fetch_ssl_hello_type(const struct arg *args, struct sample *smp, const char
        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 @@ smp_fetch_req_ssl_ver(const struct arg *args, struct sample *smp, const char *kw
 {
        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 @@ smp_fetch_ssl_hello_sni(const struct arg *args, struct sample *smp, const char *
        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 @@ fetch_rdp_cookie_name(struct stream *s, struct sample *smp, const char *cname, i
 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 @@ smp_fetch_payload_lv(const struct arg *arg_p, struct sample *smp, const char *kw
        /* 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 @@ smp_fetch_payload(const struct arg *arg_p, struct sample *smp, const char *kw, v
        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;
index fbed31e093061a661c4c7025bef22f52f45b9297..0be6228bf0111f718d52938fc1dc4db0e073e420 100644 (file)
@@ -9786,14 +9786,13 @@ int smp_prefetch_http(struct proxy *px, struct stream *s, unsigned int opt,
        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 @@ static int
 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 struct pattern *pat_match_meth(struct sample *smp, struct pattern_expr *e
 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 @@ smp_fetch_stcode(const struct arg *args, struct sample *smp, const char *kw, voi
 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 @@ smp_fetch_body(const struct arg *args, struct sample *smp, const char *kw, void
        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 @@ smp_fetch_body(const struct arg *args, struct sample *smp, const char *kw, void
 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 @@ smp_fetch_body_len(const struct arg *args, struct sample *smp, const char *kw, v
 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 @@ smp_fetch_url_param(const struct arg *args, struct sample *smp, const char *kw,
 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 @@ smp_fetch_body_param(const struct arg *args, struct sample *smp, const char *kw,
                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));
index 264da0c1ac619f6c7a1ec51f5fe674d110bd1658..393ec364d393b59594ed02aeb0d06656dca5d5b2 100644 (file)
@@ -4574,7 +4574,7 @@ static int
 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 @@ smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *
        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 @@ smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const c
        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 @@ smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const c
        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 @@ smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw,
 {
        struct connection *conn;
 
+       if (!smp->strm)
+               return 0;
+
        smp->flags = SMP_F_CONST;
        smp->data.type = SMP_T_STR;
 
@@ -4720,6 +4731,9 @@ smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw
 {
        struct connection *conn;
 
+       if (!smp->strm)
+               return 0;
+
        smp->flags = SMP_F_CONST;
        smp->data.type = SMP_T_STR;
 
@@ -4748,6 +4762,9 @@ smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char
        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 @@ smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const ch
        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 @@ smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw,
 #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 @@ smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const cha
        int finished_len;
        struct chunk *finished_trash;
 
+       if (!smp->strm)
+               return 0;
+
        smp->flags = 0;
 
        conn = objt_conn(smp->strm->si[back_conn].end);
index 7c10158a002d4465aff793e24a66315d691c4b8d..b8ed572c5b48574210c6b26f1c85074f07e93ab2 100644 (file)
@@ -2817,6 +2817,9 @@ smp_create_src_stkctr(struct session *sess, struct stream *strm, const struct ar
 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 @@ smp_fetch_sc_tracked(const struct arg *args, struct sample *smp, const char *kw,
 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 @@ smp_fetch_sc_get_gpt0(const struct arg *args, struct sample *smp, const char *kw
 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 @@ smp_fetch_sc_get_gpc0(const struct arg *args, struct sample *smp, const char *kw
 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 @@ smp_fetch_sc_gpc0_rate(const struct arg *args, struct sample *smp, const char *k
 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 @@ smp_fetch_sc_inc_gpc0(const struct arg *args, struct sample *smp, const char *kw
 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 @@ smp_fetch_sc_clr_gpc0(const struct arg *args, struct sample *smp, const char *kw
 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 @@ smp_fetch_sc_conn_cnt(const struct arg *args, struct sample *smp, const char *kw
 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 @@ smp_fetch_src_updt_conn_cnt(const struct arg *args, struct sample *smp, const ch
 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 @@ smp_fetch_sc_conn_cur(const struct arg *args, struct sample *smp, const char *kw
 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 @@ smp_fetch_sc_sess_cnt(const struct arg *args, struct sample *smp, const char *kw
 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 @@ smp_fetch_sc_sess_rate(const struct arg *args, struct sample *smp, const char *k
 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 @@ smp_fetch_sc_http_req_cnt(const struct arg *args, struct sample *smp, const char
 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 @@ smp_fetch_sc_http_req_rate(const struct arg *args, struct sample *smp, const cha
 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 @@ smp_fetch_sc_http_err_cnt(const struct arg *args, struct sample *smp, const char
 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 @@ smp_fetch_sc_http_err_rate(const struct arg *args, struct sample *smp, const cha
 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 @@ smp_fetch_sc_kbytes_in(const struct arg *args, struct sample *smp, const char *k
 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 @@ smp_fetch_sc_bytes_in_rate(const struct arg *args, struct sample *smp, const cha
 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 @@ smp_fetch_sc_kbytes_out(const struct arg *args, struct sample *smp, const char *
 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 @@ smp_fetch_sc_bytes_out_rate(const struct arg *args, struct sample *smp, const ch
 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;