From 94fae97f8888dc0539f82bf2f3c86652b7f5256d Mon Sep 17 00:00:00 2001 From: Leonid Yuriev Date: Tue, 17 Nov 2020 15:00:51 +0300 Subject: [PATCH] mdbx: avoid paranoid CLANG's enum ops UB. --- mdbx.h | 13 +++++++++++-- test/keygen.cc | 42 +++++++++++++++++++++++++----------------- test/nested.cc | 4 ++-- test/test.cc | 2 +- 4 files changed, 39 insertions(+), 22 deletions(-) diff --git a/mdbx.h b/mdbx.h index 1d4ad575..39f304f2 100644 --- a/mdbx.h +++ b/mdbx.h @@ -483,9 +483,18 @@ typedef mode_t mdbx_mode_t; MDBX_CXX01_CONSTEXPR ENUM operator&(ENUM a, ENUM b) { \ return ENUM(std::size_t(a) & std::size_t(b)); \ } \ + MDBX_CXX01_CONSTEXPR ENUM operator&(ENUM a, size_t b) { \ + return ENUM(std::size_t(a) & b); \ + } \ + MDBX_CXX01_CONSTEXPR ENUM operator&(size_t a, ENUM b) { \ + return ENUM(a & std::size_t(b)); \ + } \ MDBX_CXX14_CONSTEXPR ENUM &operator&=(ENUM &a, ENUM b) { return a = a & b; } \ - MDBX_CXX01_CONSTEXPR ENUM operator~(ENUM a) { \ - return ENUM(~std::size_t(a)); \ + MDBX_CXX14_CONSTEXPR ENUM &operator&=(ENUM &a, size_t b) { \ + return a = a & b; \ + } \ + MDBX_CXX01_CONSTEXPR std::size_t operator~(ENUM a) { \ + return ~std::size_t(a); \ } \ MDBX_CXX01_CONSTEXPR ENUM operator^(ENUM a, ENUM b) { \ return ENUM(std::size_t(a) ^ std::size_t(b)); \ diff --git a/test/keygen.cc b/test/keygen.cc index 411bf623..a941e3ae 100644 --- a/test/keygen.cc +++ b/test/keygen.cc @@ -115,7 +115,7 @@ void __hot maker::pair(serial_t serial, const buffer &key, buffer &value, serial_t key_serial = serial; serial_t value_serial = value_age << mapping.split; if (mapping.split) { - if (key_essentials.flags & MDBX_DUPSORT) { + if (MDBX_db_flags_t(key_essentials.flags) & MDBX_DUPSORT) { key_serial >>= mapping.split; value_serial += serial & mask(mapping.split); } else { @@ -203,7 +203,7 @@ void maker::setup(const config::actor_params_pod &actor, unsigned actor_id, #endif key_essentials.flags = actor.table_flags & - uint16_t(MDBX_INTEGERKEY | MDBX_REVERSEKEY | MDBX_DUPSORT); + MDBX_db_flags_t(MDBX_INTEGERKEY | MDBX_REVERSEKEY | MDBX_DUPSORT); assert(actor.keylen_min <= UINT16_MAX); key_essentials.minlen = (uint16_t)actor.keylen_min; assert(actor.keylen_max <= UINT32_MAX); @@ -213,7 +213,7 @@ void maker::setup(const config::actor_params_pod &actor, unsigned actor_id, actor.pagesize, MDBX_db_flags_t(key_essentials.flags)))); value_essentials.flags = - actor.table_flags & uint16_t(MDBX_INTEGERDUP | MDBX_REVERSEDUP); + actor.table_flags & MDBX_db_flags_t(MDBX_INTEGERDUP | MDBX_REVERSEDUP); assert(actor.datalen_min <= UINT16_MAX); value_essentials.minlen = (uint16_t)actor.datalen_min; assert(actor.datalen_max <= UINT32_MAX); @@ -236,35 +236,41 @@ void maker::setup(const config::actor_params_pod &actor, unsigned actor_id, } void maker::make_linear() { - mapping.mesh = (key_essentials.flags & MDBX_DUPSORT) ? 0 : mapping.split; + mapping.mesh = (MDBX_db_flags_t(key_essentials.flags) & MDBX_DUPSORT) + ? 0 + : mapping.split; mapping.rotate = 0; mapping.offset = 0; const auto max_serial = mask(mapping.width) + base; const auto max_key_serial = - (mapping.split && (key_essentials.flags & MDBX_DUPSORT)) + (mapping.split && (MDBX_db_flags_t(key_essentials.flags) & MDBX_DUPSORT)) ? max_serial >> mapping.split : max_serial; const auto max_value_serial = - (mapping.split && (key_essentials.flags & MDBX_DUPSORT)) + (mapping.split && (MDBX_db_flags_t(key_essentials.flags) & MDBX_DUPSORT)) ? mask(mapping.split) : 0; while (key_essentials.minlen < 8 && (key_essentials.minlen == 0 || mask(key_essentials.minlen * 8) < max_key_serial)) { - key_essentials.minlen += - (key_essentials.flags & (MDBX_INTEGERKEY | MDBX_INTEGERDUP)) ? 4 : 1; + key_essentials.minlen += (MDBX_db_flags_t(key_essentials.flags) & + (MDBX_INTEGERKEY | MDBX_INTEGERDUP)) + ? 4 + : 1; if (key_essentials.maxlen < key_essentials.minlen) key_essentials.maxlen = key_essentials.minlen; } - if ((key_essentials.flags | value_essentials.flags) & MDBX_DUPSORT) + if (MDBX_db_flags_t(key_essentials.flags | value_essentials.flags) & + MDBX_DUPSORT) while (value_essentials.minlen < 8 && (value_essentials.minlen == 0 || mask(value_essentials.minlen * 8) < max_value_serial)) { - value_essentials.minlen += - (value_essentials.flags & (MDBX_INTEGERKEY | MDBX_INTEGERDUP)) ? 4 - : 1; + value_essentials.minlen += (MDBX_db_flags_t(value_essentials.flags) & + (MDBX_INTEGERKEY | MDBX_INTEGERDUP)) + ? 4 + : 1; if (value_essentials.maxlen < value_essentials.minlen) value_essentials.maxlen = value_essentials.minlen; } @@ -272,8 +278,9 @@ void maker::make_linear() { bool maker::is_unordered() const { return mapping.rotate || - mapping.mesh > - ((key_essentials.flags & MDBX_DUPSORT) ? 0 : mapping.split); + mapping.mesh > ((MDBX_db_flags_t(key_essentials.flags) & MDBX_DUPSORT) + ? 0 + : mapping.split); } bool maker::increment(serial_t &serial, int delta) const { @@ -374,9 +381,9 @@ void __hot maker::mk_continue(const serial_t serial, const essentials ¶ms, #endif assert(length(serial) <= out.value.iov_len); out.value.iov_base = out.bytes; - if (params.flags & (MDBX_INTEGERKEY | MDBX_INTEGERDUP)) { + if (MDBX_db_flags_t(params.flags) & (MDBX_INTEGERKEY | MDBX_INTEGERDUP)) { assert(params.maxlen == params.minlen); - if (params.flags & (MDBX_INTEGERKEY | MDBX_INTEGERDUP)) + if (MDBX_db_flags_t(params.flags) & (MDBX_INTEGERKEY | MDBX_INTEGERDUP)) assert(params.minlen == 4 || params.minlen == 8); out.u64 = serial; if (!is_byteorder_le() && out.value.iov_len != 8) @@ -393,7 +400,8 @@ void __hot maker::mk_continue(const serial_t serial, const essentials ¶ms, } else memset(out.bytes + 8, '\0', out.value.iov_len - prefix); } - if (unlikely(params.flags & (MDBX_REVERSEKEY | MDBX_REVERSEDUP))) + if (unlikely(MDBX_db_flags_t(params.flags) & + (MDBX_REVERSEKEY | MDBX_REVERSEDUP))) std::reverse((char *)out.value.iov_base, (char *)out.value.iov_base + out.value.iov_len); } diff --git a/test/nested.cc b/test/nested.cc index d26382bf..1952780d 100644 --- a/test/nested.cc +++ b/test/nested.cc @@ -80,8 +80,8 @@ bool testcase_nested::teardown() { void testcase_nested::push_txn() { MDBX_txn *txn; - MDBX_txn_flags_t flags = - MDBX_txn_flags_t(prng32() & (MDBX_TXN_NOSYNC | MDBX_TXN_NOMETASYNC)); + MDBX_txn_flags_t flags = MDBX_txn_flags_t( + prng32() & uint32_t(MDBX_TXN_NOSYNC | MDBX_TXN_NOMETASYNC)); int err = mdbx_txn_begin(db_guard.get(), txn_guard.get(), flags, &txn); if (unlikely(err != MDBX_SUCCESS)) failure_perror("mdbx_txn_begin(nested)", err); diff --git a/test/test.cc b/test/test.cc index d2211a92..f23858f8 100644 --- a/test/test.cc +++ b/test/test.cc @@ -310,7 +310,7 @@ void testcase::txn_inject_writefault(void) { void testcase::txn_inject_writefault(MDBX_txn *txn) { if (config.params.inject_writefaultn && txn) { if (config.params.inject_writefaultn <= nops_completed && - (mdbx_txn_flags(txn) & MDBX_RDONLY) == 0) { + (MDBX_txn_flags_t(mdbx_txn_flags(txn)) & MDBX_TXN_RDONLY) == 0) { log_verbose( "== txn_inject_writefault(): got %u nops or more, inject FAULT", config.params.inject_writefaultn);