smp_fetch_body() is also used from the health-check context, where the HTX
message comes from <check->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 <check> is always NULL and thus <chn> always set, so it is not affected.
It must be backported wherever the commit above was backported, so 3.4 and
above.