From be508f158077cab6ed65581cd0e66d5908cf61da Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Thu, 10 Mar 2016 11:47:01 +0100 Subject: [PATCH] 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. --- include/types/sample.h | 2 +- src/backend.c | 6 +++ src/flt_http_comp.c | 4 +- src/hlua.c | 9 +++- src/payload.c | 30 ++++++++++- src/proto_http.c | 35 ++++++------ src/ssl_sock.c | 30 ++++++++++- src/stream.c | 117 ++++++++++++++++++++++++++++++++++------- 8 files changed, 188 insertions(+), 45 deletions(-) diff --git a/include/types/sample.h b/include/types/sample.h index 83b7a9b6b..4a46be836 100644 --- a/include/types/sample.h +++ b/include/types/sample.h @@ -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_*) */ }; diff --git a/src/backend.c b/src/backend.c index 4503d0efb..2c9429975 100644 --- a/src/backend.c +++ b/src/backend.c @@ -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; diff --git a/src/flt_http_comp.c b/src/flt_http_comp.c index 46abe5277..6bbf6a1a1 100644 --- a/src/flt_http_comp.c +++ b/src/flt_http_comp.c @@ -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; diff --git a/src/hlua.c b/src/hlua.c index ea800ee39..9291517b1 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -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 diff --git a/src/payload.c b/src/payload.c index 710ed4c02..620ebe434 100644 --- a/src/payload.c +++ b/src/payload.c @@ -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; diff --git a/src/proto_http.c b/src/proto_http.c index fbed31e09..0be6228bf 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -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 , - * , and are properly set. An extra check protects - * against an eventual mistake in the fetch capability matrix. + /* Note: it is possible that 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)); diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 264da0c1a..393ec364d 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -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); diff --git a/src/stream.c b/src/stream.c index 7c10158a0..b8ed572c5 100644 --- a/src/stream.c +++ b/src/stream.c @@ -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;