fraillt / bitsery

Your binary serialization library
MIT License
1.07k stars 86 forks source link

bug in apple libc++ ARM hash_code function #101

Open victorstewart opened 2 years ago

victorstewart commented 2 years ago

if you check the backtrace below you'll see that the code crashes on the __ptr dereference in non_unique_impl:: hash because it's dereferencing a junk address.

apparently __non_unique_impl is a specialization specifically and only for apple arm. crazy that it's broken out of the box.

so we definitely need some kind of workaround for when called on apple platforms.

struct __non_unique_impl : __string_impl_base {
    _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE
    static size_t __hash(__type_name_t __ptr) _NOEXCEPT {
      size_t __hash = 5381;
      while (unsigned char __c = static_cast<unsigned char>(*__ptr++))
        __hash = (__hash * 33) ^ __c;
      return __hash;
    }
...

0 0x0000000102672e5c in std::type_info_implementations::non_unique_impl::__hash(char const*) [inlined] at /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS16.0.sdk/usr/include/c++/v1/typeinfo:222

1 0x0000000102672e48 in std::type_info_implementations::non_unique_arm_rtti_bit_impl::__hash(unsigned long) [inlined] at /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS16.0.sdk/usr/include/c++/v1/typeinfo:253

2 0x0000000102672e14 in std::type_info::hash_code() const at /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS16.0.sdk/usr/include/c++/v1/typeinfo:338

3 0x0000000102692efc in unsigned long bitsery::ext::StandardRTTI::get(Person&) at /x/libraries/include/bitsery/ext/utils/rtti_utils.h:41

4 0x0000000102692e50 in void bitsery::ext::PolymorphicContext::deserialize<bitsery::Deserializer<bitsery::InputBufferAdapter<String, FastConfig>, std::1::tuple<bitsery::ext::PointerLinkingContext, bitsery::ext::PolymorphicContext > >, Person, void bitsery::ext::pointer_utils::PointerObjectExtensionBase<bitsery::ext::pointer_details::PtrOwnerManager, bitsery::ext::PolymorphicContext, bitsery::ext::StandardRTTI>::deserializeImpl<bitsery::Deserializer<bitsery::InputBufferAdapter<String, FastConfig>, std::1::tuple<bitsery::ext::PointerLinkingContext, bitsery::ext::PolymorphicContext > >, Person, void bitsery::Deserializer<bitsery::InputBufferAdapter<String, FastConfig>, std::__1::tuple<bitsery::ext::PointerLinkingContext, bitsery::ext::PolymorphicContext > >::ext<Person, bitsery::ext::pointer_utils::PointerObjectExtensionBase<bitsery::ext::pointer_details::PtrOwnerManager, bitsery::ext::PolymorphicContext, bitsery::ext::StandardRTTI> >(Person&, bitsery::ext::pointer_utils::PointerObjectExtensionBase<bitsery::ext::pointer_details::PtrOwnerManager, bitsery::ext::PolymorphicContext, bitsery::ext::StandardRTTI> const&)::'lambda'(bitsery::Deserializer<bitsery::InputBufferAdapter<String, FastConfig>, std::__1::tuple<bitsery::ext::PointerLinkingContext, bitsery::ext::PolymorphicContext > >&, Person&)>(bitsery::ext::MemResourceBase, bitsery::ext::pointer_utils::PLCInfoDeserializer&, Person&, bitsery::ext::pointer_utils::PointerObjectExtensionBase<bitsery::ext::pointer_details::PtrOwnerManager, bitsery::ext::PolymorphicContext, bitsery::ext::StandardRTTI>&, void bitsery::Deserializer<bitsery::InputBufferAdapter<String, FastConfig>, std::__1::tuple<bitsery::ext::PointerLinkingContext, bitsery::ext::PolymorphicContext > >::ext<Person, bitsery::ext::pointer_utils::PointerObjectExtensionBase<bitsery::ext::pointer_details::PtrOwnerManager, bitsery::ext::PolymorphicContext, bitsery::ext::StandardRTTI> >(Person&, bitsery::ext::pointer_utils::PointerObjectExtensionBase<bitsery::ext::pointer_details::PtrOwnerManager, bitsery::ext::PolymorphicContext, bitsery::ext::StandardRTTI> const&)::'lambda'(bitsery::Deserializer<bitsery::InputBufferAdapter<String, FastConfig>, std::1::tuple<bitsery::ext::PointerLinkingContext, bitsery::ext::PolymorphicContext > >&, Person&)&&, std::1::integral_constant<bool, true>, std::1::integral_constant<bitsery::ext::PointerOwnershipType, (bitsery::ext::PointerOwnershipType)1>) const::'lambda'(std::__1::shared_ptr const&), void bitsery::ext::pointer_utils::PointerObjectExtensionBase<bitsery::ext::pointer_details::PtrOwnerManager, bitsery::ext::PolymorphicContext, bitsery::ext::StandardRTTI>::deserializeImpl<bitsery::Deserializer<bitsery::InputBufferAdapter<String, FastConfig>, std::1::tuple<bitsery::ext::PointerLinkingContext, bitsery::ext::PolymorphicContext > >, Person, void bitsery::Deserializer<bitsery::InputBufferAdapter<String, FastConfig>, std::1::tuple<bitsery::ext::PointerLinkingContext, bitsery::ext::PolymorphicContext > >::ext<Person, bitsery::ext::pointer_utils::PointerObjectExtensionBase<bitsery::ext::pointer_details::PtrOwnerManager, bitsery::ext::PolymorphicContext, bitsery::ext::StandardRTTI> >(Person&, bitsery::ext::pointer_utils::PointerObjectExtensionBase<bitsery::ext::pointer_details::PtrOwnerManager, bitsery::ext::PolymorphicContext, bitsery::ext::StandardRTTI> const&)::'lambda'(bitsery::Deserializer<bitsery::InputBufferAdapter<String, FastConfig>, std::1::tuple<bitsery::ext::PointerLinkingContext, bitsery::ext::PolymorphicContext > >&, Person&)>(bitsery::ext::MemResourceBase, bitsery::ext::pointer_utils::PLCInfoDeserializer&, Person&, bitsery::ext::pointer_utils::PointerObjectExtensionBase<bitsery::ext::pointer_details::PtrOwnerManager, bitsery::ext::PolymorphicContext, bitsery::ext::StandardRTTI>&, void bitsery::Deserializer<bitsery::InputBufferAdapter<String, FastConfig>, std::1::tuple<bitsery::ext::PointerLinkingContext, bitsery::ext::PolymorphicContext > >::ext<Person, bitsery::ext::pointer_utils::PointerObjectExtensionBase<bitsery::ext::pointer_details::PtrOwnerManager, bitsery::ext::PolymorphicContext, bitsery::ext::StandardRTTI> >(Person&, bitsery::ext::pointer_utils::PointerObjectExtensionBase<bitsery::ext::pointer_details::PtrOwnerManager, bitsery::ext::PolymorphicContext, bitsery::ext::StandardRTTI> const&)::'lambda'(bitsery::Deserializer<bitsery::InputBufferAdapter<String, FastConfig>, std::1::tuple<bitsery::ext::PointerLinkingContext, bitsery::ext::PolymorphicContext > >&, Person&)&&, std::1::integral_constant<bool, true>, std::__1::integral_constant<bitsery::ext::PointerOwnershipType, (bitsery::ext::PointerOwnershipType)1>) const::'lambda0'(std::1::shared_ptr const&)>(Person&, bitsery::ext::pointer_utils::PointerObjectExtensionBase<bitsery::ext::pointer_details::PtrOwnerManager, bitsery::ext::PolymorphicContext, bitsery::ext::StandardRTTI>, void bitsery::Deserializer<bitsery::InputBufferAdapter<String, FastConfig>, std::1::tuple<bitsery::ext::PointerLinkingContext, bitsery::ext::PolymorphicContext > >::ext<Person, bitsery::ext::pointer_utils::PointerObjectExtensionBase<bitsery::ext::pointer_details::PtrOwnerManager, bitsery::ext::PolymorphicContext, bitsery::ext::StandardRTTI> >(Person&, bitsery::ext::pointer_utils::PointerObjectExtensionBase<bitsery::ext::pointer_details::PtrOwnerManager, bitsery::ext::PolymorphicContext, bitsery::ext::StandardRTTI> const&)::'lambda'(bitsery::Deserializer<bitsery::InputBufferAdapter<String, FastConfig>, std::1::tuple<bitsery::ext::PointerLinkingContext, bitsery::ext::PolymorphicContext > >&, Person&), void bitsery::ext::pointer_utils::PointerObjectExtensionBase<bitsery::ext::pointer_details::PtrOwnerManager, bitsery::ext::PolymorphicContext, bitsery::ext::StandardRTTI>::deserializeImpl<bitsery::Deserializer<bitsery::InputBufferAdapter<String, FastConfig>, std::1::tuple<bitsery::ext::PointerLinkingContext, bitsery::ext::PolymorphicContext > >, Person*, void bitsery::Deserializer<bitsery::InputBufferAdapter<String, FastConfig>, std::1::tuple<bitsery::ext::PointerLinkingContext, bitsery::ext::PolymorphicContext > >::ext<Person, bitsery::ext::pointer_utils::PointerObjectExtensionBase<bitsery::ext::pointer_details::PtrOwnerManager, bitsery::ext::PolymorphicContext, bitsery::ext::StandardRTTI> >(Person&, bitsery::ext::pointer_utils::PointerObjectExtensionBase<bitsery::ext::pointer_details::PtrOwnerManager, bitsery::ext::PolymorphicContext, bitsery::ext::StandardRTTI> const&)::'lambda'(bitsery::Deserializer<bitsery::InputBufferAdapter<String, FastConfig>, std::1::tuple<bitsery::ext::PointerLinkingContext, bitsery::ext::PolymorphicContext > >&, Person&)>(bitsery::ext::MemResourceBase, bitsery::ext::pointer_utils::PLCInfoDeserializer&, Person&, bitsery::ext::pointer_utils::PointerObjectExtensionBase<bitsery::ext::pointer_details::PtrOwnerManager, bitsery::ext::PolymorphicContext, bitsery::ext::StandardRTTI>&, void bitsery::Deserializer<bitsery::InputBufferAdapter<String, FastConfig>, std::1::tuple<bitsery::ext::PointerLinkingContext, bitsery::ext::PolymorphicContext > >::ext<Person, bitsery::ext::pointer_utils::PointerObjectExtensionBase<bitsery::ext::pointer_details::PtrOwnerManager, bitsery::ext::PolymorphicContext, bitsery::ext::StandardRTTI> >(Person&, bitsery::ext::pointer_utils::PointerObjectExtensionBase<bitsery::ext::pointer_details::PtrOwnerManager, bitsery::ext::PolymorphicContext, bitsery::ext::StandardRTTI> const&)::'lambda'(bitsery::Deserializer<bitsery::InputBufferAdapter<String, FastConfig>, std::1::tuple<bitsery::ext::PointerLinkingContext, bitsery::ext::PolymorphicContext > >&, Person&)&&, std::__1::integral_constant<bool, true>, std::1::integral_constant<bitsery::ext::PointerOwnershipType, (bitsery::ext::PointerOwnershipType)1>) const::'lambda0'(std::__1::shared_ptr const&)) const at /x/libraries/include/bitsery/ext/utils/polymorphism_utils.h:261

victorstewart commented 2 years ago

i solved this by creating my own RTTI type then my own pointer extension, but the fundamental issue remains

struct StaticRTTI {

   template<typename TBase>
   static size_t get(TBase& obj) 
    {
        return (size_t)static_type_info::getTypeIndex<TBase>();
    }

     template<typename TBase>
     static constexpr size_t get() 
     {
        return (size_t)static_type_info::getTypeIndex<TBase>();
     }

     template<typename TBase, typename TDerived>
     static constexpr TDerived* cast(TBase* obj) 
     {
        static_assert(!std::is_pointer<TDerived>::value, "");
        return dynamic_cast<TDerived*>(obj);
     }

     template<typename TBase>
     static constexpr bool isPolymorphic() 
     {
        return std::is_polymorphic<TBase>::value;
     }
  };

using PointerOwner = bitsery::ext::PointerOwnerBase<bitsery::ext::StaticRTTI>;
fraillt commented 1 year ago

Thanks for sharing!

I'll leave this ticket open, so people would know about it.