Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash in agi::Thesaurus::Thesaurus with Boost 1.85.0 and GCC >= 13 #137

Closed
mia-0 opened this issue Jun 1, 2024 · 1 comment
Closed

Crash in agi::Thesaurus::Thesaurus with Boost 1.85.0 and GCC >= 13 #137

mia-0 opened this issue Jun 1, 2024 · 1 comment

Comments

@mia-0
Copy link

mia-0 commented Jun 1, 2024

When building with Boost 1.85.0 and GCC >= 13 with optimization level 2 or greater, Aegisub as well as the thesaurus test case crash here:

offsets[line.substr(0, pos)] = static_cast<size_t>(atoi(line.c_str() + pos + 1));

The same does not occur with Clang 18 or lower optimization levels, so this might be a GCC bug.

System is openSUSE Tumbleweed 20240524.

Backtrace:

#0  0x00007ffff756c215 in __memcmp_avx2_movbe () from /lib64/libc.so.6
No symbol table info available.
#1  0x00000000005f3d80 in std::char_traits<char>::compare (__n=<optimized out>, __s2=<optimized out>, __s1=0x7fffffffd1a0 "Word 2")
    at /usr/include/c++/13/bits/char_traits.h:389
        __i = <optimized out>
#2  std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::compare (this=0x7fffffffd190, __str=...)
    at /usr/include/c++/13/bits/basic_string.h:3189
        __size = <optimized out>
        __osize = 7458172
        __len = <optimized out>
        __r = <optimized out>
#3  std::operator< <char, std::char_traits<char>, std::allocator<char> > (__rhs=..., __lhs=...) at /usr/include/c++/13/bits/basic_string.h:3832
No locals.
#4  std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::operator() (__y=..., __x=..., this=<optimized out>)
    at /usr/include/c++/13/bits/stl_function.h:408
No locals.
#5  boost::container::flat_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, void>::priv_subscript (mk=..., this=<optimized out>)
    at /usr/include/boost/container/flat_map.hpp:1649
        k = @0x7fffffffd190: {_M_dataplus = {<std::allocator<char>> = {<std::__new_allocator<char>> = {<No data fields>}, <No data fields>}, 
            _M_p = 0x7fffffffd1a0 "Word 2"}, _M_string_length = 6, {_M_local_buf = "Word 2\000\000\000\000\000\000\000\000\000", 
            _M_allocated_capacity = 55114705563479}}
        i = {m_ptr = 0x71cae8}
        k = <optimized out>
        i = <optimized out>
        m = <optimized out>
        v = <optimized out>
