mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-02 00:04:12 +08:00
mdbx++: add assertions for destination-overflow to from/to hex/base58/base64::write_bytes().
Change-Id: I5a1f23dcb1dc1942f9d72966a78080eacfacf546
This commit is contained in:
parent
b5b0a9a284
commit
f2995ac75b
145
src/mdbx.c++
145
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))
|
if (MDBX_UNLIKELY(envisage_result_length() > dest_size))
|
||||||
MDBX_CXX20_UNLIKELY throw_too_small_target_buffer();
|
MDBX_CXX20_UNLIKELY throw_too_small_target_buffer();
|
||||||
|
|
||||||
|
auto ptr = dest;
|
||||||
auto src = source.byte_ptr();
|
auto src = source.byte_ptr();
|
||||||
const char alphabase = (uppercase ? 'A' : 'a') - 10;
|
const char alphabase = (uppercase ? 'A' : 'a') - 10;
|
||||||
auto line = dest;
|
auto line = ptr;
|
||||||
for (const auto end = source.end_byte_ptr(); src != end; ++src) {
|
for (const auto end = source.end_byte_ptr(); src != end; ++src) {
|
||||||
if (wrap_width && size_t(dest - line) >= wrap_width) {
|
if (wrap_width && size_t(ptr - line) >= wrap_width) {
|
||||||
*dest = '\n';
|
*ptr = '\n';
|
||||||
line = ++dest;
|
line = ++ptr;
|
||||||
}
|
}
|
||||||
const int8_t hi = *src >> 4;
|
const int8_t hi = *src >> 4;
|
||||||
const int8_t lo = *src & 15;
|
const int8_t lo = *src & 15;
|
||||||
dest[0] = char(alphabase + hi + (((hi - 10) >> 7) & -7));
|
ptr[0] = char(alphabase + hi + (((hi - 10) >> 7) & -7));
|
||||||
dest[1] = char(alphabase + lo + (((lo - 10) >> 7) & -7));
|
ptr[1] = char(alphabase + lo + (((lo - 10) >> 7) & -7));
|
||||||
dest += 2;
|
ptr += 2;
|
||||||
|
assert(ptr <= dest + dest_size);
|
||||||
}
|
}
|
||||||
return dest;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
::std::ostream &to_hex::output(::std::ostream &out) const {
|
::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;
|
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))
|
if (MDBX_UNLIKELY(source.length() % 2 && !ignore_spaces))
|
||||||
MDBX_CXX20_UNLIKELY throw std::domain_error(
|
MDBX_CXX20_UNLIKELY throw std::domain_error(
|
||||||
"mdbx::from_hex:: odd length of hexadecimal string");
|
"mdbx::from_hex:: odd length of hexadecimal string");
|
||||||
if (MDBX_UNLIKELY(envisage_result_length() > dest_size))
|
if (MDBX_UNLIKELY(envisage_result_length() > dest_size))
|
||||||
MDBX_CXX20_UNLIKELY throw_too_small_target_buffer();
|
MDBX_CXX20_UNLIKELY throw_too_small_target_buffer();
|
||||||
|
|
||||||
|
auto ptr = dest;
|
||||||
auto src = source.byte_ptr();
|
auto src = source.byte_ptr();
|
||||||
for (auto left = source.length(); left > 0;) {
|
for (auto left = source.length(); left > 0;) {
|
||||||
if (MDBX_UNLIKELY(*src <= ' ') &&
|
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 = (lo | 0x20) - 'a';
|
||||||
lo += 10 + ((lo >> 7) & 7);
|
lo += 10 + ((lo >> 7) & 7);
|
||||||
|
|
||||||
*dest++ = hi << 4 | lo;
|
*ptr++ = hi << 4 | lo;
|
||||||
src += 2;
|
src += 2;
|
||||||
left -= 2;
|
left -= 2;
|
||||||
|
assert(ptr <= dest + dest_size);
|
||||||
}
|
}
|
||||||
return dest;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool from_hex::is_erroneous() const noexcept {
|
bool from_hex::is_erroneous() const noexcept {
|
||||||
@ -686,13 +691,15 @@ static inline char b58_8to11(uint64_t &v) noexcept {
|
|||||||
return b58_alphabet[i];
|
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))
|
if (MDBX_UNLIKELY(envisage_result_length() > dest_size))
|
||||||
MDBX_CXX20_UNLIKELY throw_too_small_target_buffer();
|
MDBX_CXX20_UNLIKELY throw_too_small_target_buffer();
|
||||||
|
|
||||||
|
auto ptr = dest;
|
||||||
auto src = source.byte_ptr();
|
auto src = source.byte_ptr();
|
||||||
size_t left = source.length();
|
size_t left = source.length();
|
||||||
auto line = dest;
|
auto line = ptr;
|
||||||
while (MDBX_LIKELY(left > 7)) {
|
while (MDBX_LIKELY(left > 7)) {
|
||||||
uint64_t v;
|
uint64_t v;
|
||||||
std::memcpy(&v, src, 8);
|
std::memcpy(&v, src, 8);
|
||||||
@ -703,24 +710,25 @@ char *to_base58::write_bytes(char *__restrict dest, size_t dest_size) const {
|
|||||||
#else
|
#else
|
||||||
#error "FIXME: Unsupported byte order"
|
#error "FIXME: Unsupported byte order"
|
||||||
#endif /* __BYTE_ORDER__ */
|
#endif /* __BYTE_ORDER__ */
|
||||||
dest[10] = b58_8to11(v);
|
ptr[10] = b58_8to11(v);
|
||||||
dest[9] = b58_8to11(v);
|
ptr[9] = b58_8to11(v);
|
||||||
dest[8] = b58_8to11(v);
|
ptr[8] = b58_8to11(v);
|
||||||
dest[7] = b58_8to11(v);
|
ptr[7] = b58_8to11(v);
|
||||||
dest[6] = b58_8to11(v);
|
ptr[6] = b58_8to11(v);
|
||||||
dest[5] = b58_8to11(v);
|
ptr[5] = b58_8to11(v);
|
||||||
dest[4] = b58_8to11(v);
|
ptr[4] = b58_8to11(v);
|
||||||
dest[3] = b58_8to11(v);
|
ptr[3] = b58_8to11(v);
|
||||||
dest[2] = b58_8to11(v);
|
ptr[2] = b58_8to11(v);
|
||||||
dest[1] = b58_8to11(v);
|
ptr[1] = b58_8to11(v);
|
||||||
dest[0] = b58_8to11(v);
|
ptr[0] = b58_8to11(v);
|
||||||
assert(v == 0);
|
assert(v == 0);
|
||||||
dest += 11;
|
ptr += 11;
|
||||||
left -= 8;
|
left -= 8;
|
||||||
if (wrap_width && size_t(dest - line) >= wrap_width && left) {
|
if (wrap_width && size_t(ptr - line) >= wrap_width && left) {
|
||||||
*dest = '\n';
|
*ptr = '\n';
|
||||||
line = ++dest;
|
line = ++ptr;
|
||||||
}
|
}
|
||||||
|
assert(ptr <= dest + dest_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (left) {
|
if (left) {
|
||||||
@ -731,15 +739,16 @@ char *to_base58::write_bytes(char *__restrict dest, size_t dest_size) const {
|
|||||||
parrots += 43;
|
parrots += 43;
|
||||||
} while (--left);
|
} while (--left);
|
||||||
|
|
||||||
auto ptr = dest += parrots >> 5;
|
auto tail = ptr += parrots >> 5;
|
||||||
|
assert(ptr <= dest + dest_size);
|
||||||
do {
|
do {
|
||||||
*--ptr = b58_8to11(v);
|
*--tail = b58_8to11(v);
|
||||||
parrots -= 32;
|
parrots -= 32;
|
||||||
} while (parrots > 31);
|
} while (parrots > 31);
|
||||||
assert(v == 0);
|
assert(v == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dest;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
::std::ostream &to_base58::output(::std::ostream &out) const {
|
::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;
|
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))
|
if (MDBX_UNLIKELY(envisage_result_length() > dest_size))
|
||||||
MDBX_CXX20_UNLIKELY throw_too_small_target_buffer();
|
MDBX_CXX20_UNLIKELY throw_too_small_target_buffer();
|
||||||
|
|
||||||
|
auto ptr = dest;
|
||||||
auto src = source.byte_ptr();
|
auto src = source.byte_ptr();
|
||||||
for (auto left = source.length(); left > 0;) {
|
for (auto left = source.length(); left > 0;) {
|
||||||
if (MDBX_UNLIKELY(isspace(*src)) && ignore_spaces) {
|
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
|
#else
|
||||||
#error "FIXME: Unsupported byte order"
|
#error "FIXME: Unsupported byte order"
|
||||||
#endif /* __BYTE_ORDER__ */
|
#endif /* __BYTE_ORDER__ */
|
||||||
std::memcpy(dest, &v, 8);
|
std::memcpy(ptr, &v, 8);
|
||||||
dest += 8;
|
ptr += 8;
|
||||||
src += 11;
|
src += 11;
|
||||||
left -= 11;
|
left -= 11;
|
||||||
|
assert(ptr <= dest + dest_size);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -873,14 +885,15 @@ char *from_base58::write_bytes(char *__restrict dest, size_t dest_size) const {
|
|||||||
parrots += 32;
|
parrots += 32;
|
||||||
} while (--left);
|
} while (--left);
|
||||||
|
|
||||||
auto ptr = dest += parrots / 43;
|
auto tail = ptr += parrots / 43;
|
||||||
|
assert(ptr <= dest + dest_size);
|
||||||
do {
|
do {
|
||||||
*--ptr = byte(v);
|
*--tail = byte(v);
|
||||||
v >>= 8;
|
v >>= 8;
|
||||||
} while (v > 255);
|
} while (v > 255);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return dest;
|
return ptr;
|
||||||
|
|
||||||
bailout:
|
bailout:
|
||||||
throw std::domain_error("mdbx::from_base58:: invalid base58 string");
|
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];
|
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))
|
if (MDBX_UNLIKELY(envisage_result_length() > dest_size))
|
||||||
MDBX_CXX20_UNLIKELY throw_too_small_target_buffer();
|
MDBX_CXX20_UNLIKELY throw_too_small_target_buffer();
|
||||||
|
|
||||||
|
auto ptr = dest;
|
||||||
auto src = source.byte_ptr();
|
auto src = source.byte_ptr();
|
||||||
size_t left = source.length();
|
size_t left = source.length();
|
||||||
auto line = dest;
|
auto line = ptr;
|
||||||
while (true) {
|
while (true) {
|
||||||
switch (left) {
|
switch (left) {
|
||||||
default:
|
default:
|
||||||
MDBX_CXX20_LIKELY left -= 3;
|
MDBX_CXX20_LIKELY left -= 3;
|
||||||
b64_3to4(src[0], src[1], src[2], dest);
|
b64_3to4(src[0], src[1], src[2], ptr);
|
||||||
dest += 4;
|
ptr += 4;
|
||||||
src += 3;
|
src += 3;
|
||||||
if (wrap_width && size_t(dest - line) >= wrap_width && left) {
|
if (wrap_width && size_t(ptr - line) >= wrap_width && left) {
|
||||||
*dest = '\n';
|
*ptr = '\n';
|
||||||
line = ++dest;
|
line = ++ptr;
|
||||||
}
|
}
|
||||||
|
assert(ptr <= dest + dest_size);
|
||||||
continue;
|
continue;
|
||||||
case 2:
|
case 2:
|
||||||
b64_3to4(src[0], src[1], 0, dest);
|
b64_3to4(src[0], src[1], 0, ptr);
|
||||||
dest[3] = '=';
|
ptr[3] = '=';
|
||||||
return dest + 4;
|
assert(ptr + 4 <= dest + dest_size);
|
||||||
|
return ptr + 4;
|
||||||
case 1:
|
case 1:
|
||||||
b64_3to4(src[0], 0, 0, dest);
|
b64_3to4(src[0], 0, 0, ptr);
|
||||||
dest[2] = dest[3] = '=';
|
ptr[2] = ptr[3] = '=';
|
||||||
return dest + 4;
|
assert(ptr + 4 <= dest + dest_size);
|
||||||
|
return ptr + 4;
|
||||||
case 0:
|
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;
|
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))
|
if (MDBX_UNLIKELY(source.length() % 4 && !ignore_spaces))
|
||||||
MDBX_CXX20_UNLIKELY throw std::domain_error(
|
MDBX_CXX20_UNLIKELY throw std::domain_error(
|
||||||
"mdbx::from_base64:: odd length of base64 string");
|
"mdbx::from_base64:: odd length of base64 string");
|
||||||
if (MDBX_UNLIKELY(envisage_result_length() > dest_size))
|
if (MDBX_UNLIKELY(envisage_result_length() > dest_size))
|
||||||
MDBX_CXX20_UNLIKELY throw_too_small_target_buffer();
|
MDBX_CXX20_UNLIKELY throw_too_small_target_buffer();
|
||||||
|
|
||||||
|
auto ptr = dest;
|
||||||
auto src = source.byte_ptr();
|
auto src = source.byte_ptr();
|
||||||
for (auto left = source.length(); left > 0;) {
|
for (auto left = source.length(); left > 0;) {
|
||||||
if (MDBX_UNLIKELY(*src <= ' ') &&
|
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]],
|
const signed char a = b64_map[src[0]], b = b64_map[src[1]],
|
||||||
c = b64_map[src[2]], d = b64_map[src[3]];
|
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 (left == 4 && (a | b) >= 0 && d == EQ) {
|
||||||
if (c >= 0)
|
if (c >= 0) {
|
||||||
return dest + 2;
|
assert(ptr + 2 <= dest + dest_size);
|
||||||
if (c == d)
|
return ptr + 2;
|
||||||
return dest + 1;
|
}
|
||||||
|
if (c == d) {
|
||||||
|
assert(ptr + 1 <= dest + dest_size);
|
||||||
|
return ptr + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
MDBX_CXX20_UNLIKELY goto bailout;
|
MDBX_CXX20_UNLIKELY goto bailout;
|
||||||
}
|
}
|
||||||
src += 4;
|
src += 4;
|
||||||
left -= 4;
|
left -= 4;
|
||||||
dest += 3;
|
ptr += 3;
|
||||||
|
assert(ptr <= dest + dest_size);
|
||||||
}
|
}
|
||||||
return dest;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool from_base64::is_erroneous() const noexcept {
|
bool from_base64::is_erroneous() const noexcept {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user