diff --git a/include/fast_io_core_impl/operations/writeimpl/basis.h b/include/fast_io_core_impl/operations/writeimpl/basis.h index 7910442ae..bbf259c02 100644 --- a/include/fast_io_core_impl/operations/writeimpl/basis.h +++ b/include/fast_io_core_impl/operations/writeimpl/basis.h @@ -511,7 +511,7 @@ inline constexpr void write_all_impl(outstmtype outsm, typename outstmtype::outp ::std::ptrdiff_t bfddiff{ed - curr}; ::std::ptrdiff_t itdiff{last - first}; if (itdiff < bfddiff) -#if __has_cpp_attribute(__gnu__::__may_alias__) +#if __has_cpp_attribute(likely) [[likely]] #endif { @@ -542,7 +542,7 @@ inline constexpr ::std::byte const *write_some_bytes_impl(outstmtype outsm, ::st ::std::ptrdiff_t bfddiff{ed - curr}; ::std::ptrdiff_t itdiff{last - first}; if (itdiff < bfddiff) -#if __has_cpp_attribute(__gnu__::__may_alias__) +#if __has_cpp_attribute(likely) [[likely]] #endif { diff --git a/include/fast_io_unit/string_impl/msvc_stl.h b/include/fast_io_unit/string_impl/msvc_stl.h index 45ac9144d..fc3f80db7 100644 --- a/include/fast_io_unit/string_impl/msvc_stl.h +++ b/include/fast_io_unit/string_impl/msvc_stl.h @@ -47,11 +47,95 @@ inline constexpr decltype(auto) hack_scary_val(::std::basic_string +inline _CONSTEXPR20 void msvc_stl_xstring_Apply_annotation(::std::basic_string::value_type const *const _First, + ::std::basic_string::size_type const _Capacity, + ::std::basic_string::size_type const _Old_size, + ::std::basic_string::size_type const _New_size) noexcept +{ +#if _HAS_CXX20 + if (_STD is_constant_evaluated()) + { + return; + } +#endif // _HAS_CXX20 + // Don't annotate small strings; only annotate on the heap. + if (_Capacity <= _Small_string_capacity || !_Asan_string_should_annotate) + { + return; + } + + // Note that `_Capacity`, `_Old_size`, and `_New_size` do not include the null terminator + void const *const _End = _First + _Capacity + 1; + void const *const _Old_last = _First + _Old_size + 1; + void const *const _New_last = _First + _New_size + 1; + + constexpr bool _Large_string_always_asan_aligned = + (_Container_allocation_minimum_asan_alignment<::std::basic_string>) >= _Asan_granularity; + + // for the non-aligned buffer options, the buffer must always have size >= 9 bytes, + // so it will always end at least one shadow memory section. + + _Asan_aligned_pointers _Aligned; + if constexpr (_Large_string_always_asan_aligned) + { + _Aligned = {_First, _STD _Get_asan_aligned_after(_End)}; + } + else + { + _Aligned = _STD _Get_asan_aligned_first_end(_First, _End); + } + void const *const _Old_fixed = _Aligned._Clamp_to_end(_Old_last); + void const *const _New_fixed = _Aligned._Clamp_to_end(_New_last); + + // --- always aligned case --- + // old state: + // [_First, _Old_last) valid + // [_Old_last, asan_aligned_after(_End)) poison + // new state: + // [_First, _New_last) valid + // [_New_last, asan_aligned_after(_End)) poison + + // --- sometimes non-aligned case --- + // old state: + // [_Aligned._First, _Old_fixed) valid + // [_Old_fixed, _Aligned._End) poison + // [_Aligned._End, _End) valid + // new state: + // [_Aligned._First, _New_fixed) valid + // [_New_fixed, _Aligned._End) poison + // [_Aligned._End, _End) valid + _CSTD __sanitizer_annotate_contiguous_container(_Aligned._First, _Aligned._End, _Old_fixed, _New_fixed); +} + +template +inline _CONSTEXPR20 void msvc_stl_xstring_Modify_annotation(T &_My_data, + ::std::basic_string::size_type const _Old_size, + ::std::basic_string::size_type const _New_size) const noexcept +{ + if (_Old_size == _New_size) + { + return; + } + + ::fast_io::details::string_hack::msvc_stl_xstring_Apply_annotation(_My_data._Myptr(), _My_data._Myres, _Old_size, _New_size); +} +#endif + template inline constexpr void set_end_ptr(T &str, typename T::value_type *ptr) noexcept { decltype(auto) scv{hack_scary_val(str)}; - scv._Mysize = static_cast<::std::size_t>(ptr - str.data()); + ::std::size_t newsize{static_cast<::std::size_t>(ptr - str.data())}; +#ifdef _ACTIVATE_STRING_ANNOTATION + ::fast_io::details::string_hack::sanitizer_annotate_contiguous_container(scv, scv._Mysize, newsize); +#endif + scv._Mysize = newsize; } template diff --git a/tests/0034.string/CMakeLists.txt b/tests/0034.string/CMakeLists.txt new file mode 100644 index 000000000..5418b934d --- /dev/null +++ b/tests/0034.string/CMakeLists.txt @@ -0,0 +1,2 @@ +add_executable(stringtest stringtest.cc) +add_test(stringtest stringtest) diff --git a/tests/0034.string/stringtest.cc b/tests/0034.string/stringtest.cc new file mode 100644 index 000000000..8ba44ccb1 --- /dev/null +++ b/tests/0034.string/stringtest.cc @@ -0,0 +1,8 @@ +#include +#include + +int main() +{ + ::std::string str("asfasfjaspofjaspofajsfpoasfsaf"); + ::fast_io::details::string_hack::set_end_ptr(str, str.data() + 5); // resize to 5 +} \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 17f3d35a5..6057421fc 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -2,4 +2,5 @@ set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_EXTENSIONS off) add_subdirectory(tests/0002.printscan) add_subdirectory(tests/0026.container) -add_subdirectory(tests/0033.legacy) \ No newline at end of file +add_subdirectory(tests/0033.legacy) +add_subdirectory(tests/0034.string) \ No newline at end of file