marzer / tomlplusplus

Header-only TOML config file parser and serializer for C++17.
https://marzer.github.io/tomlplusplus/
MIT License
1.47k stars 141 forks source link

aarch64-linux-gnu-g++ version 7.5.0 crash with segmentation fault #197

Closed sagi-ottopia closed 10 months ago

sagi-ottopia commented 1 year ago

Environment

toml++ version and/or commit hash: 7eb2ffcc09f8e9890dc0b77ff8ab00fc53b1f2b8 v3.3.0

Compiler: aarch64-linux-gnu-g++ (Linaro GCC 7.5-2019.12) 7.5.0

C++ standard mode: c++17

Target arch: aarch64

Library configuration overrides:

Relevant compilation flags:

Describe the bug

While trying to build the examples with the following commands: compiler crashed with segmentation fault

Steps to reproduce (or a small repro code sample)

$ cmake -B build.gcc7 -DBUILD_EXAMPLES=1 -DCMAKE_CXX_COMPILER=/opt/toolchains/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-g++
$ cmake --build build.gcc7 --verbose

Additional information

image

marzer commented 1 year ago

Can you include the error logs as actual text, instead of an image?

sagi-ottopia commented 1 year ago

sure

[ 75%] Building CXX object examples/CMakeFiles/toml_merger.dir/toml_merger.cpp.o
In file included from /tmp/tomlplusplus/include/toml++/toml.h:69:0,
                 from /tmp/tomlplusplus/examples/toml_merger.cpp:9:
/tmp/tomlplusplus/include/toml++/impl/parser.inl: In member function ‘bool toml::v3::impl::utf8_reader<T>::read_next_block()’:
/tmp/tomlplusplus/include/toml++/impl/parser.inl:264:50: warning: requested alignment 32 is larger than 16 [-Wattributes]
    TOML_OVERALIGNED char raw_bytes[block_capacity];
                                                  ^
/tmp/tomlplusplus/include/toml++/impl/parser.inl: In function ‘toml::v3::ex::parse_result toml::v3::impl::do_parse_file(std::string_view)’:
/tmp/tomlplusplus/include/toml++/impl/parser.inl:3785:58: warning: requested alignment 32 is larger than 16 [-Wattributes]
   TOML_OVERALIGNED char file_buffer[sizeof(void*) * 1024u];
                                                          ^
In file included from /tmp/tomlplusplus/include/toml++/toml.h:48:0,
                 from /tmp/tomlplusplus/examples/toml_merger.cpp:9:
/tmp/tomlplusplus/include/toml++/impl/table.h: In instantiation of ‘toml::v3::table::do_for_each(Func&&, Table&&)::<lambda(auto:4&&)> [with auto:4 = toml::v3::table&; Func = {anonymous}::merge_left(toml::v3::table&, toml::v3::table&&)::<lambda(const toml::v3::key&, auto:13&&)>; Table = toml::v3::table&]’:
/opt/toolchains/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/aarch64-linux-gnu/include/c++/7.5.0/type_traits:2428:26:   required by substitution of ‘template<class _Fn, class ... _Args> static std::__result_of_success<decltype (declval<_Fn>()((declval<_Args>)()...)), std::__invoke_other> std::__result_of_other_impl::_S_test(int) [with _Fn = toml::v3::table::do_for_each(Func&&, Table&&) [with Func = {anonymous}::merge_left(toml::v3::table&, toml::v3::table&&)::<lambda(const toml::v3::key&, auto:13&&)>; Table = toml::v3::table&]::<lambda(auto:4&&)>&&; _Args = {toml::v3::table&}]’
/opt/toolchains/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/aarch64-linux-gnu/include/c++/7.5.0/type_traits:2439:55:   required from ‘struct std::__result_of_impl<false, false, toml::v3::table::do_for_each(Func&&, Table&&) [with Func = {anonymous}::merge_left(toml::v3::table&, toml::v3::table&&)::<lambda(const toml::v3::key&, auto:13&&)>; Table = toml::v3::table&]::<lambda(auto:4&&)>&&, toml::v3::table&>’
/opt/toolchains/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/aarch64-linux-gnu/include/c++/7.5.0/type_traits:2444:12:   required from ‘struct std::__invoke_result<toml::v3::table::do_for_each(Func&&, Table&&) [with Func = {anonymous}::merge_left(toml::v3::table&, toml::v3::table&&)::<lambda(const toml::v3::key&, auto:13&&)>; Table = toml::v3::table&]::<lambda(auto:4&&)>&&, toml::v3::table&>’
/opt/toolchains/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/aarch64-linux-gnu/include/c++/7.5.0/type_traits:2845:12:   [ skipping 2 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/tmp/tomlplusplus/include/toml++/impl/node.h:735:37:   required from ‘constexpr const bool toml::v3::node::can_visit<toml::v3::table::do_for_each(Func&&, Table&&) [with Func = {anonymous}::merge_left(toml::v3::table&, toml::v3::table&&)::<lambda(const toml::v3::key&, auto:13&&)>; Table = toml::v3::table&]::<lambda(auto:4&&)>&&, toml::v3::node&, toml::v3::table>’
/tmp/tomlplusplus/include/toml++/impl/node.h:765:49:   required from ‘constexpr const bool toml::v3::node::visit_is_nothrow_one<toml::v3::table::do_for_each(Func&&, Table&&) [with Func = {anonymous}::merge_left(toml::v3::table&, toml::v3::table&&)::<lambda(const toml::v3::key&, auto:13&&)>; Table = toml::v3::table&]::<lambda(auto:4&&)>&&, toml::v3::node&, toml::v3::table>’
/tmp/tomlplusplus/include/toml++/impl/node.h:768:44:   required from ‘constexpr const bool toml::v3::node::visit_is_nothrow<toml::v3::table::do_for_each(Func&&, Table&&) [with Func = {anonymous}::merge_left(toml::v3::table&, toml::v3::table&&)::<lambda(const toml::v3::key&, auto:13&&)>; Table = toml::v3::table&]::<lambda(auto:4&&)>&&, toml::v3::node&>’
/tmp/tomlplusplus/include/toml++/impl/node.h:920:51:   required from ‘decltype(auto) toml::v3::node::visit(Func&&) & [with Func = toml::v3::table::do_for_each(Func&&, Table&&) [with Func = {anonymous}::merge_left(toml::v3::table&, toml::v3::table&&)::<lambda(const toml::v3::key&, auto:13&&)>; Table = toml::v3::table&]::<lambda(auto:4&&)>]’
/tmp/tomlplusplus/include/toml++/impl/table.h:897:16:   required from ‘static void toml::v3::table::do_for_each(Func&&, Table&&) [with Func = {anonymous}::merge_left(toml::v3::table&, toml::v3::table&&)::<lambda(const toml::v3::key&, auto:13&&)>; Table = toml::v3::table&]’
/tmp/tomlplusplus/include/toml++/impl/table.h:1042:15:   required from ‘toml::v3::table& toml::v3::table::for_each(Func&&) & [with Func = {anonymous}::merge_left(toml::v3::table&, toml::v3::table&&)::<lambda(const toml::v3::key&, auto:13&&)>]’
/tmp/tomlplusplus/examples/toml_merger.cpp:78:5:   required from here
/tmp/tomlplusplus/include/toml++/impl/table.h:912:44: internal compiler error: Segmentation fault
           visitor)(static_cast<const key&>(kvp.first), static_cast<value_ref>(v)));
                                            ^~~
