From: Willy Tarreau Date: Mon, 27 Jul 2026 08:01:30 +0000 (+0200) Subject: BUG/MINOR: http-fetch: fix a NULL channel dereference in smp_fetch_body() X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=035fd3f58fe8c9164e38bafffc27e5e7ebeb4394;p=thirdparty%2Fhaproxy.git BUG/MINOR: http-fetch: fix a NULL channel dereference in smp_fetch_body() smp_fetch_body() is also used from the health-check context, where the HTX message comes from bi> and where there is no channel at all: for "res.body", SMP_RES_CHN(smp) evaluates to NULL because smp->strm is NULL. The function is aware of this and guards the channel a few lines below: if (!finished && (check || (chn && !channel_full(chn, global.tune.maxrewrite) && but the trash chunk retrieval isn't: chk = get_best_trash_chunk(&chn->buf, htx->data); so as soon as a check response is made of more than one HTX DATA block, a bogus address close to NULL is dereferenced and the worker crashes. Let's use the check input buffer when there is no channel, as done elsewhere. Note that no reproducer could be built: with the h1 mux the successive DATA blocks of a check response always end up appended to the same HTX block, so the multi-block case was not reachable in practice. The dereference is nevertheless plainly invalid. This is a regression introduced by commit ac37158a6 ("BUG/MEDIUM: chunk: Review chunks usage to not retrieve a large buffer by error") in 3.5-dev2, which replaced get_trash_chunk_sz(htx->data), that did not look at the channel, with get_best_trash_chunk(&chn->buf, htx->data). smp_fetch_body_param() received the same change but is only reachable through "req.body_param", for which is always NULL and thus always set, so it is not affected. It must be backported wherever the commit above was backported, so 3.4 and above. --- diff --git a/src/http_fetch.c b/src/http_fetch.c index 2441a2969..6133983c1 100644 --- a/src/http_fetch.c +++ b/src/http_fetch.c @@ -685,7 +685,10 @@ static int smp_fetch_body(const struct arg *args, struct sample *smp, const char /* More than one DATA block we must use a trash */ if (!chk) { smp->flags &= ~SMP_F_CONST; - chk = get_best_trash_chunk(&chn->buf, htx->data); + /* is NULL in the health-check context, + * where the message comes from bi> + */ + chk = get_best_trash_chunk((chn ? &chn->buf : &check->bi), htx->data); if (!chk || !chunk_istcat(chk, body)) return 0; }