BUG/MEDIUM: capture: capture.{req,res}.* crash without a stream
Since commit 5f940703b3 ("MINOR: log: Don't depends on a stream to process
samples in log-format string") it has become quite obvious that a few sample
fetch functions and converters were still heavily dependent on the presence
of a stream without testing for it.
The capture.req.hdr, capture.res.hdr, capture.req.method, capture.req.uri,
capture.req.ver and capture.res.ver sample fetches used to assume the
presence of a stream, which is not necessarily the case (especially after
the commit above) and would crash haproxy if incorrectly used. Let's make
sure they check for this stream.
This fix adds a check for the stream's existence, and should be backported
to all stable versions up to 1.6.
(cherry picked from commit 0898c2d2f2c5ae043a443550992efd90ec18b2ab)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 9bec56b7734ea75c6f235bc3f6bf03569b9bf2c5)
[wt: small context adjustments]
Signed-off-by: Willy Tarreau <w@1wt.eu>
diff --git a/src/http_fetch.c b/src/http_fetch.c
index be9e597..ba2ea04 100644
--- a/src/http_fetch.c
+++ b/src/http_fetch.c
@@ -2011,12 +2011,16 @@
*/
static int smp_fetch_capture_req_hdr(const struct arg *args, struct sample *smp, const char *kw, void *private)
{
- struct proxy *fe = strm_fe(smp->strm);
+ struct proxy *fe;
int idx;
if (!args || args->type != ARGT_SINT)
return 0;
+ if (!smp->strm)
+ return 0;
+
+ fe = strm_fe(smp->strm);
idx = args->data.sint;
if (idx > (fe->nb_req_cap - 1) || smp->strm->req_cap == NULL || smp->strm->req_cap[idx] == NULL)
@@ -2035,12 +2039,16 @@
*/
static int smp_fetch_capture_res_hdr(const struct arg *args, struct sample *smp, const char *kw, void *private)
{
- struct proxy *fe = strm_fe(smp->strm);
+ struct proxy *fe;
int idx;
if (!args || args->type != ARGT_SINT)
return 0;
+ if (!smp->strm)
+ return 0;
+
+ fe = strm_fe(smp->strm);
idx = args->data.sint;
if (idx > (fe->nb_rsp_cap - 1) || smp->strm->res_cap == NULL || smp->strm->res_cap[idx] == NULL)
@@ -2058,9 +2066,13 @@
static int smp_fetch_capture_req_method(const struct arg *args, struct sample *smp, const char *kw, void *private)
{
struct buffer *temp;
- struct http_txn *txn = smp->strm->txn;
+ struct http_txn *txn;
char *ptr;
+ if (!smp->strm)
+ return 0;
+
+ txn = smp->strm->txn;
if (!txn || !txn->uri)
return 0;
@@ -2083,10 +2095,14 @@
/* Extracts the path in the HTTP request, the txn->uri should be filled before the call */
static int smp_fetch_capture_req_uri(const struct arg *args, struct sample *smp, const char *kw, void *private)
{
- struct http_txn *txn = smp->strm->txn;
+ struct http_txn *txn;
struct ist path;
const char *ptr;
+ if (!smp->strm)
+ return 0;
+
+ txn = smp->strm->txn;
if (!txn || !txn->uri)
return 0;
@@ -2121,8 +2137,12 @@
*/
static int smp_fetch_capture_req_ver(const struct arg *args, struct sample *smp, const char *kw, void *private)
{
- struct http_txn *txn = smp->strm->txn;
+ struct http_txn *txn;
+
+ if (!smp->strm)
+ return 0;
+ txn = smp->strm->txn;
if (!txn || txn->req.msg_state < HTTP_MSG_HDR_FIRST)
return 0;
@@ -2143,8 +2163,12 @@
*/
static int smp_fetch_capture_res_ver(const struct arg *args, struct sample *smp, const char *kw, void *private)
{
- struct http_txn *txn = smp->strm->txn;
+ struct http_txn *txn;
+
+ if (!smp->strm)
+ return 0;
+ txn = smp->strm->txn;
if (!txn || txn->rsp.msg_state < HTTP_MSG_HDR_FIRST)
return 0;