From: Amaury Denoyelle Date: Mon, 16 May 2022 09:09:29 +0000 (+0200) Subject: BUG/MEDIUM: ncbuf: fix null buffer usage X-Git-Tag: v2.6-dev11~105 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=48fbad45e2642748520f7775b4637776687d92cd;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: ncbuf: fix null buffer usage ncbuf public API functions were not ready to deal with a NCBUF_NULL as parameter. Strenghten these functions by handling it properly. Most of the functions will consider the buffer as empty and silently returns. The only exception is ncb_init(buf) which cannot be called with a NCBUF_NULL. This seems legitimate to consider this as a bug and not silently failed in this case. --- diff --git a/src/ncbuf.c b/src/ncbuf.c index 4012adcf45..bc636fa842 100644 --- a/src/ncbuf.c +++ b/src/ncbuf.c @@ -127,6 +127,9 @@ static struct ncb_blk ncb_blk_first(const struct ncbuf *buf) { struct ncb_blk blk; + if (ncb_is_null(buf)) + return NCB_BLK_NULL; + blk.st = ncb_head(buf); blk.sz_ptr = ncb_reserved(buf); @@ -198,6 +201,9 @@ static struct ncb_blk ncb_blk_find(const struct ncbuf *buf, ncb_sz_t off) { struct ncb_blk blk; + if (ncb_is_null(buf)) + return NCB_BLK_NULL; + BUG_ON_HOT(off >= ncb_size(buf)); for (blk = ncb_blk_first(buf); off > blk.off + blk.sz; @@ -373,10 +379,13 @@ int ncb_is_null(const struct ncbuf *buf) } /* Initialize or reset by clearing all data. Its size is untouched. - * Buffer is positioned to offset. Use 0 to realign it. + * Buffer is positioned to offset. Use 0 to realign it. must not + * be NCBUF_NULL. */ void ncb_init(struct ncbuf *buf, ncb_sz_t head) { + BUG_ON_HOT(ncb_is_null(buf)); + BUG_ON_HOT(head >= buf->size); buf->head = head; @@ -425,6 +434,9 @@ char *ncb_wrap(const struct ncbuf *buf) */ ncb_sz_t ncb_size(const struct ncbuf *buf) { + if (ncb_is_null(buf)) + return 0; + return buf->size - NCB_RESERVED_SZ; } @@ -445,6 +457,9 @@ ncb_sz_t ncb_total_data(const struct ncbuf *buf) /* Returns true if there is no data anywhere in . */ int ncb_is_empty(const struct ncbuf *buf) { + if (ncb_is_null(buf)) + return 1; + BUG_ON_HOT(*ncb_reserved(buf) + *ncb_head(buf) > ncb_size(buf)); return *ncb_reserved(buf) == 0 && *ncb_head(buf) == ncb_size(buf); } @@ -452,6 +467,9 @@ int ncb_is_empty(const struct ncbuf *buf) /* Returns true if no more data can be inserted in . */ int ncb_is_full(const struct ncbuf *buf) { + if (ncb_is_null(buf)) + return 0; + BUG_ON_HOT(ncb_read_off(buf, ncb_reserved(buf)) > ncb_size(buf)); return ncb_read_off(buf, ncb_reserved(buf)) == ncb_size(buf); } @@ -465,6 +483,9 @@ ncb_sz_t ncb_data(const struct ncbuf *buf, ncb_sz_t off) struct ncb_blk blk = ncb_blk_find(buf, off); ncb_sz_t off_blk = ncb_blk_off(blk, off); + if (ncb_blk_is_null(blk)) + return 0; + /* if at the frontier between two and is gap, retrieve the * next data block. */ @@ -791,13 +812,21 @@ static int ncbuf_test(ncb_sz_t head, int reset, int print_delay) bufarea = malloc(bufsize); + fprintf(stderr, "running unit tests\n"); + + b = NCBUF_NULL; + BUG_ON(!ncb_is_null(&b)); + NCB_DATA_EQ(&b, 0, 0); + NCB_TOTAL_DATA_EQ(&b, 0); + BUG_ON(ncb_size(&b) != 0); + BUG_ON(!ncb_is_empty(&b)); + BUG_ON(ncb_is_full(&b)); + b.area = bufarea; b.size = bufsize; b.head = head; NCB_INIT(&b); - fprintf(stderr, "running unit tests\n"); - /* insertion test suite */ NCB_INIT(&b); NCB_DATA_EQ(&b, 0, 0); NCB_DATA_EQ(&b, bufsize - NCB_RESERVED_SZ - 1, 0); /* first and last offset */