diff --git a/lib/dns/keymgr.c b/lib/dns/keymgr.c index 935d989c4d..79ac71f835 100644 --- a/lib/dns/keymgr.c +++ b/lib/dns/keymgr.c @@ -319,7 +319,7 @@ keymgr_prepublication_time(dns_dnsseckey_t *key, dns_kasp_t *kasp, return 0; } - if (ISC_OVERFLOW_ADD(active, klifetime, &retire)) { + if (ckd_add(&retire, active, klifetime)) { log_key_overflow(key->key, "retire"); retire = UINT32_MAX; } @@ -442,7 +442,7 @@ keymgr_key_update_lifetime(dns_dnsseckey_t *key, dns_kasp_t *kasp, uint32_t a = now; uint32_t inactive; (void)dst_key_gettime(key->key, DST_TIME_ACTIVATE, &a); - if (ISC_OVERFLOW_ADD(a, lifetime, &inactive)) { + if (ckd_add(&inactive, a, lifetime)) { log_key_overflow(key->key, "inactive"); inactive = UINT32_MAX; } @@ -1986,7 +1986,7 @@ keymgr_key_rollover(dns_kasp_key_t *kaspkey, dns_dnsseckey_t *active_key, if (lifetime > 0) { uint32_t inactive; - if (ISC_OVERFLOW_ADD(active, lifetime, &inactive)) { + if (ckd_add(&inactive, active, lifetime)) { log_key_overflow(new_key->key, "inactive"); inactive = UINT32_MAX; } diff --git a/lib/dns/qp.c b/lib/dns/qp.c index 3f10bd04a4..aa717c1301 100644 --- a/lib/dns/qp.c +++ b/lib/dns/qp.c @@ -495,10 +495,10 @@ static dns_qpcell_t next_capacity(uint32_t prev_capacity, uint32_t size) { /* * Request size was floored at 2 because builtin_clz used to be 0. - * We keep this behavior because ISC_LEADING_ZEROS(0) = 32. + * We keep this behavior because stdc_leading_zeros(0) = 32. */ size = ISC_MAX3(size, prev_capacity, 2U); - uint32_t log2 = 32U - ISC_LEADING_ZEROS(size - 1U); + uint32_t log2 = 32U - stdc_leading_zeros(size - 1U); return 1U << ISC_CLAMP(log2, QP_CHUNK_LOG_MIN, QP_CHUNK_LOG_MAX); } diff --git a/lib/dns/qp_p.h b/lib/dns/qp_p.h index a5dce44d84..ef9f1e3362 100644 --- a/lib/dns/qp_p.h +++ b/lib/dns/qp_p.h @@ -753,7 +753,7 @@ static inline dns_qpweight_t branch_count_bitmap_before(dns_qpnode_t *n, dns_qpshift_t bit) { uint64_t mask = (1ULL << bit) - 1 - TAG_MASK; uint64_t bitmap = branch_index(n) & mask; - return (dns_qpweight_t)ISC_POPCOUNT(bitmap); + return (dns_qpweight_t)stdc_count_zeros(bitmap); } /* diff --git a/lib/dns/rdataslab.c b/lib/dns/rdataslab.c index 2297418665..6991fe9187 100644 --- a/lib/dns/rdataslab.c +++ b/lib/dns/rdataslab.c @@ -173,7 +173,7 @@ makeslab(dns_rdataset_t *rdataset, isc_mem_t *mctx, isc_region_t *region, */ nalloc = nitems; - RUNTIME_CHECK(!ISC_OVERFLOW_MUL(nalloc, sizeof(rdata[0]), &rdatasize)); + RUNTIME_CHECK(!ckd_mul(&rdatasize, nalloc, sizeof(rdata[0]))); rdata = isc_mem_get(mctx, rdatasize); /* diff --git a/lib/dns/rpz.c b/lib/dns/rpz.c index a2f3452868..a59cad006a 100644 --- a/lib/dns/rpz.c +++ b/lib/dns/rpz.c @@ -1095,7 +1095,7 @@ diff_keys(const dns_rpz_cidr_key_t *key1, dns_rpz_prefix_t prefix1, for (i = 0; bit < maxbit; i++, bit += DNS_RPZ_CIDR_WORD_BITS) { delta = key1->w[i] ^ key2->w[i]; if (delta != 0) { - bit += ISC_LEADING_ZEROS(delta); + bit += stdc_leading_zeros(delta); break; } } diff --git a/lib/isc/histo.c b/lib/isc/histo.c index 25febb55c9..aac7081db6 100644 --- a/lib/isc/histo.c +++ b/lib/isc/histo.c @@ -181,7 +181,7 @@ static inline uint value_to_key(const isc_histo_t *hg, uint64_t value) { /* ensure that denormal numbers are all in chunk zero */ uint64_t chunked = value | CHUNKSIZE(hg); - int clz = ISC_LEADING_ZEROS(chunked); + int clz = stdc_leading_zeros(chunked); /* actually 1 less than the exponent except for denormals */ uint exponent = 63 - hg->sigbits - clz; /* mantissa has leading bit set except for denormals */ diff --git a/lib/isc/include/isc/bit.h b/lib/isc/include/isc/bit.h index 0a39c29eaf..637a68a205 100644 --- a/lib/isc/include/isc/bit.h +++ b/lib/isc/include/isc/bit.h @@ -19,26 +19,16 @@ #include #include -#ifndef __has_header -#define __has_header(x) 0 -#endif - #if __has_header() #include -#define ISC_POPCOUNT(x) stdc_count_zeros(x) -#define ISC_LEADING_ZEROS(x) stdc_leading_zeros(x) -#define ISC_TRAILING_ZEROS(x) stdc_trailing_zeros(x) -#define ISC_LEADING_ONES(x) stdc_leading_ones(x) -#define ISC_TRAILING_ONES(x) stdc_trailing_ones(x) - #else /* __has_header() */ #ifdef HAVE_BUILTIN_POPCOUNTG -#define ISC_POPCOUNT(x) __builtin_popcountg(x) +#define stdc_count_zeros(x) __builtin_popcountg(x) #else /* HAVE_BUILTIN_POPCOUNTG */ -#define ISC_POPCOUNT(x) \ +#define stdc_count_zeros(x) \ _Generic((x), \ unsigned int: __builtin_popcount, \ unsigned long: __builtin_popcountl, \ @@ -46,9 +36,9 @@ #endif /* HAVE_BUILTIN_POPCOUNTG */ #ifdef HAVE_BUILTIN_CLZG -#define ISC_LEADING_ZEROS(x) __builtin_clzg(x, (int)(sizeof(x) * 8)) +#define stdc_leading_zeros(x) __builtin_clzg(x, (int)(sizeof(x) * 8)) #else /* HAVE_BUILTIN_CLZG */ -#define ISC_LEADING_ZEROS(x) \ +#define stdc_leading_zeros(x) \ (((x) == 0) ? (sizeof(x) * 8) \ : _Generic((x), \ unsigned int: __builtin_clz, \ @@ -57,9 +47,9 @@ #endif /* HAVE_BUILTIN_CLZG */ #ifdef HAVE_BUILTIN_CTZG -#define ISC_TRAILING_ZEROS(x) __builtin_ctzg(x, (int)sizeof(x) * 8) +#define stdc_trailing_zeros(x) __builtin_ctzg(x, (int)sizeof(x) * 8) #else /* HAVE_BUILTIN_CTZG */ -#define ISC_TRAILING_ZEROS(x) \ +#define stdc_trailing_zeros(x) \ (((x) == 0) ? (sizeof(x) * 8) \ : _Generic((x), \ unsigned int: __builtin_ctz, \ @@ -67,8 +57,8 @@ unsigned long long: __builtin_ctzll)(x)) #endif /* HAVE_BUILTIN_CTZG */ -#define ISC_LEADING_ONES(x) ISC_LEADING_ZEROS(~(x)) -#define ISC_TRAILING_ONES(x) ISC_TRAILING_ZEROS(~(x)) +#define stdc_leading_ones(x) stdc_leading_zeros(~(x)) +#define stdc_trailing_ones(x) stdc_trailing_zeros(~(x)) #endif /* __has_header() */ diff --git a/lib/isc/include/isc/overflow.h b/lib/isc/include/isc/overflow.h index 62727513ad..38aa8fee9f 100644 --- a/lib/isc/include/isc/overflow.h +++ b/lib/isc/include/isc/overflow.h @@ -17,81 +17,45 @@ #include -/* - * It is awkward to support signed numbers as well, so keep it simple - * (with a safety check). - */ -#define ISC_OVERFLOW_IS_UNSIGNED(a) \ - ({ \ - STATIC_ASSERT((typeof(a))-1 > 0, \ - "overflow checks require unsigned types"); \ - (a); \ +#if HAVE_STDCKDINT_H +#include + +#else /* HAVE_STDCKDINT_H */ + +#define ckd_mul(cp, a, b) __builtin_mul_overflow(a, b, cp) +#define ckd_add(cp, a, b) __builtin_add_overflow(a, b, cp) +#define ckd_sub(cp, a, b) __builtin_sub_overflow(a, b, cp) + +#endif /* HAVE_STDCKDINT_H */ + +#define ISC_CHECKED_MUL(a, b) \ + ({ \ + typeof(a) _c; \ + bool _overflow = ckd_mul(&_c, a, b); \ + INSIST(!_overflow); \ + _c; \ }) -#define ISC_OVERFLOW_UINT_MAX(a) ISC_OVERFLOW_IS_UNSIGNED((typeof(a))-1) - -#define ISC_OVERFLOW_UINT_MIN(a) ISC_OVERFLOW_IS_UNSIGNED(0) - -/* - * Return true on overflow, e.g. - * - * bool overflow = ISC_OVERFLOW_MUL(count, sizeof(array[0]), &bytes); - * INSIST(!overflow); - */ - -#if HAVE_BUILTIN_MUL_OVERFLOW -#define ISC_OVERFLOW_MUL(a, b, cp) __builtin_mul_overflow(a, b, cp) -#else -#define ISC_OVERFLOW_MUL(a, b, cp) \ - ((ISC_OVERFLOW_UINT_MAX(a) / (b) > (a)) ? (*(cp) = (a) * (b), false) \ - : true) -#endif - -#if HAVE_BUILTIN_ADD_OVERFLOW -#define ISC_OVERFLOW_ADD(a, b, cp) __builtin_add_overflow(a, b, cp) -#else -#define ISC_OVERFLOW_ADD(a, b, cp) \ - ((ISC_OVERFLOW_UINT_MAX(a) - (b) > (a)) ? (*(cp) = (a) + (b), false) \ - : true) -#endif - -#if HAVE_BUILTIN_SUB_OVERFLOW -#define ISC_OVERFLOW_SUB(a, b, cp) __builtin_sub_overflow(a, b, cp) -#else -#define ISC_OVERFLOW_SUB(a, b, cp) \ - ((ISC_OVERFLOW_UINT_MIN(a) + (b) < (a)) ? (*(cp) = (a) - (b), false) \ - : true) -#endif - -#define ISC_CHECKED_MUL(a, b) \ - ({ \ - typeof(a) _c; \ - bool _overflow = ISC_OVERFLOW_MUL(a, b, &_c); \ - INSIST(!_overflow); \ - _c; \ +#define ISC_CHECKED_ADD(a, b) \ + ({ \ + typeof(a) _c; \ + bool _overflow = ckd_add(&_c, a, b); \ + INSIST(!_overflow); \ + _c; \ }) -#define ISC_CHECKED_ADD(a, b) \ - ({ \ - typeof(a) _c; \ - bool _overflow = ISC_OVERFLOW_ADD(a, b, &_c); \ - INSIST(!_overflow); \ - _c; \ +#define ISC_CHECKED_SUB(a, b) \ + ({ \ + typeof(a) _c; \ + bool _overflow = ckd_sub(&_c, a, b); \ + INSIST(!_overflow); \ + _c; \ }) -#define ISC_CHECKED_SUB(a, b) \ - ({ \ - typeof(a) _c; \ - bool _overflow = ISC_OVERFLOW_SUB(a, b, cp); \ - INSIST(!_overflow); \ - _c; \ - }) - -#define ISC_CHECKED_MUL_ADD(a, b, c) \ - ({ \ - size_t _d; \ - bool _overflow = ISC_OVERFLOW_MUL(a, b, &_d) || \ - ISC_OVERFLOW_ADD(_d, c, &_d); \ - INSIST(!_overflow); \ - _d; \ +#define ISC_CHECKED_MUL_ADD(a, b, c) \ + ({ \ + size_t _d; \ + bool _overflow = ckd_mul(&_d, a, b) || ckd_add(&_d, _d, c); \ + INSIST(!_overflow); \ + _d; \ }) diff --git a/lib/isc/include/isc/util.h b/lib/isc/include/isc/util.h index 971f21dc1e..95d93fd332 100644 --- a/lib/isc/include/isc/util.h +++ b/lib/isc/include/isc/util.h @@ -35,6 +35,10 @@ #define __has_feature(x) 0 #endif /* if !defined(__has_feature) */ +#ifndef __has_header +#define __has_header(x) 0 +#endif + /*** *** General Macros. ***/ diff --git a/lib/isc/time.c b/lib/isc/time.c index fc47e6c48f..90afabfc42 100644 --- a/lib/isc/time.c +++ b/lib/isc/time.c @@ -190,7 +190,7 @@ isc_time_add(const isc_time_t *t, const isc_interval_t *i, isc_time_t *result) { REQUIRE(t->nanoseconds < NS_PER_SEC && i->nanoseconds < NS_PER_SEC); /* Seconds */ - if (ISC_OVERFLOW_ADD(t->seconds, i->seconds, &result->seconds)) { + if (ckd_add(&result->seconds, t->seconds, i->seconds)) { return ISC_R_RANGE; } @@ -214,7 +214,7 @@ isc_time_subtract(const isc_time_t *t, const isc_interval_t *i, REQUIRE(t->nanoseconds < NS_PER_SEC && i->nanoseconds < NS_PER_SEC); /* Seconds */ - if (ISC_OVERFLOW_SUB(t->seconds, i->seconds, &result->seconds)) { + if (ckd_sub(&result->seconds, t->seconds, i->seconds)) { return ISC_R_RANGE; } diff --git a/meson.build b/meson.build index d0ae062092..736f99d8fe 100644 --- a/meson.build +++ b/meson.build @@ -316,12 +316,14 @@ endif foreach fn : [ '__builtin_add_overflow', + '__builtin_expect', '__builtin_mul_overflow', + '__builtin_prefetch', '__builtin_sub_overflow', '__builtin_unreachable', ] - if cc.has_function(fn) - config.set('HAVE_@0@'.format(fn.substring(2).to_upper()), 1) + if not cc.has_function(fn) + error('@0@ support required'.format(fn)) endif endforeach @@ -523,6 +525,7 @@ foreach h : [ 'net/if6.h', 'net/route.h', 'regex.h', + 'stdckdint.h', 'sys/mman.h', 'sys/select.h', 'sys/sockio.h',