diff --git a/CHANGELOG.md b/CHANGELOG.md index e40f7c6a..882a4d44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +Version 58: + +* Fix unaligned reads in utf8-checker + +-------------------------------------------------------------------------------- + Version 57: * Fix message.hpp javadocs diff --git a/include/beast/websocket/detail/utf8_checker.hpp b/include/beast/websocket/detail/utf8_checker.hpp index 47082851..6800923a 100644 --- a/include/beast/websocket/detail/utf8_checker.hpp +++ b/include/beast/websocket/detail/utf8_checker.hpp @@ -245,39 +245,59 @@ write(std::uint8_t const* in, std::size_t size) p_ = have_; } - auto last = in + size - 7; - while(in < last) - { -#if BEAST_WEBSOCKET_NO_UNALIGNED_READ - auto constexpr align = sizeof(std::size_t) - 1; - auto constexpr mask = static_cast< - std::size_t>(0x8080808080808080 & - ~std::size_t{0}); - if( - ((reinterpret_cast< - std::uintptr_t>(in) & align) == 0) && - (*reinterpret_cast< - std::size_t const*>(in) & mask) == 0) - in += sizeof(std::size_t); - else if(! valid(in)) - return false; -#else - auto constexpr mask = static_cast< - std::size_t>(0x8080808080808080 & - ~std::size_t{0}); - if( - (*reinterpret_cast< - std::size_t const*>(in) & mask) == 0) - in += sizeof(std::size_t); - else if(! valid(in)) - return false; -#endif - } - last += 4; - while(in < last) - if(! valid(in)) - return false; + if(size <= sizeof(std::size_t)) + goto slow; + // align in to sizeof(std::size_t) boundary + { + auto const in0 = in; + auto last = reinterpret_cast( + ((reinterpret_cast(in) + sizeof(std::size_t) - 1) / + sizeof(std::size_t)) * sizeof(std::size_t)); + while(in < last) + { + if(*in & 0x80) + { + size = size - (in - in0); + goto slow; + } + ++in; + } + size = size - (in - in0); + } + + // fast loop + { + auto const in0 = in; + auto last = in + size - 7; + auto constexpr mask = static_cast< + std::size_t>(0x8080808080808080 & ~std::size_t{0}); + while(in < last) + { + if((*reinterpret_cast(in) & mask) != 0) + { + size = size - (in - in0); + goto slow; + } + in += sizeof(std::size_t); + } + last += 4; + while(in < last) + if(! valid(in)) + return false; + goto tail; + } + + // slow loop: one code point at a time +slow: + { + auto last = in + size - 3; + while(in < last) + if(! valid(in)) + return false; + } + +tail: for(;;) { auto n = end - in;