diff --git a/src/mdbx.c++ b/src/mdbx.c++ index 61d293a7..218fddba 100644 --- a/src/mdbx.c++ +++ b/src/mdbx.c++ @@ -539,25 +539,27 @@ bool slice::is_printable(bool disable_utf8) const noexcept { //------------------------------------------------------------------------------ -char *to_hex::write_bytes(char *__restrict dest, size_t dest_size) const { +char *to_hex::write_bytes(char *__restrict const dest, size_t dest_size) const { if (MDBX_UNLIKELY(envisage_result_length() > dest_size)) MDBX_CXX20_UNLIKELY throw_too_small_target_buffer(); + auto ptr = dest; auto src = source.byte_ptr(); const char alphabase = (uppercase ? 'A' : 'a') - 10; - auto line = dest; + auto line = ptr; for (const auto end = source.end_byte_ptr(); src != end; ++src) { - if (wrap_width && size_t(dest - line) >= wrap_width) { - *dest = '\n'; - line = ++dest; + if (wrap_width && size_t(ptr - line) >= wrap_width) { + *ptr = '\n'; + line = ++ptr; } const int8_t hi = *src >> 4; const int8_t lo = *src & 15; - dest[0] = char(alphabase + hi + (((hi - 10) >> 7) & -7)); - dest[1] = char(alphabase + lo + (((lo - 10) >> 7) & -7)); - dest += 2; + ptr[0] = char(alphabase + hi + (((hi - 10) >> 7) & -7)); + ptr[1] = char(alphabase + lo + (((lo - 10) >> 7) & -7)); + ptr += 2; + assert(ptr <= dest + dest_size); } - return dest; + return ptr; } ::std::ostream &to_hex::output(::std::ostream &out) const { @@ -582,13 +584,15 @@ char *to_hex::write_bytes(char *__restrict dest, size_t dest_size) const { return out; } -char *from_hex::write_bytes(char *__restrict dest, size_t dest_size) const { +char *from_hex::write_bytes(char *__restrict const dest, + size_t dest_size) const { if (MDBX_UNLIKELY(source.length() % 2 && !ignore_spaces)) MDBX_CXX20_UNLIKELY throw std::domain_error( "mdbx::from_hex:: odd length of hexadecimal string"); if (MDBX_UNLIKELY(envisage_result_length() > dest_size)) MDBX_CXX20_UNLIKELY throw_too_small_target_buffer(); + auto ptr = dest; auto src = source.byte_ptr(); for (auto left = source.length(); left > 0;) { if (MDBX_UNLIKELY(*src <= ' ') && @@ -610,11 +614,12 @@ char *from_hex::write_bytes(char *__restrict dest, size_t dest_size) const { lo = (lo | 0x20) - 'a'; lo += 10 + ((lo >> 7) & 7); - *dest++ = hi << 4 | lo; + *ptr++ = hi << 4 | lo; src += 2; left -= 2; + assert(ptr <= dest + dest_size); } - return dest; + return ptr; } bool from_hex::is_erroneous() const noexcept { @@ -686,13 +691,15 @@ static inline char b58_8to11(uint64_t &v) noexcept { return b58_alphabet[i]; } -char *to_base58::write_bytes(char *__restrict dest, size_t dest_size) const { +char *to_base58::write_bytes(char *__restrict const dest, + size_t dest_size) const { if (MDBX_UNLIKELY(envisage_result_length() > dest_size)) MDBX_CXX20_UNLIKELY throw_too_small_target_buffer(); + auto ptr = dest; auto src = source.byte_ptr(); size_t left = source.length(); - auto line = dest; + auto line = ptr; while (MDBX_LIKELY(left > 7)) { uint64_t v; std::memcpy(&v, src, 8); @@ -703,24 +710,25 @@ char *to_base58::write_bytes(char *__restrict dest, size_t dest_size) const { #else #error "FIXME: Unsupported byte order" #endif /* __BYTE_ORDER__ */ - dest[10] = b58_8to11(v); - dest[9] = b58_8to11(v); - dest[8] = b58_8to11(v); - dest[7] = b58_8to11(v); - dest[6] = b58_8to11(v); - dest[5] = b58_8to11(v); - dest[4] = b58_8to11(v); - dest[3] = b58_8to11(v); - dest[2] = b58_8to11(v); - dest[1] = b58_8to11(v); - dest[0] = b58_8to11(v); + ptr[10] = b58_8to11(v); + ptr[9] = b58_8to11(v); + ptr[8] = b58_8to11(v); + ptr[7] = b58_8to11(v); + ptr[6] = b58_8to11(v); + ptr[5] = b58_8to11(v); + ptr[4] = b58_8to11(v); + ptr[3] = b58_8to11(v); + ptr[2] = b58_8to11(v); + ptr[1] = b58_8to11(v); + ptr[0] = b58_8to11(v); assert(v == 0); - dest += 11; + ptr += 11; left -= 8; - if (wrap_width && size_t(dest - line) >= wrap_width && left) { - *dest = '\n'; - line = ++dest; + if (wrap_width && size_t(ptr - line) >= wrap_width && left) { + *ptr = '\n'; + line = ++ptr; } + assert(ptr <= dest + dest_size); } if (left) { @@ -731,15 +739,16 @@ char *to_base58::write_bytes(char *__restrict dest, size_t dest_size) const { parrots += 43; } while (--left); - auto ptr = dest += parrots >> 5; + auto tail = ptr += parrots >> 5; + assert(ptr <= dest + dest_size); do { - *--ptr = b58_8to11(v); + *--tail = b58_8to11(v); parrots -= 32; } while (parrots > 31); assert(v == 0); } - return dest; + return ptr; } ::std::ostream &to_base58::output(::std::ostream &out) const { @@ -827,10 +836,12 @@ static inline signed char b58_11to8(uint64_t &v, const byte c) noexcept { return m; } -char *from_base58::write_bytes(char *__restrict dest, size_t dest_size) const { +char *from_base58::write_bytes(char *__restrict const dest, + size_t dest_size) const { if (MDBX_UNLIKELY(envisage_result_length() > dest_size)) MDBX_CXX20_UNLIKELY throw_too_small_target_buffer(); + auto ptr = dest; auto src = source.byte_ptr(); for (auto left = source.length(); left > 0;) { if (MDBX_UNLIKELY(isspace(*src)) && ignore_spaces) { @@ -854,10 +865,11 @@ char *from_base58::write_bytes(char *__restrict dest, size_t dest_size) const { #else #error "FIXME: Unsupported byte order" #endif /* __BYTE_ORDER__ */ - std::memcpy(dest, &v, 8); - dest += 8; + std::memcpy(ptr, &v, 8); + ptr += 8; src += 11; left -= 11; + assert(ptr <= dest + dest_size); continue; } @@ -873,14 +885,15 @@ char *from_base58::write_bytes(char *__restrict dest, size_t dest_size) const { parrots += 32; } while (--left); - auto ptr = dest += parrots / 43; + auto tail = ptr += parrots / 43; + assert(ptr <= dest + dest_size); do { - *--ptr = byte(v); + *--tail = byte(v); v >>= 8; } while (v > 255); break; } - return dest; + return ptr; bailout: throw std::domain_error("mdbx::from_base58:: invalid base58 string"); @@ -939,35 +952,40 @@ static inline void b64_3to4(const byte x, const byte y, const byte z, dest[3] = alphabet[z & 0x3f]; } -char *to_base64::write_bytes(char *__restrict dest, size_t dest_size) const { +char *to_base64::write_bytes(char *__restrict const dest, + size_t dest_size) const { if (MDBX_UNLIKELY(envisage_result_length() > dest_size)) MDBX_CXX20_UNLIKELY throw_too_small_target_buffer(); + auto ptr = dest; auto src = source.byte_ptr(); size_t left = source.length(); - auto line = dest; + auto line = ptr; while (true) { switch (left) { default: MDBX_CXX20_LIKELY left -= 3; - b64_3to4(src[0], src[1], src[2], dest); - dest += 4; + b64_3to4(src[0], src[1], src[2], ptr); + ptr += 4; src += 3; - if (wrap_width && size_t(dest - line) >= wrap_width && left) { - *dest = '\n'; - line = ++dest; + if (wrap_width && size_t(ptr - line) >= wrap_width && left) { + *ptr = '\n'; + line = ++ptr; } + assert(ptr <= dest + dest_size); continue; case 2: - b64_3to4(src[0], src[1], 0, dest); - dest[3] = '='; - return dest + 4; + b64_3to4(src[0], src[1], 0, ptr); + ptr[3] = '='; + assert(ptr + 4 <= dest + dest_size); + return ptr + 4; case 1: - b64_3to4(src[0], 0, 0, dest); - dest[2] = dest[3] = '='; - return dest + 4; + b64_3to4(src[0], 0, 0, ptr); + ptr[2] = ptr[3] = '='; + assert(ptr + 4 <= dest + dest_size); + return ptr + 4; case 0: - return dest; + return ptr; } } } @@ -1038,13 +1056,15 @@ static inline signed char b64_4to3(signed char a, signed char b, signed char c, return a | b | c | d; } -char *from_base64::write_bytes(char *__restrict dest, size_t dest_size) const { +char *from_base64::write_bytes(char *__restrict const dest, + size_t dest_size) const { if (MDBX_UNLIKELY(source.length() % 4 && !ignore_spaces)) MDBX_CXX20_UNLIKELY throw std::domain_error( "mdbx::from_base64:: odd length of base64 string"); if (MDBX_UNLIKELY(envisage_result_length() > dest_size)) MDBX_CXX20_UNLIKELY throw_too_small_target_buffer(); + auto ptr = dest; auto src = source.byte_ptr(); for (auto left = source.length(); left > 0;) { if (MDBX_UNLIKELY(*src <= ' ') && @@ -1061,20 +1081,25 @@ char *from_base64::write_bytes(char *__restrict dest, size_t dest_size) const { } const signed char a = b64_map[src[0]], b = b64_map[src[1]], c = b64_map[src[2]], d = b64_map[src[3]]; - if (MDBX_UNLIKELY(b64_4to3(a, b, c, d, dest) < 0)) { + if (MDBX_UNLIKELY(b64_4to3(a, b, c, d, ptr) < 0)) { if (left == 4 && (a | b) >= 0 && d == EQ) { - if (c >= 0) - return dest + 2; - if (c == d) - return dest + 1; + if (c >= 0) { + assert(ptr + 2 <= dest + dest_size); + return ptr + 2; + } + if (c == d) { + assert(ptr + 1 <= dest + dest_size); + return ptr + 1; + } } MDBX_CXX20_UNLIKELY goto bailout; } src += 4; left -= 4; - dest += 3; + ptr += 3; + assert(ptr <= dest + dest_size); } - return dest; + return ptr; } bool from_base64::is_erroneous() const noexcept {