AddressSanitizer:在boost cpp_int上发生了堆栈缓冲区溢出。

7
我有以下代码示例,应该将std::array<uint8_t>转换为BigInt,即boost::multiprecision::cpp_int。我使用来自MSYS2的clang64 15.0.7(С++17)编译此代码。代码可以正常工作并将uint8_t数组转换为BigInt。
#include <string>
#include <iostream>
#include <boost/multiprecision/cpp_int.hpp>

using BigInt = boost::multiprecision::cpp_int;

const auto b = std::array<uint8_t, 16>{
    0x11, 0x22, 0x33, 0x44,
    0x11, 0x22, 0x33, 0x44,
    0x11, 0x22, 0x33, 0x44,
    0x11, 0x22, 0x33, 0x44
};

int main() {
    size_t shift = 0;
    auto initial = BigInt{};

    auto i = std::accumulate(
            b.cbegin(),
            b.cend(),
            initial,
            [&shift](const BigInt &acc, uint8_t it) {
                auto byte = BigInt{it};
                auto result = acc | (byte << shift);
                shift += CHAR_BIT;
                return result;
            }
    );

    std::cout << "Boost integer " << i << std::endl;
}

但是当我在我的CMakeFile中添加了ASAN选项:

add_compile_options(-fsanitize=address -fsanitize=undefined)
add_link_options(-fsanitize=address -fsanitize=undefined)

代码崩溃并记录了以下日志。我还发现boost cpp_int stack unwind crash,但这个问题只适用于GCC 7.1/8.1,并未在clang上得到确认。此外,像这样的崩溃在“简单”的“boost”表达式下也会在ASAN下发生,例如m_state = (data ^ key) & mask;,其中所有项都是cpp_int(对于GCC 7.3.3)。我在使用cpp_int时做错了什么?

==8032==ERROR: AddressSanitizer: stack-buffer-underflow on address 0x00f79ccfed58 at pc 0x7ff60fb5fb02 bp 0x00f79ccfe200 sp 0x00f79ccfe248
READ of size 8 at 0x00f79ccfed58 thread T0
    #0 0x7ff60fb5fb01 in void boost::multiprecision::backends::left_shift_byte<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>>(boost::multiprecision::backe
nds::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>&, unsigned __int128) C:/msys64/clang64/include/boost/multiprecision/cpp_int/bitwise.hpp:334:25
    #1 0x7ff60fb5f314 in std::__1::enable_if<!is_trivial_cpp_int<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>>::value, void>::type boost::multiprecision:
:backends::eval_left_shift<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>(boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::c
pp_int_check_type)0, std::__1::allocator<unsigned long long>>&, unsigned __int128) C:/msys64/clang64/include/boost/multiprecision/cpp_int/bitwise.hpp:500:7
    #2 0x7ff60fb5f002 in void boost::multiprecision::default_ops::eval_left_shift<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, boost::multiprecision::ba
ckends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, unsigned long long>(boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost:
:multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>&, boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>> const&, unsigned long long
) C:/msys64/clang64/include/boost/multiprecision/detail/default_ops.hpp:890:4
    #3 0x7ff60fb5ed30 in void boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_opt
ion)1>::do_assign_left_shift<boost::multiprecision::detail::expression<boost::multiprecision::detail::terminal, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__
1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>, void, void, void>, unsigned long long>(boost::multiprecision::detail::expression<boost::multiprecision::detail::terminal, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ul
l, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>, void, void, void> const&, unsigned long long const&, boost::multiprecision::detail::terminal const&) C:/msys64
/clang64/include/boost/multiprecision/number.hpp:1665:7
    #4 0x7ff60fb5964a in void boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_opt
ion)1>::do_assign<boost::multiprecision::detail::expression<boost::multiprecision::detail::shift_left, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::alloca
tor<unsigned long long>>, (boost::multiprecision::expression_template_option)1>, unsigned long long, void, void>>(boost::multiprecision::detail::expression<boost::multiprecision::detail::shift_left, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::mu
ltiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>, unsigned long long, void, void> const&, boost::multiprecision::detail::shift_left const&) C:/msys64/clang64/include/boost/m
ultiprecision/number.hpp:1616:7
    #5 0x7ff60fb5a979 in void boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_opt
