DEBUG: buf: add BUG_ON_HOT() to most buffer management functions

A number of tests are now performed in low-level buffer management
functions to verify that we're not appending data to a full buffer
for example, or that the buffer passed in argument is consistent in
that its data don't outweigh its size. The few functions that already
involve memcpy() or memmove() instead got a BUG_ON() that will always
be enabled, since the overhead remains minimalist.
This commit is contained in:
Willy Tarreau 2022-02-28 16:11:33 +01:00
parent a8f4b34bb7
commit 8873b85bd9

View File

@ -81,6 +81,7 @@ static inline size_t b_data(const struct buffer *b)
/* b_room() : returns the amount of room left in the buffer */
static inline size_t b_room(const struct buffer *b)
{
BUG_ON_HOT(b->data > b->size);
return b->size - b_data(b);
}
@ -210,6 +211,7 @@ static inline char *b_tail(const struct buffer *b)
static inline size_t b_next_ofs(const struct buffer *b, size_t o)
{
o++;
BUG_ON_HOT(o > b->size);
if (o == b->size)
o = 0;
return o;
@ -218,6 +220,7 @@ static inline size_t b_next_ofs(const struct buffer *b, size_t o)
static inline char *b_next(const struct buffer *b, const char *p)
{
p++;
BUG_ON_HOT(p > b_wrap(b));
if (p == b_wrap(b))
p = b_orig(b);
return (char *)p;
@ -232,6 +235,7 @@ static inline size_t b_dist(const struct buffer *b, const char *from, const char
{
ssize_t dist = to - from;
BUG_ON_HOT((dist > 0 && dist > b_size(b)) || (dist < 0 && -dist > b_size(b)));
dist += dist < 0 ? b_size(b) : 0;
return dist;
}
@ -241,6 +245,7 @@ static inline size_t b_dist(const struct buffer *b, const char *from, const char
*/
static inline int b_almost_full(const struct buffer *b)
{
BUG_ON_HOT(b->data > b->size);
return b_data(b) >= b_size(b) * 3 / 4;
}
@ -259,6 +264,7 @@ static inline int b_almost_full(const struct buffer *b)
*/
static inline int b_space_wraps(const struct buffer *b)
{
BUG_ON_HOT(b->data > b->size);
if ((ssize_t)__b_head_ofs(b) <= 0)
return 0;
if (__b_tail_ofs(b) >= b_size(b))
@ -297,6 +303,8 @@ static inline size_t b_contig_space(const struct buffer *b)
{
size_t left, right;
BUG_ON_HOT(b->data > b->size);
right = b_head_ofs(b);
left = right + b_data(b);
@ -319,6 +327,10 @@ static inline size_t b_getblk(const struct buffer *buf, char *blk, size_t len, s
{
size_t firstblock;
BUG_ON(buf->data > buf->size);
BUG_ON(offset > buf->data);
BUG_ON(offset + len > buf->data);
if (len + offset > b_data(buf))
return 0;
@ -351,6 +363,10 @@ static inline size_t b_getblk_nc(const struct buffer *buf, const char **blk1, si
{
size_t l1;
BUG_ON_HOT(buf->data > buf->size);
BUG_ON_HOT(ofs > buf->data);
BUG_ON_HOT(ofs + max > buf->data);
if (!max)
return 0;
@ -393,18 +409,21 @@ static inline struct buffer b_make(char *area, size_t size, size_t head, size_t
/* b_sub() : decreases the buffer length by <count> */
static inline void b_sub(struct buffer *b, size_t count)
{
BUG_ON_HOT(b->data < count);
b->data -= count;
}
/* b_add() : increase the buffer length by <count> */
static inline void b_add(struct buffer *b, size_t count)
{
BUG_ON_HOT(b->data + count > b->size);
b->data += count;
}
/* b_set_data() : sets the buffer's length */
static inline void b_set_data(struct buffer *b, size_t len)
{
BUG_ON_HOT(len > b->size);
b->data = len;
}
@ -414,6 +433,7 @@ static inline void b_set_data(struct buffer *b, size_t len)
*/
static inline void b_del(struct buffer *b, size_t del)
{
BUG_ON_HOT(b->data < del);
b->data -= del;
b->head += del;
if (b->head >= b->size)
@ -443,6 +463,8 @@ static inline void b_slow_realign(struct buffer *b, char *swap, size_t output)
size_t block1 = output;
size_t block2 = 0;
BUG_ON_HOT(b->data > b->size);
/* process output data in two steps to cover wrapping */
if (block1 > b_size(b) - b_head_ofs(b)) {
block2 = b_size(b) - b_head_ofs(b);
@ -480,6 +502,9 @@ static inline void b_slow_realign_ofs(struct buffer *b, char *swap, size_t ofs)
size_t block1 = b_data(b);
size_t block2 = 0;
BUG_ON_HOT(b->data > b->size);
BUG_ON_HOT(ofs > b->size);
if (__b_tail_ofs(b) >= b_size(b)) {
block2 = b_tail_ofs(b);
block1 -= block2;
@ -638,10 +663,13 @@ static inline void b_move(const struct buffer *b, size_t src, size_t len, ssize_
size_t dst = src + size + shift;
size_t cnt;
BUG_ON(len > size);
if (dst >= size)
dst -= size;
if (shift < 0) {
BUG_ON(-shift >= size);
/* copy from left to right */
for (; (cnt = len); len -= cnt) {
if (cnt > size - src)
@ -659,6 +687,7 @@ static inline void b_move(const struct buffer *b, size_t src, size_t len, ssize_
}
}
else if (shift > 0) {
BUG_ON(shift >= size);
/* copy from right to left */
for (; (cnt = len); len -= cnt) {
size_t src_end = src + len;
@ -692,6 +721,8 @@ static inline int b_rep_blk(struct buffer *b, char *pos, char *end, const char *
{
int delta;
BUG_ON(pos < b->area || pos >= b->area + b->size);
delta = len - (end - pos);
if (__b_tail(b) + delta > b_wrap(b))
@ -757,6 +788,8 @@ static inline void __b_put_varint(struct buffer *b, uint64_t v)
char *wrap = b_wrap(b);
char *tail = b_tail(b);
BUG_ON_HOT(data >= size);
if (v >= 0xF0) {
/* more than one byte, first write the 4 least significant
* bits, then follow with 7 bits per byte.
@ -777,6 +810,7 @@ static inline void __b_put_varint(struct buffer *b, uint64_t v)
/* last byte */
*tail = v;
BUG_ON_HOT(data >= size);
data++;
b->data = data;
}
@ -793,6 +827,8 @@ static inline int b_put_varint(struct buffer *b, uint64_t v)
char *tail = b_tail(b);
if (data != size && v >= 0xF0) {
BUG_ON_HOT(data > size);
/* more than one byte, first write the 4 least significant
* bits, then follow with 7 bits per byte.
*/
@ -877,6 +913,8 @@ static inline int b_peek_varint(struct buffer *b, size_t ofs, uint64_t *vptr)
uint64_t v = 0;
int bits = 0;
BUG_ON_HOT(ofs > data);
if (data != 0 && (*head >= 0xF0)) {
v = *head;
bits += 4;