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/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;