ion)1>::do_assign<boost::multiprecision::detail::shift_left, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multipre
cision::expression_template_option)1>, unsigned long long, void, void>(boost::multiprecision::detail::expression<boost::multiprecision::detail::shift_left, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::m
ultiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>, unsigned long long, void, void> const&, std::__1::integral_constant<bool, true> const&) C:/msys64/clang64/include/boost/multiprecision/number.hpp:1222:7
    #6 0x7ff60fb5a719 in std::__1::enable_if<std::is_convertible<boost::multiprecision::detail::expression<boost::multiprecision::detail::shift_left, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multipr
ecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>, unsigned long long, void, void>::result_type, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer
_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>>::value, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boos
t::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>&>::type boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecisi
on::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>::operator=<boost::multiprecision::detail::shift_left, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integ
er_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>, unsigned long long, void, void>(boost::multiprecision::detail::expression<boost::multiprecision::detail::shift_left, boost::multiprecision::number
<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>, unsigned long long, void, void> const&) C:/msys64/c
lang64/include/boost/multiprecision/number.hpp:319:7
    #7 0x7ff60fb5a2db in boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1
>::number<boost::multiprecision::detail::shift_left, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::
expression_template_option)1>, unsigned long long, void, void>(boost::multiprecision::detail::expression<boost::multiprecision::detail::shift_left, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprec
ision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>, unsigned long long, void, void> const&, std::__1::enable_if<std::is_convertible<boost::multiprecision::detail::expression<boost::multiprecision::detail::shift_left, boost::mu
ltiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>, unsigned long long, void, void>
::result_type, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>>::value,
 void>::type*) C:/msys64/clang64/include/boost/multiprecision/number.hpp:440:13
    #8 0x7ff60fb58d7d in void boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_opt
ion)1>::do_bitwise_or<boost::multiprecision::detail::expression<boost::multiprecision::detail::shift_left, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::al
locator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>, unsigned long long, void, void>, boost::multiprecision::detail::shift_left>(boost::multiprecision::detail::expression<boost::multiprecision::detail::shift_left, boost::multiprecision::number<boost::multiprecision::b
ackends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>, unsigned long long, void, void> const&, boost::multiprecision::detail::shift
_left const&) C:/msys64/clang64/include/boost/multiprecision/number.hpp:2116:17
    #9 0x7ff60fb57f63 in void boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_opt
ion)1>::do_assign<boost::multiprecision::detail::expression<boost::multiprecision::detail::bitwise_or, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::alloca
tor<unsigned long long>>, (boost::multiprecision::expression_template_option)1>, boost::multiprecision::detail::expression<boost::multiprecision::detail::shift_left, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1,
 (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>, unsigned long long, void, void>, void, void>>(boost::multiprecision::detail::expression<boost::multiprecision::detail::bitwise_or, boost::multiprecision::nu
mber<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>, boost::multiprecision::detail::expression<boost
::multiprecision::detail::shift_left, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_temp
late_option)1>, unsigned long long, void, void>, void, void> const&, boost::multiprecision::detail::bitwise_or const&) C:/msys64/clang64/include/boost/multiprecision/number.hpp:1521:10
    #10 0x7ff60fb579b9 in void boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_op
tion)1>::do_assign<boost::multiprecision::detail::bitwise_or, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multipr
ecision::expression_template_option)1>, boost::multiprecision::detail::expression<boost::multiprecision::detail::shift_left, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_ty
pe)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>, unsigned long long, void, void>, void, void>(boost::multiprecision::detail::expression<boost::multiprecision::detail::bitwise_or, boost::multiprecision::number<boost::multiprecision::backends::cpp_
int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>, boost::multiprecision::detail::expression<boost::multiprecision::detail::shift_left, boos
t::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>, unsigned long long, void, 
void>, void, void> const&, std::__1::integral_constant<bool, true> const&) C:/msys64/clang64/include/boost/multiprecision/number.hpp:1222:7
    #11 0x7ff60fb56cf9 in std::__1::enable_if<std::is_convertible<boost::multiprecision::detail::expression<boost::multiprecision::detail::bitwise_or, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multip