#6  boost::container::flat_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, void>::operator[] (x=..., this=<optimized out>) at /usr/include/boost/container/flat_map.hpp:753
No locals.
#7  agi::Thesaurus::Thesaurus (this=this@entry=0x7fffffffd4f0, dat_path=..., idx_path=...) at ../libaegisub/common/thesaurus.cpp:48
        pos = <optimized out>
        line = @0x7fffffffd288: {_M_dataplus = {<std::allocator<char>> = {<std::__new_allocator<char>> = {<No data fields>}, <No data fields>}, 
            _M_p = 0x7fffffffd298 "Word 2|53"}, _M_string_length = 9, {_M_local_buf = "Word 2|53\000\000\000\000\000\000", 
            _M_allocated_capacity = 3854010495827865431}}
        __for_range = @0x7fffffffd210: {<agi::line_iterator_base> = {stream = 0x7fffffffd358, 
            conv = {<std::__shared_ptr<agi::charset::IconvWrapper, (__gnu_cxx::_Lock_policy)2>> = {<std::__shared_ptr_access<agi::charset::IconvWrapper, (__gnu_cxx::_Lock_policy)2, false, false>> = {<No data fields>}, _M_ptr = 0x0, _M_refcount = {_M_pi = 0x0}}, <No data fields>}, cr = 13, lf = 10, 
            width = 1}, <std::iterator<std::input_iterator_tag, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>> = {<No data fields>}, value = {_M_dataplus = {<std::allocator<char>> = {<std::__new_allocator<char>> = {<No data fields>}, <No data fields>}, 
              _M_p = 0x7fffffffd248 "Word 1|6"}, _M_string_length = 8, {_M_local_buf = "Word 1|6\000\000\000\000\000\000\000", 
              _M_allocated_capacity = 3926066990354165591}}}
        __for_begin = {<agi::line_iterator_base> = {stream = 0x7fffffffd358, 
            conv = {<std::__shared_ptr<agi::charset::IconvWrapper, (__gnu_cxx::_Lock_policy)2>> = {<std::__shared_ptr_access<agi::charset::IconvWrapper, (__gnu_cxx::_Lock_policy)2, false, false>> = {<No data fields>}, _M_ptr = 0x0, _M_refcount = {_M_pi = 0x0}}, <No data fields>}, cr = 13, lf = 10, 
            width = 1}, <std::iterator<std::input_iterator_tag, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>> = {<No data fields>}, value = {_M_dataplus = {<std::allocator<char>> = {<std::__new_allocator<char>> = {<No data fields>}, <No data fields>}, 
              _M_p = 0x7fffffffd298 "Word 2|53"}, _M_string_length = 9, {_M_local_buf = "Word 2|53\000\000\000\000\000\000", 
              _M_allocated_capacity = 3854010495827865431}}}
        __for_end = {<agi::line_iterator_base> = {stream = 0x0, 
            conv = {<std::__shared_ptr<agi::charset::IconvWrapper, (__gnu_cxx::_Lock_policy)2>> = {<std::__shared_ptr_access<agi::charset::IconvWrapper, (__gnu_cxx::_Lock_policy)2, false, false>> = {<No data fields>}, _M_ptr = 0x0, _M_refcount = {_M_pi = 0x0}}, <No data fields>}, cr = 13, lf = 10, 
            width = 1}, <std::iterator<std::input_iterator_tag, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>> = {<No data fields>}, value = {_M_dataplus = {<std::allocator<char>> = {<std::__new_allocator<char>> = {<No data fields>}, <No data fields>}, 
              _M_p = 0x7fffffffd2e8 ""}, _M_string_length = 0, {_M_local_buf = '\000' <repeats 15 times>, _M_allocated_capacity = 0}}}
        idx_file = {file = {handle = 5}, region = {
            _M_t = {<std::__uniq_ptr_impl<boost::interprocess::mapped_region, std::default_delete<boost::interprocess::mapped_region> >> = {
                _M_t = {<std::_Tuple_impl<0, boost::interprocess::mapped_region*, std::default_delete<boost::interprocess::mapped_region> >> = {<std::_Tuple_impl<1, std::default_delete<boost::interprocess::mapped_region> >> = {<std::_Head_base<1, std::default_delete<boost::interprocess::mapped_region>, true>> = {
                        _M_head_impl = {<No data fields>}}, <No data fields>}, <std::_Head_base<0, boost::interprocess::mapped_region*, false>> = {
                      _M_head_impl = 0x71b300}, <No data fields>}, <No data fields>}}, <No data fields>}}, mapping_start = 0, file_size = 136}
        idx = {<boost::interprocess::basic_bufferbuf<char, std::char_traits<char> >> = {<std::basic_streambuf<char, std::char_traits<char> >> = {
              _vptr.basic_streambuf = 0x647408 <vtable for boost::interprocess::basic_ibufferstream<char, std::char_traits<char> >+24>, 
              _M_in_beg = 0x7ffff7fb7000 "UTF-8\n7\nWord 1|6\nWord 2|53\nWord 3|163\nToo few fields\nToo many fields|100|100\nNot a number|foo\nOut of range|195\nFurther out of range|196\n", 
              _M_in_cur = 0x7ffff7fb701b "Word 3|163\nToo few fields\nToo many fields|100|100\nNot a number|foo\nOut of range|195\nFurther out of range|196\n", _M_in_end = 0x7ffff7fb7088 "", _M_out_beg = 0x0, _M_out_cur = 0x0, _M_out_end = 0x0, _M_buf_locale = {static none = 0, static ctype = 1, static numeric = 2, 
                static collate = 4, static time = 8, static monetary = 16, static messages = 32, static all = 63, _M_impl = 0x6de920}}, m_mode = std::_S_in, 
            m_buffer = 0x7ffff7fb7000 "UTF-8\n7\nWord 1|6\nWord 2|53\nWord 3|163\nToo few fields\nToo many fields|100|100\nNot a number|foo\nOut of range|195\nFurther out of range|196\n", 
            m_length = 136}, <std::basic_istream<char, std::char_traits<char> >> = {<std::basic_ios<char, std::char_traits<char> >> = {<std::ios_base> = {
                _vptr.ios_base = 0x6474b8 <vtable for boost::interprocess::basic_ibufferstream<char, std::char_traits<char> >+200>, 
                static boolalpha = std::_S_boolalpha, static dec = std::_S_dec, static fixed = std::_S_fixed, static hex = std::_S_hex, 
                static internal = std::_S_internal, static left = std::_S_left, static oct = std::_S_oct, static right = std::_S_right, 
                static scientific = std::_S_scientific, static showbase = std::_S_showbase, static showpoint = std::_S_showpoint, 
                static showpos = std::_S_showpos, static skipws = std::_S_skipws, static unitbuf = std::_S_unitbuf, static uppercase = std::_S_uppercase, 
                static adjustfield = std::_S_adjustfield, static basefield = std::_S_basefield, static floatfield = std::_S_floatfield, 
                static badbit = std::_S_badbit, static eofbit = std::_S_eofbit, static failbit = std::_S_failbit, static goodbit = std::_S_goodbit, 
                static app = std::_S_app, static ate = std::_S_ate, static binary = std::_S_bin, static in = std::_S_in, static out = std::_S_out, 
                static trunc = std::_S_trunc, static __noreplace = std::_S_noreplace, static beg = std::_S_beg, static cur = std::_S_cur, 
                static end = std::_S_end, _M_precision = 6, _M_width = 0, _M_flags = 4098, _M_exception = std::_S_goodbit, 
                _M_streambuf_state = std::_S_goodbit, _M_callbacks = 0x0, _M_word_zero = {_M_pword = 0x0, _M_iword = 0}, _M_local_word = {{_M_pword = 0x0, 
                    _M_iword = 0}, {_M_pword = 0x0, _M_iword = 0}, {_M_pword = 0x0, _M_iword = 0}, {_M_pword = 0x0, _M_iword = 0}, {_M_pword = 0x0, 
                    _M_iword = 0}, {_M_pword = 0x0, _M_iword = 0}, {_M_pword = 0x0, _M_iword = 0}, {_M_pword = 0x0, _M_iword = 0}}, _M_word_size = 8, 
                _M_word = 0x7fffffffd3a8, _M_ios_locale = {static none = 0, static ctype = 1, static numeric = 2, static collate = 4, static time = 8, 
                  static monetary = 16, static messages = 32, static all = 63, _M_impl = 0x6de920}}, _M_tie = 0x0, _M_fill = 0 '\000', _M_fill_init = false, 
              _M_streambuf = 0x7fffffffd300, _M_ctype = 0x7ffff7a55920 <(anonymous namespace)::ctype_c>, _M_num_put = 0x7082f0, _M_num_get = 0x70c0a0}, 
            _vptr.basic_istream = 0x647490 <vtable for boost::interprocess::basic_ibufferstream<char, std::char_traits<char> >+160>, 
            _M_gcount = 0}, <No data fields>}
        encoding_name = {_M_dataplus = {<std::allocator<char>> = {<std::__new_allocator<char>> = {<No data fields>}, <No data fields>}, 
            _M_p = 0x7fffffffd160 "UTF-8"}, _M_string_length = 5, {_M_local_buf = "UTF-8\000\000\000\000\000\000\000\000\000\000", 
            _M_allocated_capacity = 241277752405}}
        unused_entry_count = {_M_dataplus = {<std::allocator<char>> = {<std::__new_allocator<char>> = {<No data fields>}, <No data fields>}, 
            _M_p = 0x7fffffffd180 "7"}, _M_string_length = 1, {_M_local_buf = "7", '\000' <repeats 14 times>, _M_allocated_capacity = 55}}
        idx_file = <optimized out>
        idx = <optimized out>
        encoding_name = <optimized out>
        unused_entry_count = <optimized out>
        line = <optimized out>
        __for_range = <optimized out>
        __for_begin = <optimized out>
        __for_end = <optimized out>
        pos = <optimized out>