Please submit a full bug report,
with preprocessed source if appropriate.
See <https://gcc.gnu.org/bugs/> for instructions.
gmake[2]: *** [examples/CMakeFiles/toml_merger.dir/build.make:76: examples/CMakeFiles/toml_merger.dir/toml_merger.cpp.o] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:354: examples/CMakeFiles/toml_merger.dir/all] Error 2
gmake: *** [Makefile:156: all] Error 2
marzer commented 1 year ago

Ah yup, I've had trouble with other older versions of GCC with over-alignment in the past, looks like more of the same. Should be easy to address, thanks for the report :)

sagi-ottopia commented 1 year ago

Thank you for the quick response, currently I can't upgrade the compiler version that I use on that platform so a fix will be very helpful

marzer commented 1 year ago

@sagi-ottopia I've just realized that I mis-read the error log and this isn't actually to do with over-alignment at all, but the template machinery that makes table::for_each() work. It might just be an ICE with that particular instantiation in the toml_merger example, and not actually the library itself; can you tell me if the simple_parser example compiles OK?

sagi-ottopia commented 1 year ago

Yes, simple_parser compiles OK. but I started to compile the examples code because when I'm compiling my code which uses the library this particular compiler crashed as well.

marzer commented 1 year ago

Ah, OK, I see. Well I'll try to come up with a workaround but it might ultimately be the case that GCC 7 is a bit too broken - the lowest I'm able to easily test with these days is GCC 8.

damirbarr commented 1 year ago

Hi @marzer Is there anything new with this issue?

marzer commented 1 year ago

@damirbarr are you also experiencing the same issue? If so, which specific version of GCC and target environment, the same one as @sagi-ottopia?

damirbarr commented 1 year ago

@marzer yes, the same one. I applied the following patch and was able to work around this issue. Now I'm compiling both with gcc-7 and gcc-10.

tomlplusplus-fix.zip

All my unit tests pass and I'm able to compile everything. The issue is that I'll need to create my own Conan package with this workaround

marzer commented 1 year ago

I applied the following patch and was able to work around this issue.

Hmmn, interesting. A worrying factor - a bool (or bool-convertible) return result of false from the for_each() callback is supposed to stop the iteration; your workaround deletes the branches responsible for handling that and always returns true, which effectively changes the API. Are you able to do some less destructive alterations, to find which specific construct in do_for_each triggers the ICE? My guess is the using return_type = ...; part, but I can't test at the moment.

If I can't modify for_each to support the bool propagation and have it still work on GCC 7 I will have to end support for GCC 7, unfortunately.

All my unit tests pass and I'm able to compile everything.

Looks like I am missing tests to ensure for_each() iteration does what it's supposed to do when you return false :P

marzer commented 1 year ago

@damirbarr In 2414d904a837aa2d0b795f086081df2d53b57d98 I have added some additional tests to check for the above

sagi-ottopia commented 1 year ago

Ah, OK, I see. Well I'll try to come up with a workaround but it might ultimately be the case that GCC 7 is a bit too broken - the lowest I'm able to easily test with these days is GCC 8.

  1. I can assist with checking on a relevant compiler and a machine. I have a cloud machine installed with Ubuntu 18.04 ARM64
  2. You can download the compiler from https://releases.linaro.org/components/toolchain/binaries/latest-7/aarch64-linux-gnu/

Sagi.

marzer commented 10 months ago

Alright folks, sorry it took me so long to get back to this. I wasn't able to come up a workaround that preserved the same API (returning false to early exit the loop) since I think GCC 7 is just overtly broken in this area, so instead I've added an error message and some #define escape hatches.