recision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>, boost::multiprecision::detail::expression<boost::multiprecision::detail::shift_left, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0
ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>, unsigned long long, void, void>, void, void>::result_type, boost::multiprecision::number<boost::multiprecisi
on::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>>::value, boost::multiprecision::number<boost::multiprecision::backends::
cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>&>::type boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend
<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>::operator=<boost::multiprecision::detail::bitwise_or, boost::multiprecision::number<boost::multipreci
sion::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>, boost::multiprecision::detail::expression<boost::multiprecision::deta
il::shift_left, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>, unsign
ed long long, void, void>, void, void>(boost::multiprecision::detail::expression<boost::multiprecision::detail::bitwise_or, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_typ
e)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>, boost::multiprecision::detail::expression<boost::multiprecision::detail::shift_left, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision
::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>, unsigned long long, void, void>, void, void> const&) C:/msys64/clang64/include/boost/multiprecision/number.hpp:319:7
    #12 0x7ff60fb51c8c in boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)
1> std::__1::accumulate[abi:v15007]<unsigned char const*, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecis
ion::expression_template_option)1>, main::$_0>(unsigned char const*, unsigned char const*, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned
 long long>>, (boost::multiprecision::expression_template_option)1>, main::$_0) C:/msys64/clang64/include/c++/v1/__numeric/accumulate.h:45:16
    #13 0x7ff60fb5164c in main main.cpp:18:14
    #14 0x7ff60fb51315 in __tmainCRTStartup C:/M/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:272:15
    #15 0x7ff60fb51365 in .l_start C:/M/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:193:9
    #16 0x7ff9b7457613  (C:\WINDOWS\System32\KERNEL32.DLL+0x180017613)
    #17 0x7ff9b77026a0  (C:\WINDOWS\SYSTEM32\ntdll.dll+0x1800526a0)

Address 0x00f79ccfed58 is located in stack of thread T0 at offset 24 in frame
    #0 0x7ff60fb58bff in void boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_opt
ion)1>::do_bitwise_or<boost::multiprecision::detail::expression<boost::multiprecision::detail::shift_left, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::al
locator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>, unsigned long long, void, void>, boost::multiprecision::detail::shift_left>(boost::multiprecision::detail::expression<boost::multiprecision::detail::shift_left, boost::multiprecision::number<boost::multiprecision::b
ackends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>, (boost::multiprecision::expression_template_option)1>, unsigned long long, void, void> const&, boost::multiprecision::detail::shift
_left const&) C:/msys64/clang64/include/boost/multiprecision/number.hpp:2113

  This frame has 1 object(s):
    [32, 64) 'temp' (line 2116) <== Memory access at offset 24 underflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp, SEH and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-underflow C:/msys64/clang64/include/boost/multiprecision/cpp_int/bitwise.hpp:334:25 in void boost::multiprecision::backends::left_shift_byte<boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multip
recision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>>(boost::multiprecision::backends::cpp_int_backend<0ull, 0ull, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::__1::allocator<unsigned long long>>&, unsigned __int128)
Shadow bytes around the buggy address:
  0x027524f9fd50: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 01 f3 f3 f3
  0x027524f9fd60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x027524f9fd70: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 01 f2 01 f3
  0x027524f9fd80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x027524f9fd90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x027524f9fda0: 00 00 00 00 00 00 00 00 f1 f1 f1[f1]00 00 00 00
  0x027524f9fdb0: f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
  0x027524f9fdc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x027524f9fdd0: f1 f1 f1 f1 f8 f2 f2 f2 f8 f8 f2 f2 f8 f2 f2 f2
  0x027524f9fde0: 00 00 f2 f2 01 f2 f8 f8 f2 f2 f8 f2 f2 f2 f8 f2
  0x027524f9fdf0: f8 f2 f2 f2 f8 f2 f8 f8 f2 f2 f8 f2 f8 f8 f2 f2
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==8032==ABORTING

Process finished with exit code 1