#8  0x000000000052270d in lagi_thes_parse_Test::TestBody (this=<optimized out>) at /usr/include/c++/13/bits/basic_string.tcc:242
No locals.
#9  0x000000000057ba3f in testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void> (location=0x6103c1 "the test body", 
    method=<optimized out>, object=0x71cfd0) at ../subprojects/googletest-release-1.8.1/googletest/src/gtest.cc:2424
No locals.
#10 testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void> (object=object@entry=0x71cfd0, method=<optimized out>, 
    location=location@entry=0x6103c1 "the test body") at ../subprojects/googletest-release-1.8.1/googletest/src/gtest.cc:2479
No locals.
#11 0x000000000056faeb in testing::Test::Run (this=0x71cfd0) at ../subprojects/googletest-release-1.8.1/googletest/src/gtest.cc:2517
        impl = 0x6de680
        impl = <optimized out>
#12 testing::Test::Run (this=0x71cfd0) at ../subprojects/googletest-release-1.8.1/googletest/src/gtest.cc:2508
        impl = <optimized out>
#13 0x000000000056fcd0 in testing::TestInfo::Run (this=0x6f9ea0) at ../subprojects/googletest-release-1.8.1/googletest/src/gtest.cc:2693
        impl = 0x6de680
        repeater = 0x6de5c0
        start = 1717237242890
        test = 0x71cfd0
