summaryrefslogtreecommitdiff
path: root/boost/endian/buffers.hpp
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2019-12-05 15:12:59 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2019-12-05 15:12:59 +0900
commitb8cf34c691623e4ec329053cbbf68522a855882d (patch)
tree34da08632a99677f6b79ecb65e5b655a5b69a67f /boost/endian/buffers.hpp
parent3fdc3e5ee96dca5b11d1694975a65200787eab86 (diff)
downloadboost-b8cf34c691623e4ec329053cbbf68522a855882d.tar.gz
boost-b8cf34c691623e4ec329053cbbf68522a855882d.tar.bz2
boost-b8cf34c691623e4ec329053cbbf68522a855882d.zip
Imported Upstream version 1.67.0upstream/1.67.0
Diffstat (limited to 'boost/endian/buffers.hpp')
-rw-r--r--boost/endian/buffers.hpp58
1 files changed, 39 insertions, 19 deletions
diff --git a/boost/endian/buffers.hpp b/boost/endian/buffers.hpp
index b48b8de7d4..258bbecb54 100644
--- a/boost/endian/buffers.hpp
+++ b/boost/endian/buffers.hpp
@@ -21,8 +21,8 @@
#ifndef BOOST_ENDIAN_BUFFERS_HPP
#define BOOST_ENDIAN_BUFFERS_HPP
-#if defined(_MSC_VER)
-# pragma warning(push)
+#if defined(_MSC_VER)
+# pragma warning(push)
# pragma warning(disable:4365) // conversion ... signed/unsigned mismatch
#endif
@@ -38,11 +38,16 @@
#include <boost/predef/detail/endian_compat.h>
#include <boost/endian/conversion.hpp>
#include <boost/type_traits/is_signed.hpp>
+#include <boost/type_traits/make_unsigned.hpp>
+#include <boost/type_traits/conditional.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/type_identity.hpp>
#include <boost/cstdint.hpp>
#include <boost/static_assert.hpp>
#include <boost/core/scoped_enum.hpp>
#include <iosfwd>
#include <climits>
+#include <cstring>
# if CHAR_BIT != 8
# error Platforms with CHAR_BIT != 8 are not supported
@@ -195,7 +200,7 @@ namespace endian
return os << x.value();
}
- // Stream extractor
+ // Stream extractor
template <class charT, class traits, BOOST_SCOPED_ENUM(order) Order, class T,
std::size_t n_bits, BOOST_SCOPED_ENUM(align) A>
std::basic_istream<charT, traits>&
@@ -221,20 +226,27 @@ namespace endian
{
typedef unrolled_byte_loops<T, n_bytes - 1, sign> next;
+ // shifting a negative number is flagged by -fsanitize=undefined
+ // so use the corresponding unsigned type for the shifts
+
+ typedef typename boost::conditional<
+ boost::is_integral<T>::value,
+ boost::make_unsigned<T>, boost::type_identity<T> >::type::type U;
+
static T load_big(const unsigned char* bytes) BOOST_NOEXCEPT
- { return static_cast<T>(*(bytes - 1) | (next::load_big(bytes - 1) << 8)); }
+ { return static_cast<T>(*(bytes - 1) | (static_cast<U>(next::load_big(bytes - 1)) << 8)); }
static T load_little(const unsigned char* bytes) BOOST_NOEXCEPT
- { return static_cast<T>(*bytes | (next::load_little(bytes + 1) << 8)); }
+ { return static_cast<T>(*bytes | (static_cast<U>(next::load_little(bytes + 1)) << 8)); }
static void store_big(char* bytes, T value) BOOST_NOEXCEPT
{
*(bytes - 1) = static_cast<char>(value);
- next::store_big(bytes - 1, static_cast<T>(value >> 8));
+ next::store_big(bytes - 1, static_cast<T>(static_cast<U>(value) >> 8));
}
static void store_little(char* bytes, T value) BOOST_NOEXCEPT
{
*bytes = static_cast<char>(value);
- next::store_little(bytes + 1, static_cast<T>(value >> 8));
+ next::store_little(bytes + 1, static_cast<T>(static_cast<U>(value) >> 8));
}
};
@@ -284,7 +296,12 @@ namespace endian
// case since sizeof(T) and n_bytes are known at compile
// time.
{
- return *reinterpret_cast<T const *>(bytes);
+ // Avoids -fsanitize=undefined violations due to unaligned loads
+ // All major x86 compilers optimize a short-sized memcpy into a single instruction
+
+ T t;
+ std::memcpy( &t, bytes, sizeof(T) );
+ return t;
}
# endif
return unrolled_byte_loops<T, n_bytes>::load_little
@@ -310,7 +327,10 @@ namespace endian
// case since sizeof(T) and n_bytes are known at compile
// time.
{
- *reinterpret_cast<T *>(bytes) = value;
+ // Avoids -fsanitize=undefined violations due to unaligned stores
+ // All major x86 compilers optimize a short-sized memcpy into a single instruction
+
+ std::memcpy( bytes, &value, sizeof(T) );
return;
}
# endif
@@ -346,7 +366,7 @@ namespace endian
# ifndef BOOST_ENDIAN_NO_CTORS
endian_buffer() BOOST_ENDIAN_DEFAULT_CONSTRUCT
explicit endian_buffer(T val) BOOST_NOEXCEPT
- {
+ {
# ifdef BOOST_ENDIAN_LOG
if ( endian_log )
std::cout << "big, unaligned, "
@@ -365,7 +385,7 @@ namespace endian
return *this;
}
value_type value() const BOOST_NOEXCEPT
- {
+ {
# ifdef BOOST_ENDIAN_LOG
if ( endian_log )
std::cout << "big, unaligned, " << n_bits << "-bits, convert("
@@ -388,7 +408,7 @@ namespace endian
# ifndef BOOST_ENDIAN_NO_CTORS
endian_buffer() BOOST_ENDIAN_DEFAULT_CONSTRUCT
explicit endian_buffer(T val) BOOST_NOEXCEPT
- {
+ {
# ifdef BOOST_ENDIAN_LOG
if ( endian_log )
std::cout << "little, unaligned, " << n_bits << "-bits, construct("
@@ -400,7 +420,7 @@ namespace endian
endian_buffer & operator=(T val) BOOST_NOEXCEPT
{ detail::store_little_endian<T, n_bits/8>(m_value, val); return *this; }
value_type value() const BOOST_NOEXCEPT
- {
+ {
# ifdef BOOST_ENDIAN_LOG
if ( endian_log )
std::cout << "little, unaligned, " << n_bits << "-bits, convert("
@@ -435,14 +455,14 @@ namespace endian
m_value = ::boost::endian::native_to_big(val);
}
-# endif
+# endif
endian_buffer& operator=(T val) BOOST_NOEXCEPT
{
m_value = ::boost::endian::native_to_big(val);
return *this;
}
//operator value_type() const BOOST_NOEXCEPT
- //{
+ //{
// return ::boost::endian::big_to_native(m_value);
//}
value_type value() const BOOST_NOEXCEPT
@@ -480,7 +500,7 @@ namespace endian
m_value = ::boost::endian::native_to_little(val);
}
-# endif
+# endif
endian_buffer& operator=(T val) BOOST_NOEXCEPT
{
m_value = ::boost::endian::native_to_little(val);
@@ -508,8 +528,8 @@ namespace endian
# pragma pack(pop)
#endif
-#if defined(_MSC_VER)
-# pragma warning(pop)
-#endif
+#if defined(_MSC_VER)
+# pragma warning(pop)
+#endif
#endif // BOOST_ENDIAN_BUFFERS_HPP