1
我得到了不同的结果:https://godbolt.org/z/7Pd47aqox AddressSanitizer: stack-use-after-scope. 编译器在boost中发现错误:使用未初始化的值。 - Marek R
1
Boost bug。如果您要提交错误报告,请告诉我。也许我将在未来处理它。 - Marek R
2
顺便提一下,使用 uint8_tCHAR_BIT 有点可疑。在99.9%的平台上是可以的,但可能存在 CHAR_BIT 不是8位的平台,而 uint8_t 应该保持8位。 - Marek R
1
@MarekR 不是的。不过这是一个常见的陷阱。 - sehe
1
这里不需要使用CHAR_BIT。使用std::numeric_limits<uint8_t>::digits,根据uint8_t作为一个8位类型的定义,它必须是8(也没有填充)。C++实现中CHAR_BIT > 8(如一些DSP)很少能提供可选类型uint8_t,但我想理论上它可以通过原子RMW在必要时支持存储一个而不是非线程安全的加载+存储周围字节。@MarekR是正确的,不要使用其他具有不同语义含义的常量,只因为它恰好具有某个值。 - Peter Cordes
显示剩余2条评论
2个回答

10

表达式模板再次出现!

你的lambda表达式的结果不是BigInt。它是一个惰性引用操作数的表达式(大大简化了):

detail::expression<detail::bitwise_or, number<backends::cpp_int_backend<...>, et_on>,
                   detail::expression<detail::shift_left, number<backends::cpp_int_backend<...>, et_on>,
                                      unsigned long, void, void>,
                   void, void>;

修复问题的方法:

BigInt result = acc | (byte << shift); // look, no auto!

或者

std::accumulate(b.cbegin(), b.cend(), initial,
        [&shift](BigInt const& acc, uint8_t it)
-> BigInt { // trailing return

替代方案

更通用的解决方案是完全禁用您的BigInt表达式模板:

//using BigInt = boost::multiprecision::cpp_int;
using BigInt =
    boost::multiprecision::number<boost::multiprecision::cpp_int_backend<>, boost::multiprecision::et_off>;

1
感谢这个解决方案 using BigInt = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<>, boost::multiprecision::et_off>;,真的很厉害! - mblw

1

我在某处看到过std::accumulate有一些奇怪的问题。当我从你的代码中除去它并使用基于范围的for循环时,一切都正常:

int main() {
    size_t shift = 0;
    auto i = BigInt{};

    for(auto it : b) {
        auto byte = BigInt{it};
        i = i | (byte << shift);
        shift += CHAR_BIT;
    }

    std::cout << "Boost integer " << i << std::endl;
}

https://godbolt.org/z/5GjsTMEnY

我不知道为什么会发生这种情况。没有调查过我何时何地看到其他std::accumulate失败的情况。

我怀疑std::accumulate会导致一些额外的工作,从而暴露出boost::multiprecision::cpp_int中的一些错误。这些额外的工作在其他情况下引起了性能问题,我曾经看到过std::acumulate存在性能问题


你能告诉我们“某个地方”在哪里吗? - Jabberwocky
иҝҷжҳҜз”ұstd::accumulateеј•е…Ҙзҡ„жҖ§иғҪй—®йўҳпјҡhttps://youtu.be/mOSirVeP5lo?t=1391 - Marek R
我试图用代码制作MWP,其中我提到了m_state = (data ^ key) &amp; mask;。我在代码中也遇到了崩溃的情况。我通过将所有的boost::detail::expression转换为BigInt来修复它,在每个bigint操作之后。您可以查看工作代码std::accumulate https://godbolt.org/z/GG3To8dn1,其中包含这个怪癖(第26行)。关键是:`std::accumulate`是崩溃的一部分,但不是根本原因。我想知道是不是boost bigint有缺陷,我应该查找另一个bigint实现,还是我使用它不正确?我的错误是什么?只是几个操作的使用导致了崩溃吗? - mblw
我尝试使用代码制作MWP,其中我提到了m_state = (data ^ key) & mask;。 我在代码中也遇到了崩溃。 我通过将所有的boost::detail::expression转换为BigInt来修复它,在每个大整数操作之后。您可以查看带有此怪癖(第26行)的工作代码std::accumulate https://godbolt.org/z/GG3To8dn1。 要点是:std::accumulate是崩溃的一部分,但不是崩溃的根源。 我想知道boost bigint是否有缺陷,并且我应该查找另一个bigint实现还是我错误地使用它? 还有我的错误是什么? 只是使用几个操作就导致崩溃? - mblw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接