#14 0x000000000056fe3c in testing::TestInfo::Run (this=<optimized out>) at ../subprojects/googletest-release-1.8.1/googletest/src/gtest.cc:2668
        impl = <optimized out>
        repeater = <optimized out>
        start = <optimized out>
        test = <optimized out>
#15 testing::TestCase::Run (this=0x6f9fb0) at ../subprojects/googletest-release-1.8.1/googletest/src/gtest.cc:2811
        i = 0
        impl = 0x6de680
        repeater = 0x6de5c0
        start = 1717237242890
#16 0x0000000000572a70 in testing::TestCase::Run (this=<optimized out>) at ../subprojects/googletest-release-1.8.1/googletest/src/gtest.cc:2797
        impl = <optimized out>
        repeater = <optimized out>
        start = <optimized out>
        impl = <optimized out>
        repeater = <optimized out>
        start = <optimized out>
        i = <optimized out>
#17 testing::internal::UnitTestImpl::RunAllTests (this=<optimized out>) at ../subprojects/googletest-release-1.8.1/googletest/src/gtest.cc:5177
        test_index = 23
        start = 1717237242728
        i = 0
        gtest_is_initialized_before_run_all_tests = true
        in_subprocess_for_death_test = <optimized out>
        should_shard = <optimized out>
        has_tests_to_run = true
        failed = <optimized out>
        repeater = <optimized out>
        repeat = <optimized out>
        forever = <optimized out>
#18 0x000000000057bebf in testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool> (
    location=0x627160 "auxiliary test code (environments or event listeners)", method=<optimized out>, object=0x6de680)
    at ../subprojects/googletest-release-1.8.1/googletest/src/gtest.cc:2424
No locals.
#19 testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool> (object=0x6de680, method=<optimized out>, 
    location=location@entry=0x627160 "auxiliary test code (environments or event listeners)")
    at ../subprojects/googletest-release-1.8.1/googletest/src/gtest.cc:2479
No locals.
#20 0x000000000056ffc2 in testing::UnitTest::Run (this=0x6cb220 <testing::UnitTest::GetInstance()::instance>)
    at ../subprojects/googletest-release-1.8.1/googletest/src/gtest.cc:4786
        in_death_test_child_process = <optimized out>
        premature_exit_file = {premature_exit_filepath_ = {
            _M_dataplus = {<std::allocator<char>> = {<std::__new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x7fffffffd740 ""}, 
            _M_string_length = 0, {_M_local_buf = "\000\327\377\377\377\177\000\000&#W\000\000\000\000", _M_allocated_capacity = 140737488344832}}}
#21 0x0000000000439bd0 in RUN_ALL_TESTS () at ../subprojects/googletest-release-1.8.1/googletest/include/gtest/gtest.h:2341
No locals.
#22 main (argc=<optimized out>, argv=0x7fffffffd8f8) at ../tests/support/main.cpp:37
        retval = <optimized out>
@mia-0
Copy link
Author

mia-0 commented Jun 1, 2024

Is there a genuine need to use Boost’s flat_map here, as opposed to just std::map?
Performance-wise it doesn’t seem to matter in practice which implementation is used, so even if this is just a bug in either GCC or Boost, I would suggest replacing it.

0tkl pushed a commit to 0tkl/Aegisub that referenced this issue Jan 2, 2025
…tingTools#252)

I do not see a reason to prefer the flat_map implementation,
and it’s causing crashes when compiled with GCC >= 13 and
Boost 1.85.0 at optimization level 2 or higher.

Whether or not this is a bug in GCC, or Boost hitting a case of
undefined behavior, avoiding it altogether doesn’t seem to hurt.

Fixes arch1t3cht#137

Co-authored-by: Mia Herkt <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant