]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
DEBUG: channel: add consistency checks using BUG_ON_HOT() in some key functions
authorWilly Tarreau <w@1wt.eu>
Mon, 28 Feb 2022 15:55:51 +0000 (16:55 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 28 Feb 2022 15:59:17 +0000 (16:59 +0100)
A few functions such as c_adv(), c_rew(), co_set_data() or co_skip() got a
BUG_ON_HOT() to make sure they're not used to push more data than available
in the buffer. Note that with HTX the margin can be high and will less easily
trigger, but the goal is to detect a misuse early enough.

co_data() should never be called with a wrong c->output. At least it never
happens in regtests, but we're adding a CHECK_IF_HOT() there to avoid crashing
but report it if it ever happened when the hot path checks are enabled.

include/haproxy/channel.h

index 57e3d9853479e5cd443c73c66cfae4a329b40ec3..6829cbb1e486d62ae44a7ecbe370356cdf8799c6 100644 (file)
@@ -127,6 +127,7 @@ static inline size_t c_full(const struct channel *c)
 /* co_data() : returns the amount of output data in the channel's buffer */
 static inline size_t co_data(const struct channel *c)
 {
+       CHECK_IF_HOT(c->output > c_data(c));
        return c->output;
 }
 
@@ -170,6 +171,7 @@ static inline char *c_ptr(const struct channel *c, ssize_t ofs)
 static inline void c_adv(struct channel *c, size_t adv)
 {
        c->output += adv;
+       BUG_ON_HOT(c->output > c_data(c));
 }
 
 /* c_rew() : rewinds the channel's buffer by <adv> bytes, which means that the
@@ -179,6 +181,7 @@ static inline void c_adv(struct channel *c, size_t adv)
  */
 static inline void c_rew(struct channel *c, size_t adv)
 {
+       BUG_ON_HOT(c->output < adv);
        c->output -= adv;
 }
 
@@ -191,6 +194,7 @@ static inline void c_realign_if_empty(struct channel *chn)
 /* Sets the amount of output for the channel */
 static inline void co_set_data(struct channel *c, size_t output)
 {
+       BUG_ON_HOT(output > c_data(c));
        c->output = output;
 }
 
@@ -932,6 +936,7 @@ static inline int32_t channel_htx_fwd_headers(struct channel *chn, struct htx *h
  */
 static inline void co_skip(struct channel *chn, int len)
 {
+       BUG_ON_HOT(len > chn->output);
        b_del(&chn->buf, len);
        chn->output -= len;
        c_realign_if_empty(chn);
@@ -946,8 +951,10 @@ static inline void co_htx_skip(struct channel *chn, struct htx *htx, int len)
        struct htx_ret htxret;
 
        htxret = htx_drain(htx, len);
-       if (htxret.ret)
+       if (htxret.ret) {
+               BUG_ON_HOT(htxret.ret > chn->output);
                chn->output -= htxret.ret;
+       }
 }
 
 /* Tries to copy chunk <chunk> into the channel's buffer after length controls.