diff options
author | Juan José Arboleda <soyjuanarbol@gmail.com> | 2020-08-25 23:31:11 +0300 |
---|---|---|
committer | Anna Henningsen <anna@addaleax.net> | 2020-09-30 18:53:35 +0300 |
commit | ff4cf817a3159ddf7c4bf898819f88445c5fee53 (patch) | |
tree | edbca8efc08eec6297be0e3bb088f9bf3e07b1bc | |
parent | a8806535d9e7db7bf20b3b3ef8f911320baf7511 (diff) |
src: create helper for reading Uint32BE
Fixes: https://github.com/nodejs/node/issues/34827
PR-URL: https://github.com/nodejs/node/pull/34944
Reviewed-By: Anna Henningsen <anna@addaleax.net>
-rw-r--r-- | node.gyp | 1 | ||||
-rw-r--r-- | src/base64-inl.h | 98 | ||||
-rw-r--r-- | src/base64.h | 78 | ||||
-rw-r--r-- | src/cares_wrap.cc | 18 | ||||
-rw-r--r-- | src/node_sockaddr.cc | 3 |
5 files changed, 110 insertions, 88 deletions
@@ -668,6 +668,7 @@ 'src/base_object.h', 'src/base_object-inl.h', 'src/base64.h', + 'src/base64-inl.h', 'src/callback_queue.h', 'src/callback_queue-inl.h', 'src/connect_wrap.h', diff --git a/src/base64-inl.h b/src/base64-inl.h new file mode 100644 index 00000000000..9132faa614e --- /dev/null +++ b/src/base64-inl.h @@ -0,0 +1,98 @@ +#ifndef SRC_BASE64_INL_H_ +#define SRC_BASE64_INL_H_ + +#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#include "util.h" + +namespace node { + +extern const int8_t unbase64_table[256]; + + +inline static int8_t unbase64(uint8_t x) { + return unbase64_table[x]; +} + + +inline uint32_t ReadUint32BE(const unsigned char* p) { + return static_cast<uint32_t>(p[0] << 24U) | + static_cast<uint32_t>(p[1] << 16U) | + static_cast<uint32_t>(p[2] << 8U) | + static_cast<uint32_t>(p[3]); +} + + +template <typename TypeName> +bool base64_decode_group_slow(char* const dst, const size_t dstlen, + const TypeName* const src, const size_t srclen, + size_t* const i, size_t* const k) { + uint8_t hi; + uint8_t lo; +#define V(expr) \ + for (;;) { \ + const uint8_t c = src[*i]; \ + lo = unbase64(c); \ + *i += 1; \ + if (lo < 64) \ + break; /* Legal character. */ \ + if (c == '=' || *i >= srclen) \ + return false; /* Stop decoding. */ \ + } \ + expr; \ + if (*i >= srclen) \ + return false; \ + if (*k >= dstlen) \ + return false; \ + hi = lo; + V(/* Nothing. */); + V(dst[(*k)++] = ((hi & 0x3F) << 2) | ((lo & 0x30) >> 4)); + V(dst[(*k)++] = ((hi & 0x0F) << 4) | ((lo & 0x3C) >> 2)); + V(dst[(*k)++] = ((hi & 0x03) << 6) | ((lo & 0x3F) >> 0)); +#undef V + return true; // Continue decoding. +} + + +template <typename TypeName> +size_t base64_decode_fast(char* const dst, const size_t dstlen, + const TypeName* const src, const size_t srclen, + const size_t decoded_size) { + const size_t available = dstlen < decoded_size ? dstlen : decoded_size; + const size_t max_k = available / 3 * 3; + size_t max_i = srclen / 4 * 4; + size_t i = 0; + size_t k = 0; + while (i < max_i && k < max_k) { + const unsigned char txt[] = { + static_cast<unsigned char>(unbase64(src[i + 0])), + static_cast<unsigned char>(unbase64(src[i + 1])), + static_cast<unsigned char>(unbase64(src[i + 2])), + static_cast<unsigned char>(unbase64(src[i + 3])), + }; + + const uint32_t v = ReadUint32BE(txt); + // If MSB is set, input contains whitespace or is not valid base64. + if (v & 0x80808080) { + if (!base64_decode_group_slow(dst, dstlen, src, srclen, &i, &k)) + return k; + max_i = i + (srclen - i) / 4 * 4; // Align max_i again. + } else { + dst[k + 0] = ((v >> 22) & 0xFC) | ((v >> 20) & 0x03); + dst[k + 1] = ((v >> 12) & 0xF0) | ((v >> 10) & 0x0F); + dst[k + 2] = ((v >> 2) & 0xC0) | ((v >> 0) & 0x3F); + i += 4; + k += 3; + } + } + if (i < srclen && k < dstlen) { + base64_decode_group_slow(dst, dstlen, src, srclen, &i, &k); + } + return k; +} + +} // namespace node + +#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#endif // SRC_BASE64_INL_H_ diff --git a/src/base64.h b/src/base64.h index 1cb90bdeba7..24fc57e1d60 100644 --- a/src/base64.h +++ b/src/base64.h @@ -4,6 +4,7 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include "util.h" +#include "base64-inl.h" #include <cstddef> #include <cstdint> @@ -20,6 +21,8 @@ static inline constexpr size_t base64_decoded_size_fast(size_t size) { return size > 1 ? (size / 4) * 3 + (size % 4 + 1) / 2 : 0; } +inline uint32_t ReadUint32BE(const unsigned char* p); + template <typename TypeName> size_t base64_decoded_size(const TypeName* src, size_t size) { // 1-byte input cannot be decoded @@ -34,81 +37,6 @@ size_t base64_decoded_size(const TypeName* src, size_t size) { return base64_decoded_size_fast(size); } - -extern const int8_t unbase64_table[256]; - - -inline static int8_t unbase64(uint8_t x) { - return unbase64_table[x]; -} - - -template <typename TypeName> -bool base64_decode_group_slow(char* const dst, const size_t dstlen, - const TypeName* const src, const size_t srclen, - size_t* const i, size_t* const k) { - uint8_t hi; - uint8_t lo; -#define V(expr) \ - for (;;) { \ - const uint8_t c = src[*i]; \ - lo = unbase64(c); \ - *i += 1; \ - if (lo < 64) \ - break; /* Legal character. */ \ - if (c == '=' || *i >= srclen) \ - return false; /* Stop decoding. */ \ - } \ - expr; \ - if (*i >= srclen) \ - return false; \ - if (*k >= dstlen) \ - return false; \ - hi = lo; - V(/* Nothing. */); - V(dst[(*k)++] = ((hi & 0x3F) << 2) | ((lo & 0x30) >> 4)); - V(dst[(*k)++] = ((hi & 0x0F) << 4) | ((lo & 0x3C) >> 2)); - V(dst[(*k)++] = ((hi & 0x03) << 6) | ((lo & 0x3F) >> 0)); -#undef V - return true; // Continue decoding. -} - - -template <typename TypeName> -size_t base64_decode_fast(char* const dst, const size_t dstlen, - const TypeName* const src, const size_t srclen, - const size_t decoded_size) { - const size_t available = dstlen < decoded_size ? dstlen : decoded_size; - const size_t max_k = available / 3 * 3; - size_t max_i = srclen / 4 * 4; - size_t i = 0; - size_t k = 0; - while (i < max_i && k < max_k) { - const uint32_t v = - unbase64(src[i + 0]) << 24 | - unbase64(src[i + 1]) << 16 | - unbase64(src[i + 2]) << 8 | - unbase64(src[i + 3]); - // If MSB is set, input contains whitespace or is not valid base64. - if (v & 0x80808080) { - if (!base64_decode_group_slow(dst, dstlen, src, srclen, &i, &k)) - return k; - max_i = i + (srclen - i) / 4 * 4; // Align max_i again. - } else { - dst[k + 0] = ((v >> 22) & 0xFC) | ((v >> 20) & 0x03); - dst[k + 1] = ((v >> 12) & 0xF0) | ((v >> 10) & 0x0F); - dst[k + 2] = ((v >> 2) & 0xC0) | ((v >> 0) & 0x3F); - i += 4; - k += 3; - } - } - if (i < srclen && k < dstlen) { - base64_decode_group_slow(dst, dstlen, src, srclen, &i, &k); - } - return k; -} - - template <typename TypeName> size_t base64_decode(char* const dst, const size_t dstlen, const TypeName* const src, const size_t srclen) { diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc index 73a0ac6b334..defe1ef3749 100644 --- a/src/cares_wrap.cc +++ b/src/cares_wrap.cc @@ -22,6 +22,7 @@ #define CARES_STATICLIB #include "ares.h" #include "async_wrap-inl.h" +#include "base64-inl.h" #include "env-inl.h" #include "memory_tracker-inl.h" #include "node.h" @@ -79,13 +80,6 @@ inline uint16_t cares_get_16bit(const unsigned char* p) { return static_cast<uint32_t>(p[0] << 8U) | (static_cast<uint32_t>(p[1])); } -inline uint32_t cares_get_32bit(const unsigned char* p) { - return static_cast<uint32_t>(p[0] << 24U) | - static_cast<uint32_t>(p[1] << 16U) | - static_cast<uint32_t>(p[2] << 8U) | - static_cast<uint32_t>(p[3]); -} - const int ns_t_cname_or_a = -1; #define DNS_ESETSRVPENDING -1000 @@ -1127,11 +1121,11 @@ int ParseSoaReply(Environment* env, return ARES_EBADRESP; } - const unsigned int serial = cares_get_32bit(ptr + 0 * 4); - const unsigned int refresh = cares_get_32bit(ptr + 1 * 4); - const unsigned int retry = cares_get_32bit(ptr + 2 * 4); - const unsigned int expire = cares_get_32bit(ptr + 3 * 4); - const unsigned int minttl = cares_get_32bit(ptr + 4 * 4); + const unsigned int serial = ReadUint32BE(ptr + 0 * 4); + const unsigned int refresh = ReadUint32BE(ptr + 1 * 4); + const unsigned int retry = ReadUint32BE(ptr + 2 * 4); + const unsigned int expire = ReadUint32BE(ptr + 3 * 4); + const unsigned int minttl = ReadUint32BE(ptr + 4 * 4); Local<Object> soa_record = Object::New(env->isolate()); soa_record->Set(context, diff --git a/src/node_sockaddr.cc b/src/node_sockaddr.cc index 58d03eefa6e..8d7c93255b0 100644 --- a/src/node_sockaddr.cc +++ b/src/node_sockaddr.cc @@ -1,5 +1,6 @@ #include "node_sockaddr-inl.h" // NOLINT(build/include) #include "env-inl.h" +#include "base64-inl.h" #include "base_object-inl.h" #include "memory_tracker-inl.h" #include "uv.h" @@ -302,7 +303,7 @@ bool in_network_ipv6_ipv4( return false; ptr += sizeof(mask); - uint32_t check = ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3]; + uint32_t check = ReadUint32BE(ptr); return (check & m) == (htonl(net_in->sin_addr.s_addr) & m); } |