From 369858730ad7fddb1a12bcb93b9c7989bc28342b Mon Sep 17 00:00:00 2001 From: Evan Hunt Date: Wed, 17 Aug 2022 13:39:38 -0700 Subject: [PATCH] change ISC__BUFFER macros to inline functions previously, when ISC_BUFFER_USEINLINE was defined, macros were used to implement isc_buffer primitives (isc_buffer_init(), isc_buffer_region(), etc). these macros were missing the DbC assertions for those primitives, which made it possible for coding errors to go undetected. adding the assertions to the macros caused compiler warnings on some platforms. therefore, this commit converts the ISC__BUFFER macros to static inline functions instead, with assertions included, and eliminates the non-inline implementation from buffer.c. the --enable-buffer-useinline configure option has been removed. (cherry picked from commit 1926ddc98765571289ce489f1b20dd33f9b00936) --- .gitlab-ci.yml | 12 +- configure.ac | 12 - lib/isc/buffer.c | 298 --------- lib/isc/include/isc/buffer.h | 1116 ++++++++++++++++------------------ 4 files changed, 549 insertions(+), 889 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index bfc6a7241e..7f543722d2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -615,7 +615,7 @@ gcc:oraclelinux8:amd64: variables: CC: gcc CFLAGS: "${CFLAGS_COMMON}" - EXTRA_CONFIGURE: "--enable-buffer-useinline --with-libidn2" + EXTRA_CONFIGURE: "--with-libidn2" <<: *oraclelinux_8_amd64_image <<: *build_job @@ -1486,6 +1486,16 @@ gcov: # Help gcovr process the nasty tricks in lib/dns/code.h, where we include C # source files from lib/dns/rdata/*/, using an even nastier trick. - find lib/dns/rdata/* -name "*.c" -execdir cp -f "{}" ../../ \; + # Help gcovr process inline functions in headers + - cp -f lib/dns/include/dns/*.h lib/dns/ + - cp -f lib/dns/include/dns/*.h lib/ns/ + - cp -f lib/isc/include/isc/*.h lib/isc/ + - cp -f lib/isc/include/isc/*.h lib/dns/ + - cp -f lib/isc/include/isc/*.h lib/ns/ + - find bin lib -maxdepth 1 -mindepth 1 -type d -exec cp -f lib/isc/include/isc/buffer.h "{}" \; + - cp -f lib/isc/include/isc/buffer.h fuzz/ + - cp -f lib/isc/include/isc/buffer.h lib/isc/netmgr/buffer.h + - cp -f lib/isc/include/isc/hash.h lib/dns/hash.h # Generate XML file in the Cobertura XML format suitable for use by GitLab # for the purpose of displaying code coverage information in the diff view # of a given merge request. diff --git a/configure.ac b/configure.ac index e148900650..6eaac533a4 100644 --- a/configure.ac +++ b/configure.ac @@ -186,18 +186,6 @@ PKG_PROG_PKG_CONFIG AS_IF([test -z "$PKG_CONFIG"], [AC_MSG_ERROR([The pkg-config script could not be found or is too old.])]) -# [pairwise: --enable-buffer-useinline, --disable-buffer-useinline] -AC_ARG_ENABLE(buffer_useinline, - AS_HELP_STRING([--enable-buffer-useinline], - [define ISC_BUFFER_USEINLINE when compiling - [default=yes]]), - if test yes = "${enable}" - then - AC_DEFINE([ISC_BUFFER_USEINLINE], [1], - [Define if you want to use inline buffers]) - fi, - AC_DEFINE([ISC_BUFFER_USEINLINE], [1])) - # Fuzzing is not included in pairwise testing as fuzzing tools are # not present in the relevant Docker image. # diff --git a/lib/isc/buffer.c b/lib/isc/buffer.c index 0a38801bee..e7e84dff28 100644 --- a/lib/isc/buffer.c +++ b/lib/isc/buffer.c @@ -24,28 +24,6 @@ #include #include -void -isc__buffer_init(isc_buffer_t *b, void *base, unsigned int length) { - /* - * Make 'b' refer to the 'length'-byte region starting at 'base'. - * XXXDCL see the comment in buffer.h about base being const. - */ - - REQUIRE(b != NULL); - - ISC__BUFFER_INIT(b, base, length); -} - -void -isc__buffer_initnull(isc_buffer_t *b) { - /* - * Initialize a new buffer which has no backing store. This can - * later be grown as needed and swapped in place. - */ - - ISC__BUFFER_INIT(b, NULL, 0); -} - void isc_buffer_reinit(isc_buffer_t *b, void *base, unsigned int length) { /* @@ -69,19 +47,6 @@ isc_buffer_reinit(isc_buffer_t *b, void *base, unsigned int length) { b->length = length; } -void -isc__buffer_invalidate(isc_buffer_t *b) { - /* - * Make 'b' an invalid buffer. - */ - - REQUIRE(ISC_BUFFER_VALID(b)); - REQUIRE(!ISC_LINK_LINKED(b, link)); - REQUIRE(b->mctx == NULL); - - ISC__BUFFER_INVALIDATE(b); -} - void isc_buffer_setautorealloc(isc_buffer_t *b, bool enable) { REQUIRE(ISC_BUFFER_VALID(b)); @@ -89,160 +54,6 @@ isc_buffer_setautorealloc(isc_buffer_t *b, bool enable) { b->autore = enable; } -void -isc__buffer_region(isc_buffer_t *b, isc_region_t *r) { - /* - * Make 'r' refer to the region of 'b'. - */ - - REQUIRE(ISC_BUFFER_VALID(b)); - REQUIRE(r != NULL); - - ISC__BUFFER_REGION(b, r); -} - -void -isc__buffer_usedregion(const isc_buffer_t *b, isc_region_t *r) { - /* - * Make 'r' refer to the used region of 'b'. - */ - - REQUIRE(ISC_BUFFER_VALID(b)); - REQUIRE(r != NULL); - - ISC__BUFFER_USEDREGION(b, r); -} - -void -isc__buffer_availableregion(isc_buffer_t *b, isc_region_t *r) { - /* - * Make 'r' refer to the available region of 'b'. - */ - - REQUIRE(ISC_BUFFER_VALID(b)); - REQUIRE(r != NULL); - - ISC__BUFFER_AVAILABLEREGION(b, r); -} - -void -isc__buffer_add(isc_buffer_t *b, unsigned int n) { - /* - * Increase the 'used' region of 'b' by 'n' bytes. - */ - - REQUIRE(ISC_BUFFER_VALID(b)); - REQUIRE(b->used + n <= b->length); - - ISC__BUFFER_ADD(b, n); -} - -void -isc__buffer_subtract(isc_buffer_t *b, unsigned int n) { - /* - * Decrease the 'used' region of 'b' by 'n' bytes. - */ - - REQUIRE(ISC_BUFFER_VALID(b)); - REQUIRE(b->used >= n); - - ISC__BUFFER_SUBTRACT(b, n); -} - -void -isc__buffer_clear(isc_buffer_t *b) { - /* - * Make the used region empty. - */ - - REQUIRE(ISC_BUFFER_VALID(b)); - - ISC__BUFFER_CLEAR(b); -} - -void -isc__buffer_consumedregion(isc_buffer_t *b, isc_region_t *r) { - /* - * Make 'r' refer to the consumed region of 'b'. - */ - - REQUIRE(ISC_BUFFER_VALID(b)); - REQUIRE(r != NULL); - - ISC__BUFFER_CONSUMEDREGION(b, r); -} - -void -isc__buffer_remainingregion(isc_buffer_t *b, isc_region_t *r) { - /* - * Make 'r' refer to the remaining region of 'b'. - */ - - REQUIRE(ISC_BUFFER_VALID(b)); - REQUIRE(r != NULL); - - ISC__BUFFER_REMAININGREGION(b, r); -} - -void -isc__buffer_activeregion(isc_buffer_t *b, isc_region_t *r) { - /* - * Make 'r' refer to the active region of 'b'. - */ - - REQUIRE(ISC_BUFFER_VALID(b)); - REQUIRE(r != NULL); - - ISC__BUFFER_ACTIVEREGION(b, r); -} - -void -isc__buffer_setactive(isc_buffer_t *b, unsigned int n) { - /* - * Sets the end of the active region 'n' bytes after current. - */ - - REQUIRE(ISC_BUFFER_VALID(b)); - REQUIRE(b->current + n <= b->used); - - ISC__BUFFER_SETACTIVE(b, n); -} - -void -isc__buffer_first(isc_buffer_t *b) { - /* - * Make the consumed region empty. - */ - - REQUIRE(ISC_BUFFER_VALID(b)); - - ISC__BUFFER_FIRST(b); -} - -void -isc__buffer_forward(isc_buffer_t *b, unsigned int n) { - /* - * Increase the 'consumed' region of 'b' by 'n' bytes. - */ - - REQUIRE(ISC_BUFFER_VALID(b)); - REQUIRE(b->current + n <= b->used); - - ISC__BUFFER_FORWARD(b, n); -} - -void -isc__buffer_back(isc_buffer_t *b, unsigned int n) { - /* - * Decrease the 'consumed' region of 'b' by 'n' bytes. - */ - - REQUIRE(ISC_BUFFER_VALID(b)); - REQUIRE(n <= b->current); - - ISC__BUFFER_BACK(b, n); -} - void isc_buffer_compact(isc_buffer_t *b) { unsigned int length; @@ -290,19 +101,6 @@ isc_buffer_getuint8(isc_buffer_t *b) { return (result); } -void -isc__buffer_putuint8(isc_buffer_t *b, uint8_t val) { - isc_result_t result; - REQUIRE(ISC_BUFFER_VALID(b)); - if (b->autore) { - result = isc_buffer_reserve(&b, 1); - REQUIRE(result == ISC_R_SUCCESS); - } - REQUIRE(isc_buffer_availablelength(b) >= 1); - - ISC__BUFFER_PUTUINT8(b, val); -} - uint16_t isc_buffer_getuint16(isc_buffer_t *b) { unsigned char *cp; @@ -324,32 +122,6 @@ isc_buffer_getuint16(isc_buffer_t *b) { return (result); } -void -isc__buffer_putuint16(isc_buffer_t *b, uint16_t val) { - isc_result_t result; - REQUIRE(ISC_BUFFER_VALID(b)); - if (b->autore) { - result = isc_buffer_reserve(&b, 2); - REQUIRE(result == ISC_R_SUCCESS); - } - REQUIRE(isc_buffer_availablelength(b) >= 2); - - ISC__BUFFER_PUTUINT16(b, val); -} - -void -isc__buffer_putuint24(isc_buffer_t *b, uint32_t val) { - isc_result_t result; - REQUIRE(ISC_BUFFER_VALID(b)); - if (b->autore) { - result = isc_buffer_reserve(&b, 3); - REQUIRE(result == ISC_R_SUCCESS); - } - REQUIRE(isc_buffer_availablelength(b) >= 3); - - ISC__BUFFER_PUTUINT24(b, val); -} - uint32_t isc_buffer_getuint32(isc_buffer_t *b) { unsigned char *cp; @@ -373,19 +145,6 @@ isc_buffer_getuint32(isc_buffer_t *b) { return (result); } -void -isc__buffer_putuint32(isc_buffer_t *b, uint32_t val) { - isc_result_t result; - REQUIRE(ISC_BUFFER_VALID(b)); - if (b->autore) { - result = isc_buffer_reserve(&b, 4); - REQUIRE(result == ISC_R_SUCCESS); - } - REQUIRE(isc_buffer_availablelength(b) >= 4); - - ISC__BUFFER_PUTUINT32(b, val); -} - uint64_t isc_buffer_getuint48(isc_buffer_t *b) { unsigned char *cp; @@ -411,63 +170,6 @@ isc_buffer_getuint48(isc_buffer_t *b) { return (result); } -void -isc__buffer_putuint48(isc_buffer_t *b, uint64_t val) { - isc_result_t result; - uint16_t valhi; - uint32_t vallo; - - REQUIRE(ISC_BUFFER_VALID(b)); - if (b->autore) { - result = isc_buffer_reserve(&b, 6); - REQUIRE(result == ISC_R_SUCCESS); - } - REQUIRE(isc_buffer_availablelength(b) >= 6); - - valhi = (uint16_t)(val >> 32); - vallo = (uint32_t)(val & 0xFFFFFFFF); - ISC__BUFFER_PUTUINT16(b, valhi); - ISC__BUFFER_PUTUINT32(b, vallo); -} - -void -isc__buffer_putmem(isc_buffer_t *b, const unsigned char *base, - unsigned int length) { - isc_result_t result; - REQUIRE(ISC_BUFFER_VALID(b)); - if (b->autore) { - result = isc_buffer_reserve(&b, length); - REQUIRE(result == ISC_R_SUCCESS); - } - REQUIRE(isc_buffer_availablelength(b) >= length); - - ISC__BUFFER_PUTMEM(b, base, length); -} - -void -isc__buffer_putstr(isc_buffer_t *b, const char *source) { - unsigned int l; - unsigned char *cp; - isc_result_t result; - - REQUIRE(ISC_BUFFER_VALID(b)); - REQUIRE(source != NULL); - - /* - * Do not use ISC__BUFFER_PUTSTR(), so strlen is only done once. - */ - l = strlen(source); - if (b->autore) { - result = isc_buffer_reserve(&b, l); - REQUIRE(result == ISC_R_SUCCESS); - } - REQUIRE(isc_buffer_availablelength(b) >= l); - - cp = isc_buffer_used(b); - memmove(cp, source, l); - b->used += l; -} - void isc_buffer_putdecint(isc_buffer_t *b, int64_t v) { unsigned int l = 0; diff --git a/lib/isc/include/isc/buffer.h b/lib/isc/include/isc/buffer.h index e7ac340df9..1be0081e4c 100644 --- a/lib/isc/include/isc/buffer.h +++ b/lib/isc/include/isc/buffer.h @@ -106,15 +106,12 @@ #include #include #include +#include #include +#include +#include #include -/*! - * To make many functions be inline macros (via \#define) define this. - * If it is undefined, a function will be used. - */ -/* #define ISC_BUFFER_USEINLINE */ - ISC_LANG_BEGINDECLS /*@{*/ @@ -245,24 +242,8 @@ isc_buffer_free(isc_buffer_t **dynbuffer); * isc_buffer_allocate(). */ -void -isc__buffer_init(isc_buffer_t *b, void *base, unsigned int length); -/*!< - * \brief Make 'b' refer to the 'length'-byte region starting at base. - * - * Requires: - * - *\li 'length' > 0 - * - *\li 'base' is a pointer to a sequence of 'length' bytes. - * - */ - void isc__buffer_initnull(isc_buffer_t *b); -/*!< - *\brief Initialize a buffer 'b' with a null data and zero length/ - */ void isc_buffer_reinit(isc_buffer_t *b, void *base, unsigned int length); @@ -278,19 +259,6 @@ isc_buffer_reinit(isc_buffer_t *b, void *base, unsigned int length); * */ -void -isc__buffer_invalidate(isc_buffer_t *b); -/*!< - * \brief Make 'b' an invalid buffer. - * - * Requires: - *\li 'b' is a valid buffer. - * - * Ensures: - *\li If assertion checking is enabled, future attempts to use 'b' without - * calling isc_buffer_init() on it will cause an assertion failure. - */ - void isc_buffer_setautorealloc(isc_buffer_t *b, bool enable); /*!< @@ -301,172 +269,6 @@ isc_buffer_setautorealloc(isc_buffer_t *b, bool enable); * */ -void -isc__buffer_region(isc_buffer_t *b, isc_region_t *r); -/*!< - * \brief Make 'r' refer to the region of 'b'. - * - * Requires: - * - *\li 'b' is a valid buffer. - * - *\li 'r' points to a region structure. - */ - -void -isc__buffer_usedregion(const isc_buffer_t *b, isc_region_t *r); -/*!< - * \brief Make 'r' refer to the used region of 'b'. - * - * Requires: - * - *\li 'b' is a valid buffer. - * - *\li 'r' points to a region structure. - */ - -void -isc__buffer_availableregion(isc_buffer_t *b, isc_region_t *r); -/*!< - * \brief Make 'r' refer to the available region of 'b'. - * - * Requires: - * - *\li 'b' is a valid buffer. - * - *\li 'r' points to a region structure. - */ - -void -isc__buffer_add(isc_buffer_t *b, unsigned int n); -/*!< - * \brief Increase the 'used' region of 'b' by 'n' bytes. - * - * Requires: - * - *\li 'b' is a valid buffer - * - *\li used + n <= length - * - */ - -void -isc__buffer_subtract(isc_buffer_t *b, unsigned int n); -/*!< - * \brief Decrease the 'used' region of 'b' by 'n' bytes. - * - * Requires: - * - *\li 'b' is a valid buffer - * - *\li used >= n - * - */ - -void -isc__buffer_clear(isc_buffer_t *b); -/*!< - * \brief Make the used region empty. - * - * Requires: - * - *\li 'b' is a valid buffer - * - * Ensures: - * - *\li used = 0 - * - */ - -void -isc__buffer_consumedregion(isc_buffer_t *b, isc_region_t *r); -/*!< - * \brief Make 'r' refer to the consumed region of 'b'. - * - * Requires: - * - *\li 'b' is a valid buffer. - * - *\li 'r' points to a region structure. - */ - -void -isc__buffer_remainingregion(isc_buffer_t *b, isc_region_t *r); -/*!< - * \brief Make 'r' refer to the remaining region of 'b'. - * - * Requires: - * - *\li 'b' is a valid buffer. - * - *\li 'r' points to a region structure. - */ - -void -isc__buffer_activeregion(isc_buffer_t *b, isc_region_t *r); -/*!< - * \brief Make 'r' refer to the active region of 'b'. - * - * Requires: - * - *\li 'b' is a valid buffer. - * - *\li 'r' points to a region structure. - */ - -void -isc__buffer_setactive(isc_buffer_t *b, unsigned int n); -/*!< - * \brief Sets the end of the active region 'n' bytes after current. - * - * Requires: - * - *\li 'b' is a valid buffer. - * - *\li current + n <= used - */ - -void -isc__buffer_first(isc_buffer_t *b); -/*!< - * \brief Make the consumed region empty. - * - * Requires: - * - *\li 'b' is a valid buffer - * - * Ensures: - * - *\li current == 0 - * - */ - -void -isc__buffer_forward(isc_buffer_t *b, unsigned int n); -/*!< - * \brief Increase the 'consumed' region of 'b' by 'n' bytes. - * - * Requires: - * - *\li 'b' is a valid buffer - * - *\li current + n <= used - * - */ - -void -isc__buffer_back(isc_buffer_t *b, unsigned int n); -/*!< - * \brief Decrease the 'consumed' region of 'b' by 'n' bytes. - * - * Requires: - * - *\li 'b' is a valid buffer - * - *\li n <= current - * - */ - void isc_buffer_compact(isc_buffer_t *b); /*!< @@ -507,21 +309,6 @@ isc_buffer_getuint8(isc_buffer_t *b); *\li A 8-bit unsigned integer. */ -void -isc__buffer_putuint8(isc_buffer_t *b, uint8_t val); -/*!< - * \brief Store an unsigned 8-bit integer from 'val' into 'b'. - * - * Requires: - *\li 'b' is a valid buffer. - * - *\li The length of the available region of 'b' is at least 1 - * or the buffer has autoreallocation enabled. - * - * Ensures: - *\li The used pointer in 'b' is advanced by 1. - */ - uint16_t isc_buffer_getuint16(isc_buffer_t *b); /*!< @@ -543,22 +330,6 @@ isc_buffer_getuint16(isc_buffer_t *b); *\li A 16-bit unsigned integer. */ -void -isc__buffer_putuint16(isc_buffer_t *b, uint16_t val); -/*!< - * \brief Store an unsigned 16-bit integer in host byte order from 'val' - * into 'b' in network byte order. - * - * Requires: - *\li 'b' is a valid buffer. - * - *\li The length of the available region of 'b' is at least 2 - * or the buffer has autoreallocation enabled. - * - * Ensures: - *\li The used pointer in 'b' is advanced by 2. - */ - uint32_t isc_buffer_getuint32(isc_buffer_t *b); /*!< @@ -580,22 +351,6 @@ isc_buffer_getuint32(isc_buffer_t *b); *\li A 32-bit unsigned integer. */ -void -isc__buffer_putuint32(isc_buffer_t *b, uint32_t val); -/*!< - * \brief Store an unsigned 32-bit integer in host byte order from 'val' - * into 'b' in network byte order. - * - * Requires: - *\li 'b' is a valid buffer. - * - *\li The length of the available region of 'b' is at least 4 - * or the buffer has autoreallocation enabled. - * - * Ensures: - *\li The used pointer in 'b' is advanced by 4. - */ - uint64_t isc_buffer_getuint48(isc_buffer_t *b); /*!< @@ -617,73 +372,6 @@ isc_buffer_getuint48(isc_buffer_t *b); *\li A 48-bit unsigned integer (stored in a 64-bit integer). */ -void -isc__buffer_putuint48(isc_buffer_t *b, uint64_t val); -/*!< - * \brief Store an unsigned 48-bit integer in host byte order from 'val' - * into 'b' in network byte order. - * - * Requires: - *\li 'b' is a valid buffer. - * - *\li The length of the available region of 'b' is at least 6 - * or the buffer has autoreallocation enabled. - * - * Ensures: - *\li The used pointer in 'b' is advanced by 6. - */ - -void -isc__buffer_putuint24(isc_buffer_t *b, uint32_t val); -/*!< - * Store an unsigned 24-bit integer in host byte order from 'val' - * into 'b' in network byte order. - * - * Requires: - *\li 'b' is a valid buffer. - * - *\li The length of the available region of 'b' is at least 3 - * or the buffer has autoreallocation enabled. - * - * Ensures: - *\li The used pointer in 'b' is advanced by 3. - */ - -void -isc__buffer_putmem(isc_buffer_t *b, const unsigned char *base, - unsigned int length); -/*!< - * \brief Copy 'length' bytes of memory at 'base' into 'b'. - * - * Requires: - *\li 'b' is a valid buffer. - * - *\li 'base' points to 'length' bytes of valid memory. - * - *\li The length of the available region of 'b' is at least 'length' - * or the buffer has autoreallocation enabled. - * - * Ensures: - *\li The used pointer in 'b' is advanced by 'length'. - */ - -void -isc__buffer_putstr(isc_buffer_t *b, const char *source); -/*!< - * \brief Copy 'source' into 'b', not including terminating NUL. - * - * Requires: - *\li 'b' is a valid buffer. - * - *\li 'source' is a valid NULL terminated string. - * - *\li The length of the available region of 'b' is at least strlen('source') - * or the buffer has autoreallocation enabled. - * - * Ensures: - *\li The used pointer in 'b' is advanced by strlen('source'). - */ - void isc_buffer_putdecint(isc_buffer_t *b, int64_t v); /*!< @@ -765,24 +453,19 @@ isc_buffer_printf(isc_buffer_t *b, const char *format, ...) *\li #ISC_R_FAILURE Other error occurred. */ -ISC_LANG_ENDDECLS - /* - * Inline macro versions of the functions. These should never be called - * directly by an application, but will be used by the functions within - * buffer.c. The callers should always use "isc_buffer_*()" names, never - * ones beginning with "isc__" + * Buffer functions implemented as inline. */ /*! \note * XXXDCL Something more could be done with initializing buffers that * point to const data. For example, isc_buffer_constinit() could * set a new boolean flag in the buffer structure indicating whether - * the buffer was initialized with that function. * Then if the + * the buffer was initialized with that function. Then if the * boolean were true, the isc_buffer_put* functions could assert a * contractual requirement for a non-const buffer. * - * One drawback is that the isc_buffer_* functions (macros) that return + * One drawback is that the isc_buffer_* functions that return * pointers would still need to return non-const pointers to avoid compiler * warnings, so it would be up to code that uses them to have to deal * with the possibility that the buffer was initialized as const -- @@ -791,262 +474,45 @@ ISC_LANG_ENDDECLS * true/false, they could at least assert a contractual requirement for * non-const buffers when needed. */ -#define ISC__BUFFER_INIT(_b, _base, _length) \ - do { \ - (_b)->base = _base; \ - (_b)->length = (_length); \ - (_b)->used = 0; \ - (_b)->current = 0; \ - (_b)->active = 0; \ - (_b)->mctx = NULL; \ - ISC_LINK_INIT(_b, link); \ - (_b)->magic = ISC_BUFFER_MAGIC; \ - (_b)->autore = false; \ - } while (0) -#define ISC__BUFFER_INITNULL(_b) ISC__BUFFER_INIT(_b, NULL, 0) +/*! + * \brief Make 'b' refer to the 'length'-byte region starting at 'base'. + * + * Requires: + * + *\li 'length' > 0 + * + *\li 'base' is a pointer to a sequence of 'length' bytes. + */ +static inline void +isc_buffer_init(isc_buffer_t *b, void *base, unsigned int length) { + ISC_REQUIRE(b != NULL); -#define ISC__BUFFER_INVALIDATE(_b) \ - do { \ - (_b)->magic = 0; \ - (_b)->base = NULL; \ - (_b)->length = 0; \ - (_b)->used = 0; \ - (_b)->current = 0; \ - (_b)->active = 0; \ - } while (0) + *b = (isc_buffer_t){ .base = base, + .length = length, + .magic = ISC_BUFFER_MAGIC }; + ISC_LINK_INIT(b, link); +} -#define ISC__BUFFER_REGION(_b, _r) \ - do { \ - (_r)->base = (_b)->base; \ - (_r)->length = (_b)->length; \ - } while (0) - -#define ISC__BUFFER_USEDREGION(_b, _r) \ - do { \ - (_r)->base = (_b)->base; \ - (_r)->length = (_b)->used; \ - } while (0) - -#define ISC__BUFFER_AVAILABLEREGION(_b, _r) \ - do { \ - (_r)->base = isc_buffer_used(_b); \ - (_r)->length = isc_buffer_availablelength(_b); \ - } while (0) - -#define ISC__BUFFER_ADD(_b, _n) \ - do { \ - (_b)->used += (_n); \ - } while (0) - -#define ISC__BUFFER_SUBTRACT(_b, _n) \ - do { \ - (_b)->used -= (_n); \ - if ((_b)->current > (_b)->used) \ - (_b)->current = (_b)->used; \ - if ((_b)->active > (_b)->used) \ - (_b)->active = (_b)->used; \ - } while (0) - -#define ISC__BUFFER_CLEAR(_b) \ - do { \ - (_b)->used = 0; \ - (_b)->current = 0; \ - (_b)->active = 0; \ - } while (0) - -#define ISC__BUFFER_CONSUMEDREGION(_b, _r) \ - do { \ - (_r)->base = (_b)->base; \ - (_r)->length = (_b)->current; \ - } while (0) - -#define ISC__BUFFER_REMAININGREGION(_b, _r) \ - do { \ - (_r)->base = isc_buffer_current(_b); \ - (_r)->length = isc_buffer_remaininglength(_b); \ - } while (0) - -#define ISC__BUFFER_ACTIVEREGION(_b, _r) \ - do { \ - if ((_b)->current < (_b)->active) { \ - (_r)->base = isc_buffer_current(_b); \ - (_r)->length = isc_buffer_activelength(_b); \ - } else { \ - (_r)->base = NULL; \ - (_r)->length = 0; \ - } \ - } while (0) - -#define ISC__BUFFER_SETACTIVE(_b, _n) \ - do { \ - (_b)->active = (_b)->current + (_n); \ - } while (0) - -#define ISC__BUFFER_FIRST(_b) \ - do { \ - (_b)->current = 0; \ - } while (0) - -#define ISC__BUFFER_FORWARD(_b, _n) \ - do { \ - (_b)->current += (_n); \ - } while (0) - -#define ISC__BUFFER_BACK(_b, _n) \ - do { \ - (_b)->current -= (_n); \ - } while (0) - -#define ISC__BUFFER_PUTMEM(_b, _base, _length) \ - do { \ - if ((_b)->autore) { \ - isc_buffer_t *_tmp = _b; \ - ISC_REQUIRE(isc_buffer_reserve(&_tmp, _length) == \ - ISC_R_SUCCESS); \ - } \ - ISC_REQUIRE(isc_buffer_availablelength(_b) >= \ - (unsigned int)_length); \ - if (_length > 0U) { \ - memmove(isc_buffer_used(_b), (_base), (_length)); \ - (_b)->used += (_length); \ - } \ - } while (0) - -#define ISC__BUFFER_PUTSTR(_b, _source) \ - do { \ - unsigned int _length; \ - unsigned char *_cp; \ - _length = (unsigned int)strlen(_source); \ - if ((_b)->autore) { \ - isc_buffer_t *_tmp = _b; \ - ISC_REQUIRE(isc_buffer_reserve(&_tmp, _length) == \ - ISC_R_SUCCESS); \ - } \ - ISC_REQUIRE(isc_buffer_availablelength(_b) >= _length); \ - _cp = isc_buffer_used(_b); \ - memmove(_cp, (_source), _length); \ - (_b)->used += (_length); \ - } while (0) - -#define ISC__BUFFER_PUTUINT8(_b, _val) \ - do { \ - unsigned char *_cp; \ - /* evaluate (_val) only once */ \ - uint8_t _val2 = (_val); \ - if ((_b)->autore) { \ - isc_buffer_t *_tmp = _b; \ - ISC_REQUIRE(isc_buffer_reserve(&_tmp, 1) == \ - ISC_R_SUCCESS); \ - } \ - ISC_REQUIRE(isc_buffer_availablelength(_b) >= 1U); \ - _cp = isc_buffer_used(_b); \ - (_b)->used++; \ - _cp[0] = _val2; \ - } while (0) - -#define ISC__BUFFER_PUTUINT16(_b, _val) \ - do { \ - unsigned char *_cp; \ - /* evaluate (_val) only once */ \ - uint16_t _val2 = (_val); \ - if ((_b)->autore) { \ - isc_buffer_t *_tmp = _b; \ - ISC_REQUIRE(isc_buffer_reserve(&_tmp, 2) == \ - ISC_R_SUCCESS); \ - } \ - ISC_REQUIRE(isc_buffer_availablelength(_b) >= 2U); \ - _cp = isc_buffer_used(_b); \ - (_b)->used += 2; \ - _cp[0] = (unsigned char)(_val2 >> 8); \ - _cp[1] = (unsigned char)_val2; \ - } while (0) - -#define ISC__BUFFER_PUTUINT24(_b, _val) \ - do { \ - unsigned char *_cp; \ - /* evaluate (_val) only once */ \ - uint32_t _val2 = (_val); \ - if ((_b)->autore) { \ - isc_buffer_t *_tmp = _b; \ - ISC_REQUIRE(isc_buffer_reserve(&_tmp, 3) == \ - ISC_R_SUCCESS); \ - } \ - ISC_REQUIRE(isc_buffer_availablelength(_b) >= 3U); \ - _cp = isc_buffer_used(_b); \ - (_b)->used += 3; \ - _cp[0] = (unsigned char)(_val2 >> 16); \ - _cp[1] = (unsigned char)(_val2 >> 8); \ - _cp[2] = (unsigned char)_val2; \ - } while (0) - -#define ISC__BUFFER_PUTUINT32(_b, _val) \ - do { \ - unsigned char *_cp; \ - /* evaluate (_val) only once */ \ - uint32_t _val2 = (_val); \ - if ((_b)->autore) { \ - isc_buffer_t *_tmp = _b; \ - ISC_REQUIRE(isc_buffer_reserve(&_tmp, 4) == \ - ISC_R_SUCCESS); \ - } \ - ISC_REQUIRE(isc_buffer_availablelength(_b) >= 4U); \ - _cp = isc_buffer_used(_b); \ - (_b)->used += 4; \ - _cp[0] = (unsigned char)(_val2 >> 24); \ - _cp[1] = (unsigned char)(_val2 >> 16); \ - _cp[2] = (unsigned char)(_val2 >> 8); \ - _cp[3] = (unsigned char)_val2; \ - } while (0) - -#if defined(ISC_BUFFER_USEINLINE) -#define isc_buffer_init ISC__BUFFER_INIT -#define isc_buffer_initnull ISC__BUFFER_INITNULL -#define isc_buffer_invalidate ISC__BUFFER_INVALIDATE -#define isc_buffer_region ISC__BUFFER_REGION -#define isc_buffer_usedregion ISC__BUFFER_USEDREGION -#define isc_buffer_availableregion ISC__BUFFER_AVAILABLEREGION -#define isc_buffer_add ISC__BUFFER_ADD -#define isc_buffer_subtract ISC__BUFFER_SUBTRACT -#define isc_buffer_clear ISC__BUFFER_CLEAR -#define isc_buffer_consumedregion ISC__BUFFER_CONSUMEDREGION -#define isc_buffer_remainingregion ISC__BUFFER_REMAININGREGION -#define isc_buffer_activeregion ISC__BUFFER_ACTIVEREGION -#define isc_buffer_setactive ISC__BUFFER_SETACTIVE -#define isc_buffer_first ISC__BUFFER_FIRST -#define isc_buffer_forward ISC__BUFFER_FORWARD -#define isc_buffer_back ISC__BUFFER_BACK -#define isc_buffer_putmem ISC__BUFFER_PUTMEM -#define isc_buffer_putstr ISC__BUFFER_PUTSTR -#define isc_buffer_putuint8 ISC__BUFFER_PUTUINT8 -#define isc_buffer_putuint16 ISC__BUFFER_PUTUINT16 -#define isc_buffer_putuint24 ISC__BUFFER_PUTUINT24 -#define isc_buffer_putuint32 ISC__BUFFER_PUTUINT32 -#else /* if defined(ISC_BUFFER_USEINLINE) */ -#define isc_buffer_init isc__buffer_init -#define isc_buffer_initnull isc__buffer_initnull -#define isc_buffer_invalidate isc__buffer_invalidate -#define isc_buffer_region isc__buffer_region -#define isc_buffer_usedregion isc__buffer_usedregion -#define isc_buffer_availableregion isc__buffer_availableregion -#define isc_buffer_add isc__buffer_add -#define isc_buffer_subtract isc__buffer_subtract -#define isc_buffer_clear isc__buffer_clear -#define isc_buffer_consumedregion isc__buffer_consumedregion -#define isc_buffer_remainingregion isc__buffer_remainingregion -#define isc_buffer_activeregion isc__buffer_activeregion -#define isc_buffer_setactive isc__buffer_setactive -#define isc_buffer_first isc__buffer_first -#define isc_buffer_forward isc__buffer_forward -#define isc_buffer_back isc__buffer_back -#define isc_buffer_putmem isc__buffer_putmem -#define isc_buffer_putstr isc__buffer_putstr -#define isc_buffer_putuint8 isc__buffer_putuint8 -#define isc_buffer_putuint16 isc__buffer_putuint16 -#define isc_buffer_putuint24 isc__buffer_putuint24 -#define isc_buffer_putuint32 isc__buffer_putuint32 -#endif /* if defined(ISC_BUFFER_USEINLINE) */ +/*! + *\brief Initialize a buffer 'b' with a null data field and zero length. + * This can later be grown as needed and swapped in place. + */ +static inline void +isc_buffer_initnull(isc_buffer_t *b) { + *b = (isc_buffer_t){ .magic = ISC_BUFFER_MAGIC }; + ISC_LINK_INIT(b, link); +} +/*! + * \brief Make 'b' refer to the 'length'-byte constant region starting + * at 'base'. + * + * Requires: + * + *\li 'length' > 0 + *\li 'base' is a pointer to a sequence of 'length' bytes. + */ #define isc_buffer_constinit(_b, _d, _l) \ do { \ union { \ @@ -1057,7 +523,501 @@ ISC_LANG_ENDDECLS isc_buffer_init((_b), _deconst._var, (_l)); \ } while (0) -/* - * No inline method for this one (yet). +/*! + * \brief Make 'b' an invalid buffer. + * + * Requires: + *\li 'b' is a valid buffer. + * + * Ensures: + *\li Future attempts to use 'b' without calling isc_buffer_init() on + * it will cause an assertion failure. */ -#define isc_buffer_putuint48 isc__buffer_putuint48 +static inline void +isc_buffer_invalidate(isc_buffer_t *b) { + ISC_REQUIRE(ISC_BUFFER_VALID(b)); + ISC_REQUIRE(!ISC_LINK_LINKED(b, link)); + ISC_REQUIRE(b->mctx == NULL); + + b->magic = 0; + b->base = NULL; + b->length = 0; + b->used = 0; + b->current = 0; + b->active = 0; +} + +/*! + * \brief Make 'r' refer to the region of 'b'. + * + * Requires: + * + *\li 'b' is a valid buffer. + * + *\li 'r' points to a region structure. + */ +static inline void +isc_buffer_region(isc_buffer_t *b, isc_region_t *r) { + ISC_REQUIRE(ISC_BUFFER_VALID(b)); + ISC_REQUIRE(r != NULL); + + r->base = b->base; + r->length = b->length; +} + +/*! + * \brief Make 'r' refer to the used region of 'b'. + * + * Requires: + * + *\li 'b' is a valid buffer. + * + *\li 'r' points to a region structure. + */ +static inline void +isc_buffer_usedregion(const isc_buffer_t *b, isc_region_t *r) { + ISC_REQUIRE(ISC_BUFFER_VALID(b)); + ISC_REQUIRE(r != NULL); + + r->base = b->base; + r->length = b->used; +} + +/*! + * \brief Make 'r' refer to the available region of 'b'. + * + * Requires: + * + *\li 'b' is a valid buffer. + * + *\li 'r' points to a region structure. + */ +static inline void +isc_buffer_availableregion(isc_buffer_t *b, isc_region_t *r) { + ISC_REQUIRE(ISC_BUFFER_VALID(b)); + ISC_REQUIRE(r != NULL); + + r->base = isc_buffer_used(b); + r->length = isc_buffer_availablelength(b); +} + +/*! + * \brief Increase the 'used' region of 'b' by 'n' bytes. + * + * Requires: + * + *\li 'b' is a valid buffer + * + *\li used + n <= length + */ +static inline void +isc_buffer_add(isc_buffer_t *b, unsigned int n) { + ISC_REQUIRE(ISC_BUFFER_VALID(b)); + ISC_REQUIRE(b->used + n <= b->length); + + b->used += n; +} + +/*! + * \brief Decrease the 'used' region of 'b' by 'n' bytes. + * + * Requires: + * + *\li 'b' is a valid buffer + * + *\li used >= n + */ +static inline void +isc_buffer_subtract(isc_buffer_t *b, unsigned int n) { + ISC_REQUIRE(ISC_BUFFER_VALID(b)); + ISC_REQUIRE(b->used >= n); + + b->used -= n; + if (b->current > b->used) { + b->current = b->used; + } + if (b->active > b->used) { + b->active = b->used; + } +} + +/*!< + * \brief Make the used region empty. + * + * Requires: + * + *\li 'b' is a valid buffer + * + * Ensures: + * + *\li used = 0 + */ +static inline void +isc_buffer_clear(isc_buffer_t *b) { + ISC_REQUIRE(ISC_BUFFER_VALID(b)); + + b->used = 0; + b->current = 0; + b->active = 0; +} + +/*! + * \brief Make 'r' refer to the consumed region of 'b'. + * + * Requires: + * + *\li 'b' is a valid buffer. + * + *\li 'r' points to a region structure. + */ +static inline void +isc_buffer_consumedregion(isc_buffer_t *b, isc_region_t *r) { + ISC_REQUIRE(ISC_BUFFER_VALID(b)); + ISC_REQUIRE(r != NULL); + + r->base = b->base; + r->length = b->current; +} + +/*! + * \brief Make 'r' refer to the remaining region of 'b'. + * + * Requires: + * + *\li 'b' is a valid buffer. + * + *\li 'r' points to a region structure. + */ +static inline void +isc_buffer_remainingregion(isc_buffer_t *b, isc_region_t *r) { + ISC_REQUIRE(ISC_BUFFER_VALID(b)); + ISC_REQUIRE(r != NULL); + + r->base = isc_buffer_current(b); + r->length = isc_buffer_remaininglength(b); +} + +/*! + * \brief Make 'r' refer to the active region of 'b'. + * + * Requires: + * + *\li 'b' is a valid buffer. + * + *\li 'r' points to a region structure. + */ +static inline void +isc_buffer_activeregion(isc_buffer_t *b, isc_region_t *r) { + ISC_REQUIRE(ISC_BUFFER_VALID(b)); + ISC_REQUIRE(r != NULL); + + if (b->current < b->active) { + r->base = isc_buffer_current(b); + r->length = isc_buffer_activelength(b); + } else { + r->base = NULL; + r->length = 0; + } +} + +/*! + * \brief Sets the end of the active region 'n' bytes after current. + * + * Requires: + * + *\li 'b' is a valid buffer. + * + *\li current + n <= used + */ +static inline void +isc_buffer_setactive(isc_buffer_t *b, unsigned int n) { + ISC_REQUIRE(ISC_BUFFER_VALID(b)); + ISC_REQUIRE(b->current + n <= b->used); + + b->active = b->current + n; +} + +/*!< + * \brief Make the consumed region empty. + * + * Requires: + * + *\li 'b' is a valid buffer + * + * Ensures: + * + *\li current == 0 + */ +static inline void +isc_buffer_first(isc_buffer_t *b) { + ISC_REQUIRE(ISC_BUFFER_VALID(b)); + + b->current = 0; +} + +/*! + * \brief Increase the 'consumed' region of 'b' by 'n' bytes. + * + * Requires: + * + *\li 'b' is a valid buffer + * + *\li current + n <= used + */ +static inline void +isc_buffer_forward(isc_buffer_t *b, unsigned int n) { + ISC_REQUIRE(ISC_BUFFER_VALID(b)); + ISC_REQUIRE(b->current + n <= b->used); + + b->current += n; +} + +/*! + * \brief Decrease the 'consumed' region of 'b' by 'n' bytes. + * + * Requires: + * + *\li 'b' is a valid buffer + * + *\li n <= current + */ +static inline void +isc_buffer_back(isc_buffer_t *b, unsigned int n) { + ISC_REQUIRE(ISC_BUFFER_VALID(b)); + ISC_REQUIRE(n <= b->current); + + b->current -= n; +} + +/*! + * \brief Store an unsigned 8-bit integer from 'val' into 'b'. + * + * Requires: + *\li 'b' is a valid buffer. + * + *\li The length of the available region of 'b' is at least 1 + * or the buffer has autoreallocation enabled. + * + * Ensures: + *\li The used pointer in 'b' is advanced by 1. + */ +static inline void +isc_buffer_putuint8(isc_buffer_t *b, uint8_t val) { + unsigned char *cp; + + ISC_REQUIRE(ISC_BUFFER_VALID(b)); + + if (b->autore) { + isc_buffer_t *tmp = b; + ISC_REQUIRE(isc_buffer_reserve(&tmp, 1) == ISC_R_SUCCESS); + } + + ISC_REQUIRE(isc_buffer_availablelength(b) >= 1U); + + cp = isc_buffer_used(b); + b->used++; + cp[0] = val; +} + +/*! + * \brief Store an unsigned 16-bit integer in host byte order from 'val' + * into 'b' in network byte order. + * + * Requires: + *\li 'b' is a valid buffer. + * + *\li The length of the available region of 'b' is at least 2 + * or the buffer has autoreallocation enabled. + * + * Ensures: + *\li The used pointer in 'b' is advanced by 2. + */ +static inline void +isc_buffer_putuint16(isc_buffer_t *b, uint16_t val) { + unsigned char *cp; + + ISC_REQUIRE(ISC_BUFFER_VALID(b)); + + if (b->autore) { + isc_buffer_t *tmp = b; + ISC_REQUIRE(isc_buffer_reserve(&tmp, 2) == ISC_R_SUCCESS); + } + + ISC_REQUIRE(isc_buffer_availablelength(b) >= 2U); + + cp = isc_buffer_used(b); + b->used += 2; + cp[0] = (unsigned char)(val >> 8); + cp[1] = (unsigned char)val; +} + +/*! + * Store an unsigned 24-bit integer in host byte order from 'val' + * into 'b' in network byte order. + * + * Requires: + *\li 'b' is a valid buffer. + * + *\li The length of the available region of 'b' is at least 3 + * or the buffer has autoreallocation enabled. + * + * Ensures: + *\li The used pointer in 'b' is advanced by 3. + */ +static inline void +isc_buffer_putuint24(isc_buffer_t *b, uint32_t val) { + unsigned char *cp; + + ISC_REQUIRE(ISC_BUFFER_VALID(b)); + + if (b->autore) { + isc_buffer_t *tmp = b; + ISC_REQUIRE(isc_buffer_reserve(&tmp, 3) == ISC_R_SUCCESS); + } + + ISC_REQUIRE(isc_buffer_availablelength(b) >= 3U); + + cp = isc_buffer_used(b); + b->used += 3; + cp[0] = (unsigned char)(val >> 16); + cp[1] = (unsigned char)(val >> 8); + cp[2] = (unsigned char)val; +} + +/*! + * \brief Store an unsigned 32-bit integer in host byte order from 'val' + * into 'b' in network byte order. + * + * Requires: + *\li 'b' is a valid buffer. + * + *\li The length of the available region of 'b' is at least 4 + * or the buffer has autoreallocation enabled. + * + * Ensures: + *\li The used pointer in 'b' is advanced by 4. + */ +static inline void +isc_buffer_putuint32(isc_buffer_t *b, uint32_t val) { + unsigned char *cp; + + ISC_REQUIRE(ISC_BUFFER_VALID(b)); + + if (b->autore) { + isc_buffer_t *tmp = b; + ISC_REQUIRE(isc_buffer_reserve(&tmp, 4) == ISC_R_SUCCESS); + } + + ISC_REQUIRE(isc_buffer_availablelength(b) >= 4U); + + cp = isc_buffer_used(b); + b->used += 4; + cp[0] = (unsigned char)(val >> 24); + cp[1] = (unsigned char)(val >> 16); + cp[2] = (unsigned char)(val >> 8); + cp[3] = (unsigned char)val; +} + +/*! + * \brief Store an unsigned 48-bit integer in host byte order from 'val' + * into 'b' in network byte order. + * + * Requires: + *\li 'b' is a valid buffer. + * + *\li The length of the available region of 'b' is at least 6 + * or the buffer has autoreallocation enabled. + * + * Ensures: + *\li The used pointer in 'b' is advanced by 6. + */ +static inline void +isc_buffer_putuint48(isc_buffer_t *b, uint64_t val) { + unsigned char *cp = NULL; + + ISC_REQUIRE(ISC_BUFFER_VALID(b)); + + if (b->autore) { + isc_buffer_t *tmp = b; + ISC_REQUIRE(isc_buffer_reserve(&tmp, 6) == ISC_R_SUCCESS); + } + + ISC_REQUIRE(isc_buffer_availablelength(b) >= 6U); + + cp = isc_buffer_used(b); + b->used += 6; + cp[0] = (unsigned char)(val >> 40); + cp[1] = (unsigned char)(val >> 32); + cp[2] = (unsigned char)(val >> 24); + cp[3] = (unsigned char)(val >> 16); + cp[4] = (unsigned char)(val >> 8); + cp[5] = (unsigned char)val; +} + +/*! + * \brief Copy 'length' bytes of memory at 'base' into 'b'. + * + * Requires: + *\li 'b' is a valid buffer. + * + *\li 'base' points to 'length' bytes of valid memory. + * + *\li The length of the available region of 'b' is at least 'length' + * or the buffer has autoreallocation enabled. + * + * Ensures: + *\li The used pointer in 'b' is advanced by 'length'. + */ +static inline void +isc_buffer_putmem(isc_buffer_t *b, const unsigned char *base, + unsigned int length) { + ISC_REQUIRE(ISC_BUFFER_VALID(b)); + + if (b->autore) { + isc_buffer_t *tmp = b; + ISC_REQUIRE(isc_buffer_reserve(&tmp, length) == ISC_R_SUCCESS); + } + + ISC_REQUIRE(isc_buffer_availablelength(b) >= (unsigned int)length); + + if (length > 0U) { + memmove(isc_buffer_used(b), base, length); + b->used += length; + } +} + +/*! + * \brief Copy 'source' into 'b', not including terminating NUL. + * + * Requires: + *\li 'b' is a valid buffer. + * + *\li 'source' is a valid NULL terminated string. + * + *\li The length of the available region of 'b' is at least strlen('source') + * or the buffer has autoreallocation enabled. + * + * Ensures: + *\li The used pointer in 'b' is advanced by strlen('source'). + */ +static inline void +isc_buffer_putstr(isc_buffer_t *b, const char *source) { + unsigned int length; + unsigned char *cp; + + ISC_REQUIRE(ISC_BUFFER_VALID(b)); + ISC_REQUIRE(source != NULL); + + length = (unsigned int)strlen(source); + if (b->autore) { + isc_buffer_t *tmp = b; + ISC_REQUIRE(isc_buffer_reserve(&tmp, length) == ISC_R_SUCCESS); + } + + ISC_REQUIRE(isc_buffer_availablelength(b) >= length); + + cp = isc_buffer_used(b); + memmove(cp, source, length); + b->used += length; +} +ISC_LANG_ENDDECLS