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