Ticket #11726: 0001-Fix-undefined-behavior-in-.-support-detail-endian-en.patch

File 0001-Fix-undefined-behavior-in-.-support-detail-endian-en.patch, 3.7 KB (added by davidlt, 7 years ago)

proposed patch (same as on GitHub)

  • include/boost/spirit/home/support/detail/endian/endian.hpp

    From 86705a50afd1bb317fa07181a86b18666befc219 Mon Sep 17 00:00:00 2001
    From: David Abdurachmanov <david.abdurachmanov@gmail.com>
    Date: Mon, 19 Oct 2015 07:46:57 +0000
    Subject: [PATCH] Fix undefined behavior in ../support/detail/endian/endian.hpp
     (#11726)
    
    Undefined behavior sanitizer (UBSan) with GCC 5.1.1 complains about left
    shifting of negative value at run-time. This happens once
    boost::spirit::detail::load_little_endian is used with a singed type.
    
    The patch resolves the issue by using unsigned type for making left shifts,
    then load_little_endian casts it to specific type T.
    
    Tested with Clang and GCC locally (test case in #11726) and all worked fine.
    Tested by running all Boost test cases before and after, no regressions.
    
    Signed-off-by: David Abdurachmanov <david.abdurachmanov@gmail.com>
    ---
     .../spirit/home/support/detail/endian/endian.hpp    | 21 +++++++++++----------
     1 file changed, 11 insertions(+), 10 deletions(-)
    
    diff --git a/include/boost/spirit/home/support/detail/endian/endian.hpp b/include/boost/spirit/home/support/detail/endian/endian.hpp
    index c806b58..ac1c13f 100644
    a b  
    4141#undef  BOOST_NO_IO_COVER_OPERATORS
    4242#undef  BOOST_MINIMAL_INTEGER_COVER_OPERATORS
    4343#include <boost/type_traits/is_signed.hpp>
     44#include <boost/type_traits/make_unsigned.hpp>
    4445#include <boost/cstdint.hpp>
    4546#include <boost/static_assert.hpp>
    4647#include <boost/spirit/home/support/detail/scoped_enum_emulation.hpp>
    namespace boost { namespace spirit  
    7071    {
    7172      typedef unrolled_byte_loops<T, n_bytes - 1, sign> next;
    7273
    73       static T load_big(const unsigned char* bytes)
     74      static typename boost::make_unsigned<T>::type load_big(const unsigned char* bytes)
    7475        { return *(bytes - 1) | (next::load_big(bytes - 1) << 8); }
    75       static T load_little(const unsigned char* bytes)
     76      static typename boost::make_unsigned<T>::type load_little(const unsigned char* bytes)
    7677        { return *bytes | (next::load_little(bytes + 1) << 8); }
    7778
    7879      static void store_big(char* bytes, T value)
    namespace boost { namespace spirit  
    104105    template <typename T>
    105106    struct unrolled_byte_loops<T, 1, true>
    106107    {
    107       static T load_big(const unsigned char* bytes)
    108         { return *reinterpret_cast<const signed char*>(bytes - 1); }
    109       static T load_little(const unsigned char* bytes)
    110         { return *reinterpret_cast<const signed char*>(bytes); }
     108      static typename boost::make_unsigned<T>::type load_big(const unsigned char* bytes)
     109        { return *(bytes - 1); }
     110      static typename boost::make_unsigned<T>::type load_little(const unsigned char* bytes)
     111        { return *bytes; }
    111112      static void store_big(char* bytes, T value)
    112113        { *(bytes - 1) = static_cast<char>(value); }
    113114      static void store_little(char* bytes, T value)
    namespace boost { namespace spirit  
    118119    inline
    119120    T load_big_endian(const void* bytes)
    120121    {
    121       return unrolled_byte_loops<T, n_bytes>::load_big
    122         (static_cast<const unsigned char*>(bytes) + n_bytes);
     122      return static_cast<T>(unrolled_byte_loops<T, n_bytes>::load_big
     123        (static_cast<const unsigned char*>(bytes) + n_bytes));
    123124    }
    124125
    125126    template <>
    namespace boost { namespace spirit  
    164165    inline
    165166    T load_little_endian(const void* bytes)
    166167    {
    167       return unrolled_byte_loops<T, n_bytes>::load_little
    168         (static_cast<const unsigned char*>(bytes));
     168      return static_cast<T>(unrolled_byte_loops<T, n_bytes>::load_little
     169        (static_cast<const unsigned char*>(bytes)));
    169170    }
    170171
    171172    template <>