From: Christopher Faulet Date: Thu, 9 Apr 2026 19:00:00 +0000 (+0200) Subject: BUG/MEDIUM: samples: Fix handling of SMP_T_METH samples X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b0a9216ca5375c076fd144db68365d7a9a41a161;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: samples: Fix handling of SMP_T_METH samples Samples of type SMP_T_METH were not properly handled in smp_dup(), smp_is_safe() and smp_is_rw(). For "other" methods, for instance PATCH, a fallback was performed on the SMP_T_STR type. Only the buffer considered changed. "smp->data.u.meth.str" should be used for the SMP_T_METH samples while smp->data.u.str should be used for SMP_T_STR samples. However, in smp_dup(), the result was stored in wrong buffer, the string one instead of the method one. In smp_is_safe() and smp_is_rw(), the method buffer was not used at all. We now take care to use the right buffer. This patch must be backported to all stable versions. --- diff --git a/include/haproxy/sample.h b/include/haproxy/sample.h index d60d0077c..96ae06757 100644 --- a/include/haproxy/sample.h +++ b/include/haproxy/sample.h @@ -101,6 +101,8 @@ struct sample *smp_set_owner(struct sample *smp, struct proxy *px, static inline int smp_is_safe(struct sample *smp) { + struct buffer *buf; + switch (smp->data.type) { case SMP_T_METH: if (smp->data.u.meth.meth != HTTP_METH_OTHER) @@ -108,16 +110,17 @@ int smp_is_safe(struct sample *smp) __fallthrough; case SMP_T_STR: - if (!smp->data.u.str.size || smp->data.u.str.data >= smp->data.u.str.size) + buf = (smp->data.type == SMP_T_STR ? &smp->data.u.str : &smp->data.u.meth.str); + if (!buf->size || buf->data >= buf->size) return 0; - if (smp->data.u.str.area[smp->data.u.str.data] == 0) + if (buf->area[buf->data] == 0) return 1; if (smp->flags & SMP_F_CONST) return 0; - smp->data.u.str.area[smp->data.u.str.data] = 0; + buf->area[buf->data] = 0; return 1; case SMP_T_BIN: @@ -148,6 +151,8 @@ int smp_make_safe(struct sample *smp) static inline int smp_is_rw(struct sample *smp) { + struct buffer *buf; + if (smp->flags & SMP_F_CONST) return 0; @@ -158,12 +163,12 @@ int smp_is_rw(struct sample *smp) __fallthrough; case SMP_T_STR: - if (!smp->data.u.str.size || - smp->data.u.str.data >= smp->data.u.str.size) + buf = (smp->data.type == SMP_T_STR ? &smp->data.u.str : &smp->data.u.meth.str); + if (!buf->size || buf->data >= buf->size) return 0; - if (smp->data.u.str.area[smp->data.u.str.data] != 0) - smp->data.u.str.area[smp->data.u.str.data] = 0; + if (buf->area[buf->data] != 0) + buf->area[buf->data] = 0; return 1; case SMP_T_BIN: diff --git a/src/sample.c b/src/sample.c index 42f211ad4..22172a33f 100644 --- a/src/sample.c +++ b/src/sample.c @@ -885,7 +885,7 @@ static int c_int2str(struct sample *smp) */ int smp_dup(struct sample *smp) { - struct buffer *trash; + struct buffer *trash, *buf; switch (smp->data.type) { case SMP_T_BOOL: @@ -902,19 +902,17 @@ int smp_dup(struct sample *smp) __fallthrough; case SMP_T_STR: - trash = get_trash_chunk_sz(smp->data.u.str.data+1); + buf = (smp->data.type == SMP_T_STR ? &smp->data.u.str : &smp->data.u.meth.str); + trash = get_trash_chunk_sz(buf->data+1); if (!trash) return 0; - trash->data = smp->data.type == SMP_T_STR ? - smp->data.u.str.data : smp->data.u.meth.str.data; + trash->data = buf->data; if (trash->data > trash->size - 1) trash->data = trash->size - 1; - memcpy(trash->area, smp->data.type == SMP_T_STR ? - smp->data.u.str.area : smp->data.u.meth.str.area, - trash->data); + memcpy(trash->area, buf->area, trash->data); trash->area[trash->data] = 0; - smp->data.u.str = *trash; + *buf = *trash; break; case SMP_T_BIN: