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

unique_ptr for ownership #7

Closed
hrobeers opened this issue Jan 5, 2015 · 7 comments
Closed

unique_ptr for ownership #7

hrobeers opened this issue Jan 5, 2015 · 7 comments
Labels
kind: enhancement/improvement solution: wontfix the issue will not be fixed (either it is impossible or deemed out of scope)

Comments

@hrobeers
Copy link

hrobeers commented Jan 5, 2015

Since you're using C++11, wouldn't it be better to manage object ownership using unique_ptr?

I will issue a pull request when I start using your library.

@nlohmann
Copy link
Owner

nlohmann commented Jan 5, 2015

As I wrote on Reddit:

There is no specific reason. I used pointers in order to limit the union's size. As the pointers are never exposed to the user, I never thought about using smart pointer. However, this could be a nice experiment. Do you know whether there are size overheads compared to raw pointers?

When there is no overhead (i.e. the size of the union will not grow), I would change the code myself.

@hrobeers
Copy link
Author

hrobeers commented Jan 6, 2015

Let's quote Reddit again ;)

[–]hrobeers 3 points 13 hours ago
If I'm not mistaken, there is no memory overhead because it just stores the raw pointer internally. But there could be a little runtime performance overhead when using another deleter. So when using the default deleter instead of manually call delete, there is no overhead.

[–]Splanky222 3 points 12 hours ago
No overhead with regular destructors. Unique_ptr is just a wrapper around a raw pointer so you can use RAII

@hrobeers
Copy link
Author

hrobeers commented Jan 6, 2015

This would also fix issue #11

@nlohmann
Copy link
Owner

nlohmann commented Jan 6, 2015

Alright - I understand that using unique_ptrs will be really nice. However, it seems as if the situation where pointers are inside a union makes the code quite difficult to port to unique_ptr in case we start swapping and moving. At lease this is what I take away from http://stackoverflow.com/questions/24713833/using-a-union-with-unique-ptr

I may need some more time to really understand the problem, but currently it seems as if I haven't understood all the implications yet. If you have any helping reference, I would be glad.

@hrobeers
Copy link
Author

hrobeers commented Jan 6, 2015

Yes it is indead true that smart pointers cannot be used inside unions. I missed the fact that you were heavily relying on a union, so using unique_ptrs is not possible.
When I start using your library, I'll try to find some other ways to manage memory.

Thanks for sharing this code, it looks really nice!

@nlohmann
Copy link
Owner

nlohmann commented Jan 6, 2015

Thanks! Until then, we have to rely on Valgrind that no memory is leaked ;-)

@cmaloney
Copy link

For the json::iterator and json::const_iterator you can use optional types (Like std::optional which was unfortunately dropped from c++14), as a replacement for the explicit new / delete calls. Also can give a slight speed boost because it eliminates a indirection. std::unique_ptr would work as well though / take less additional boilerplate.

@nlohmann nlohmann added the solution: wontfix the issue will not be fixed (either it is impossible or deemed out of scope) label Feb 22, 2015
t-b added a commit to t-b/json that referenced this issue Aug 30, 2019
Clang UBSAN complains with the following message when an empty std::valarray is passed in:

SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/valarray:571:14 in

2/2 Test nlohmann#68: test-regression_all ..............***Failed    4.68 sec
/usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/valarray:571:14: runtime error: reference binding to null pointer of type 'const do
uble'
    #0 0x6fbe57 in std::valarray<double>::operator[](unsigned long) const /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/valarray:
571:7
    nlohmann#1 0x6fbe57 in double const* std::begin<double>(std::valarray<double> const&) /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/v
alarray:1207
    nlohmann#2 0x6fbe57 in void nlohmann::detail::external_constructor<(nlohmann::detail::value_t)2>::construct<nlohmann::basic_json<std::map, std::vector, s
td::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_seri
alizer>, double, 0>(nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool
, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>&, std::valarray<double> const&) /home/firma/devel/json/include/nlohmann/deta
il/conversions/to_json.hpp:157
    nlohmann#3 0x5e3fe3 in void nlohmann::detail::to_json<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>
, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>, double, 0>(nlohmann::basic_json<std::map, std
::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohman
n::adl_serializer>&, std::valarray<double> const&) /home/firma/devel/json/include/nlohmann/detail/conversions/to_json.hpp:270:5
    nlohmann#4 0x5e3fe3 in decltype((to_json(fp, std::forward<std::valarray<double>&>(fp0))) , ((void)())) nlohmann::detail::to_json_fn::operator()<nlohmann:
:basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double
, std::allocator, nlohmann::adl_serializer>, std::valarray<double>&>(nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std
::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>&, std::valarray<double>&) c
onst /home/firma/devel/json/include/nlohmann/detail/conversions/to_json.hpp:334
    nlohmann#5 0x5e3fe3 in decltype((nlohmann::(anonymous namespace)::to_json(fp, std::forward<std::valarray<double>&>(fp0))) , ((void)())) nlohmann::adl_ser
ializer<std::valarray<double>, void>::to_json<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, st
d::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>, std::valarray<double>&>(nlohmann::basic_json<std:
:map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator
, nlohmann::adl_serializer>&, std::valarray<double>&) /home/firma/devel/json/include/nlohmann/adl_serializer.hpp:45
    nlohmann#6 0x5e3fe3 in nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool,
 long, unsigned long, double, std::allocator, nlohmann::adl_serializer>::basic_json<std::valarray<double>&, std::valarray<double>, 0>(std::valarray<d
ouble>&) /home/firma/devel/json/include/nlohmann/json.hpp:1257
    nlohmann#7 0x5e3fe3 in _DOCTEST_ANON_FUNC_2() /home/firma/devel/json/test/src/unit-regression.cpp:1377
    nlohmann#8 0x77313e in doctest::Context::run() /home/firma/devel/json/test/thirdparty/doctest/doctest.h:5938:21
    nlohmann#9 0x777ae0 in main /home/firma/devel/json/test/thirdparty/doctest/doctest.h:6016:71
    nlohmann#10 0x7fae220532e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202e0)
    nlohmann#11 0x4a6479 in _start (/home/firma/devel/json/build/test/test-regression+0x4a6479)

The important thing to note here is that a std::valarray is *not* a STL
container, so the usual containter and iterator semantics don't apply.

Therefore we have to check if the container is non-empty before.
t-b added a commit to t-b/json that referenced this issue Aug 30, 2019
Clang UBSAN complains here with

/usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/stl_bvector.h:158:20: runtime error: unsigned integer overflow: 0 - 1 cannot b
e represented in type 'unsigned int'
    #0 0x61f497 in std::_Bit_iterator_base::_M_bump_down() /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/stl_bvector.h:158:2
0
    nlohmann#1 0x61b7eb in bool nlohmann::detail::parser<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>,
 std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer> >::sax_parse_internal<nlohmann::detail::json_sa
x_dom_parser<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long,
 unsigned long, double, std::allocator, nlohmann::adl_serializer> > >(nlohmann::detail::json_sax_dom_parser<nlohmann::basic_json<std::map, std::vecto
r, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_
serializer> >*) /home/firma/devel/json/include/nlohmann/detail/input/json_sax.hpp
    nlohmann#2 0x611f33 in nlohmann::detail::parser<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std:
:allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer> >::parse(bool, nlohmann::basic_json<std::map, std::v
ector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::
adl_serializer>&) /home/firma/devel/json/include/nlohmann/detail/input/parser.hpp:116:13
    nlohmann#3 0x5d0522 in nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool,
 long, unsigned long, double, std::allocator, nlohmann::adl_serializer>::parse(nlohmann::detail::input_adapter&&, std::function<bool (int, nlohmann::
detail::parser<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, lon
g, unsigned long, double, std::allocator, nlohmann::adl_serializer> >::parse_event_t, nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic
_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>&)>, bool)/
home/firma/devel/json/include/nlohmann/json.hpp:6160:41
    nlohmann#4 0x5af340 in _DOCTEST_ANON_FUNC_84() /home/firma/devel/json/test/src/unit-msgpack.cpp:1321:19
    nlohmann#5 0x657d5e in doctest::Context::run() /home/firma/devel/json/test/thirdparty/doctest/doctest.h:5938:21
    nlohmann#6 0x65c700 in main /home/firma/devel/json/test/thirdparty/doctest/doctest.h:6016:71
    nlohmann#7 0x7f17952e32e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202e0)
    nlohmann#8 0x453f29 in _start (/home/firma/devel/json/build/test/test-msgpack+0x453f29)

so to make it happy we use the "official" way of denoting the maximum
value of a size_t instead of the shortcut by casting.
t-b added a commit to t-b/json that referenced this issue Aug 30, 2019
Clang UBSAN complains with the following message when an empty std::valarray is passed in:

SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/valarray:571:14 in

2/2 Test nlohmann#68: test-regression_all ..............***Failed    4.68 sec
/usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/valarray:571:14: runtime error: reference binding to null pointer of type 'const do
uble'
    #0 0x6fbe57 in std::valarray<double>::operator[](unsigned long) const /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/valarray:
571:7
    nlohmann#1 0x6fbe57 in double const* std::begin<double>(std::valarray<double> const&) /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/v
alarray:1207
    nlohmann#2 0x6fbe57 in void nlohmann::detail::external_constructor<(nlohmann::detail::value_t)2>::construct<nlohmann::basic_json<std::map, std::vector, s
td::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_seri
alizer>, double, 0>(nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool
, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>&, std::valarray<double> const&) /home/firma/devel/json/include/nlohmann/deta
il/conversions/to_json.hpp:157
    nlohmann#3 0x5e3fe3 in void nlohmann::detail::to_json<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>
, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>, double, 0>(nlohmann::basic_json<std::map, std
::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohman
n::adl_serializer>&, std::valarray<double> const&) /home/firma/devel/json/include/nlohmann/detail/conversions/to_json.hpp:270:5
    nlohmann#4 0x5e3fe3 in decltype((to_json(fp, std::forward<std::valarray<double>&>(fp0))) , ((void)())) nlohmann::detail::to_json_fn::operator()<nlohmann:
:basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double
, std::allocator, nlohmann::adl_serializer>, std::valarray<double>&>(nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std
::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>&, std::valarray<double>&) c
onst /home/firma/devel/json/include/nlohmann/detail/conversions/to_json.hpp:334
    nlohmann#5 0x5e3fe3 in decltype((nlohmann::(anonymous namespace)::to_json(fp, std::forward<std::valarray<double>&>(fp0))) , ((void)())) nlohmann::adl_ser
ializer<std::valarray<double>, void>::to_json<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, st
d::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>, std::valarray<double>&>(nlohmann::basic_json<std:
:map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator
, nlohmann::adl_serializer>&, std::valarray<double>&) /home/firma/devel/json/include/nlohmann/adl_serializer.hpp:45
    nlohmann#6 0x5e3fe3 in nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool,
 long, unsigned long, double, std::allocator, nlohmann::adl_serializer>::basic_json<std::valarray<double>&, std::valarray<double>, 0>(std::valarray<d
ouble>&) /home/firma/devel/json/include/nlohmann/json.hpp:1257
    nlohmann#7 0x5e3fe3 in _DOCTEST_ANON_FUNC_2() /home/firma/devel/json/test/src/unit-regression.cpp:1377
    nlohmann#8 0x77313e in doctest::Context::run() /home/firma/devel/json/test/thirdparty/doctest/doctest.h:5938:21
    nlohmann#9 0x777ae0 in main /home/firma/devel/json/test/thirdparty/doctest/doctest.h:6016:71
    nlohmann#10 0x7fae220532e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202e0)
    nlohmann#11 0x4a6479 in _start (/home/firma/devel/json/build/test/test-regression+0x4a6479)

The important thing to note here is that a std::valarray is *not* a STL
container, so the usual containter and iterator semantics don't apply.

Therefore we have to check if the container is non-empty before.
t-b added a commit to t-b/json that referenced this issue Aug 31, 2019
- Switch to clang-7
- Adapt PATH so that llvm-symbolizer can be found for useful stacktraces
- Adapt compile flags
  "-O0" ensures much faster compile times
  "-fno-sanitize-recover=all
  -fsanitize-recover=unsigned-integer-overflow" this fails the build on
  all issues except unsigned integer overflows. Not failing in this case
  is required in combination with the sanitizer suppression file as only
  recoverable errors can be suppressed.

The UBSAN suppression file ignores errors from stl_bvector.h (which
holds std::vector<bool>).

Clang reports that error as

SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/stl_bvector.h:158:20 in

      Start 34: test-deserialization_all
28/88 Test nlohmann#71: test-testsuites_default .............***Failed    0.32 sec
/usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/stl_bvector.h:158:20: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'unsigned int'
    #0 0x628f72 in std::_Bit_iterator_base::_M_bump_down() /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/stl_bvector.h:158:20
    nlohmann#1 0x628d16 in std::_Bit_iterator::operator--() /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/stl_bvector.h:251:7
    nlohmann#2 0x634aac in std::vector<bool, std::allocator<bool> >::pop_back() /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/stl_bvector.h:1010:7
    nlohmann#3 0x61eff0 in bool nlohmann::detail::parser<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer> >::sax_parse_internal<nlohmann::detail::json_sax_dom_parser<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer> > >(nlohmann::detail::json_sax_dom_parser<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer> >*) /home/firma/devel/json/include/nlohmann/detail/input/parser.hpp:439:28
    nlohmann#4 0x604864 in nlohmann::detail::parser<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer> >::parse(bool, nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>&) /home/firma/devel/json/include/nlohmann/detail/input/parser.hpp:116:13
    nlohmann#5 0x5f8079 in nlohmann::operator>>(std::istream&, nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>&) /home/firma/devel/json/include/nlohmann/json.hpp:6356:42
    nlohmann#6 0x5e1d92 in _DOCTEST_ANON_FUNC_21() /home/firma/devel/json/test/src/unit-testsuites.cpp:343:9
    nlohmann#7 0x7207fe in doctest::Context::run() /home/firma/devel/json/test/thirdparty/doctest/doctest.h:5938:21
    nlohmann#8 0x72681a in main /home/firma/devel/json/test/thirdparty/doctest/doctest.h:6016:71
    nlohmann#9 0x7f75d22362e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202e0)
    nlohmann#10 0x4c28b9 in _start (/home/firma/devel/json/build/test/test-testsuites+0x4c28b9)

The pop_back() in parser.hpp

      assert(not states.empty());
  ->  states.pop_back();

triggers the UBSAN report. But the assertion above ensure that we only
call pop_back() on an non-empty vector, therefore this is a STL library
bug and thus must be ignored for us.
t-b added a commit to t-b/json that referenced this issue Aug 31, 2019
Clang UBSAN complains with the following message when an empty std::valarray is passed in:

SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/valarray:571:14 in

2/2 Test nlohmann#68: test-regression_all ..............***Failed    4.68 sec
/usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/valarray:571:14: runtime error: reference binding to null pointer of type 'const do
uble'
    #0 0x6fbe57 in std::valarray<double>::operator[](unsigned long) const /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/valarray:
571:7
    nlohmann#1 0x6fbe57 in double const* std::begin<double>(std::valarray<double> const&) /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/v
alarray:1207
    nlohmann#2 0x6fbe57 in void nlohmann::detail::external_constructor<(nlohmann::detail::value_t)2>::construct<nlohmann::basic_json<std::map, std::vector, s
td::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_seri
alizer>, double, 0>(nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool
, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>&, std::valarray<double> const&) /home/firma/devel/json/include/nlohmann/deta
il/conversions/to_json.hpp:157
    nlohmann#3 0x5e3fe3 in void nlohmann::detail::to_json<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>
, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>, double, 0>(nlohmann::basic_json<std::map, std
::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohman
n::adl_serializer>&, std::valarray<double> const&) /home/firma/devel/json/include/nlohmann/detail/conversions/to_json.hpp:270:5
    nlohmann#4 0x5e3fe3 in decltype((to_json(fp, std::forward<std::valarray<double>&>(fp0))) , ((void)())) nlohmann::detail::to_json_fn::operator()<nlohmann:
:basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double
, std::allocator, nlohmann::adl_serializer>, std::valarray<double>&>(nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std
::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>&, std::valarray<double>&) c
onst /home/firma/devel/json/include/nlohmann/detail/conversions/to_json.hpp:334
    nlohmann#5 0x5e3fe3 in decltype((nlohmann::(anonymous namespace)::to_json(fp, std::forward<std::valarray<double>&>(fp0))) , ((void)())) nlohmann::adl_ser
ializer<std::valarray<double>, void>::to_json<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, st
d::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>, std::valarray<double>&>(nlohmann::basic_json<std:
:map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator
, nlohmann::adl_serializer>&, std::valarray<double>&) /home/firma/devel/json/include/nlohmann/adl_serializer.hpp:45
    nlohmann#6 0x5e3fe3 in nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool,
 long, unsigned long, double, std::allocator, nlohmann::adl_serializer>::basic_json<std::valarray<double>&, std::valarray<double>, 0>(std::valarray<d
ouble>&) /home/firma/devel/json/include/nlohmann/json.hpp:1257
    nlohmann#7 0x5e3fe3 in _DOCTEST_ANON_FUNC_2() /home/firma/devel/json/test/src/unit-regression.cpp:1377
    nlohmann#8 0x77313e in doctest::Context::run() /home/firma/devel/json/test/thirdparty/doctest/doctest.h:5938:21
    nlohmann#9 0x777ae0 in main /home/firma/devel/json/test/thirdparty/doctest/doctest.h:6016:71
    nlohmann#10 0x7fae220532e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202e0)
    nlohmann#11 0x4a6479 in _start (/home/firma/devel/json/build/test/test-regression+0x4a6479)

The important thing to note here is that a std::valarray is *not* a STL
container, so the usual containter and iterator semantics don't apply.

Therefore we have to check if the container is non-empty before.
t-b added a commit to t-b/json that referenced this issue Aug 31, 2019
- Switch to clang-7
- Adapt PATH so that llvm-symbolizer can be found for useful stacktraces
- Adapt compile flags
  "-O0" ensures much faster compile times
  "-fno-sanitize-recover=all
  -fsanitize-recover=unsigned-integer-overflow" this fails the build on
  all issues except unsigned integer overflows. Not failing in this case
  is required in combination with the sanitizer suppression file as only
  recoverable errors can be suppressed.

The UBSAN suppression file ignores errors from stl_bvector.h (which
holds std::vector<bool>).

Clang reports that error as

SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/stl_bvector.h:158:20 in

      Start 34: test-deserialization_all
28/88 Test nlohmann#71: test-testsuites_default .............***Failed    0.32 sec
/usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/stl_bvector.h:158:20: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'unsigned int'
    #0 0x628f72 in std::_Bit_iterator_base::_M_bump_down() /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/stl_bvector.h:158:20
    nlohmann#1 0x628d16 in std::_Bit_iterator::operator--() /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/stl_bvector.h:251:7
    nlohmann#2 0x634aac in std::vector<bool, std::allocator<bool> >::pop_back() /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/stl_bvector.h:1010:7
    nlohmann#3 0x61eff0 in bool nlohmann::detail::parser<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer> >::sax_parse_internal<nlohmann::detail::json_sax_dom_parser<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer> > >(nlohmann::detail::json_sax_dom_parser<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer> >*) /home/firma/devel/json/include/nlohmann/detail/input/parser.hpp:439:28
    nlohmann#4 0x604864 in nlohmann::detail::parser<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer> >::parse(bool, nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>&) /home/firma/devel/json/include/nlohmann/detail/input/parser.hpp:116:13
    nlohmann#5 0x5f8079 in nlohmann::operator>>(std::istream&, nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>&) /home/firma/devel/json/include/nlohmann/json.hpp:6356:42
    nlohmann#6 0x5e1d92 in _DOCTEST_ANON_FUNC_21() /home/firma/devel/json/test/src/unit-testsuites.cpp:343:9
    nlohmann#7 0x7207fe in doctest::Context::run() /home/firma/devel/json/test/thirdparty/doctest/doctest.h:5938:21
    nlohmann#8 0x72681a in main /home/firma/devel/json/test/thirdparty/doctest/doctest.h:6016:71
    nlohmann#9 0x7f75d22362e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202e0)
    nlohmann#10 0x4c28b9 in _start (/home/firma/devel/json/build/test/test-testsuites+0x4c28b9)

The pop_back() in parser.hpp

      assert(not states.empty());
  ->  states.pop_back();

triggers the UBSAN report. But the assertion above ensure that we only
call pop_back() on an non-empty vector, therefore this is a STL library
bug and thus must be ignored for us.
t-b added a commit to t-b/json that referenced this issue Aug 31, 2019
Clang UBSAN complains with the following message when an empty std::valarray is passed in:

SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/valarray:571:14 in

2/2 Test nlohmann#68: test-regression_all ..............***Failed    4.68 sec
/usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/valarray:571:14: runtime error: reference binding to null pointer of type 'const do
uble'
    #0 0x6fbe57 in std::valarray<double>::operator[](unsigned long) const /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/valarray:
571:7
    nlohmann#1 0x6fbe57 in double const* std::begin<double>(std::valarray<double> const&) /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/v
alarray:1207
    nlohmann#2 0x6fbe57 in void nlohmann::detail::external_constructor<(nlohmann::detail::value_t)2>::construct<nlohmann::basic_json<std::map, std::vector, s
td::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_seri
alizer>, double, 0>(nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool
, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>&, std::valarray<double> const&) /home/firma/devel/json/include/nlohmann/deta
il/conversions/to_json.hpp:157
    nlohmann#3 0x5e3fe3 in void nlohmann::detail::to_json<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>
, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>, double, 0>(nlohmann::basic_json<std::map, std
::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohman
n::adl_serializer>&, std::valarray<double> const&) /home/firma/devel/json/include/nlohmann/detail/conversions/to_json.hpp:270:5
    nlohmann#4 0x5e3fe3 in decltype((to_json(fp, std::forward<std::valarray<double>&>(fp0))) , ((void)())) nlohmann::detail::to_json_fn::operator()<nlohmann:
:basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double
, std::allocator, nlohmann::adl_serializer>, std::valarray<double>&>(nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std
::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>&, std::valarray<double>&) c
onst /home/firma/devel/json/include/nlohmann/detail/conversions/to_json.hpp:334
    nlohmann#5 0x5e3fe3 in decltype((nlohmann::(anonymous namespace)::to_json(fp, std::forward<std::valarray<double>&>(fp0))) , ((void)())) nlohmann::adl_ser
ializer<std::valarray<double>, void>::to_json<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, st
d::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>, std::valarray<double>&>(nlohmann::basic_json<std:
:map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator
, nlohmann::adl_serializer>&, std::valarray<double>&) /home/firma/devel/json/include/nlohmann/adl_serializer.hpp:45
    nlohmann#6 0x5e3fe3 in nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool,
 long, unsigned long, double, std::allocator, nlohmann::adl_serializer>::basic_json<std::valarray<double>&, std::valarray<double>, 0>(std::valarray<d
ouble>&) /home/firma/devel/json/include/nlohmann/json.hpp:1257
    nlohmann#7 0x5e3fe3 in _DOCTEST_ANON_FUNC_2() /home/firma/devel/json/test/src/unit-regression.cpp:1377
    nlohmann#8 0x77313e in doctest::Context::run() /home/firma/devel/json/test/thirdparty/doctest/doctest.h:5938:21
    nlohmann#9 0x777ae0 in main /home/firma/devel/json/test/thirdparty/doctest/doctest.h:6016:71
    nlohmann#10 0x7fae220532e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202e0)
    nlohmann#11 0x4a6479 in _start (/home/firma/devel/json/build/test/test-regression+0x4a6479)

The important thing to note here is that a std::valarray is *not* a STL
container, so the usual containter and iterator semantics don't apply.

Therefore we have to check if the container is non-empty before.
t-b added a commit to t-b/json that referenced this issue Sep 3, 2019
- Switch to clang-7
- Adapt PATH so that llvm-symbolizer can be found for useful stacktraces
- Adapt compile flags
  "-O0" ensures much faster compile times
  "-fno-sanitize-recover=all
  -fsanitize-recover=unsigned-integer-overflow" this fails the build on
  all issues except unsigned integer overflows. Not failing in this case
  is required in combination with the sanitizer suppression file as only
  recoverable errors can be suppressed.

The UBSAN suppression file ignores errors from stl_bvector.h (which
holds std::vector<bool>).

Clang reports that error as

SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/stl_bvector.h:158:20 in

      Start 34: test-deserialization_all
28/88 Test nlohmann#71: test-testsuites_default .............***Failed    0.32 sec
/usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/stl_bvector.h:158:20: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'unsigned int'
    #0 0x628f72 in std::_Bit_iterator_base::_M_bump_down() /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/stl_bvector.h:158:20
    nlohmann#1 0x628d16 in std::_Bit_iterator::operator--() /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/stl_bvector.h:251:7
    nlohmann#2 0x634aac in std::vector<bool, std::allocator<bool> >::pop_back() /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/stl_bvector.h:1010:7
    nlohmann#3 0x61eff0 in bool nlohmann::detail::parser<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer> >::sax_parse_internal<nlohmann::detail::json_sax_dom_parser<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer> > >(nlohmann::detail::json_sax_dom_parser<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer> >*) /home/firma/devel/json/include/nlohmann/detail/input/parser.hpp:439:28
    nlohmann#4 0x604864 in nlohmann::detail::parser<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer> >::parse(bool, nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>&) /home/firma/devel/json/include/nlohmann/detail/input/parser.hpp:116:13
    nlohmann#5 0x5f8079 in nlohmann::operator>>(std::istream&, nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>&) /home/firma/devel/json/include/nlohmann/json.hpp:6356:42
    nlohmann#6 0x5e1d92 in _DOCTEST_ANON_FUNC_21() /home/firma/devel/json/test/src/unit-testsuites.cpp:343:9
    nlohmann#7 0x7207fe in doctest::Context::run() /home/firma/devel/json/test/thirdparty/doctest/doctest.h:5938:21
    nlohmann#8 0x72681a in main /home/firma/devel/json/test/thirdparty/doctest/doctest.h:6016:71
    nlohmann#9 0x7f75d22362e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202e0)
    nlohmann#10 0x4c28b9 in _start (/home/firma/devel/json/build/test/test-testsuites+0x4c28b9)

The pop_back() in parser.hpp

      assert(not states.empty());
  ->  states.pop_back();

triggers the UBSAN report. But the assertion above ensure that we only
call pop_back() on an non-empty vector, therefore this is a STL library
bug and thus must be ignored for us.
t-b added a commit to t-b/json that referenced this issue Sep 3, 2019
Clang UBSAN complains with the following message when an empty std::valarray is passed in:

SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/valarray:571:14 in

2/2 Test nlohmann#68: test-regression_all ..............***Failed    4.68 sec
/usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/valarray:571:14: runtime error: reference binding to null pointer of type 'const do
uble'
    #0 0x6fbe57 in std::valarray<double>::operator[](unsigned long) const /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/valarray:
571:7
    nlohmann#1 0x6fbe57 in double const* std::begin<double>(std::valarray<double> const&) /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/v
alarray:1207
    nlohmann#2 0x6fbe57 in void nlohmann::detail::external_constructor<(nlohmann::detail::value_t)2>::construct<nlohmann::basic_json<std::map, std::vector, s
td::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_seri
alizer>, double, 0>(nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool
, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>&, std::valarray<double> const&) /home/firma/devel/json/include/nlohmann/deta
il/conversions/to_json.hpp:157
    nlohmann#3 0x5e3fe3 in void nlohmann::detail::to_json<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>
, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>, double, 0>(nlohmann::basic_json<std::map, std
::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohman
n::adl_serializer>&, std::valarray<double> const&) /home/firma/devel/json/include/nlohmann/detail/conversions/to_json.hpp:270:5
    nlohmann#4 0x5e3fe3 in decltype((to_json(fp, std::forward<std::valarray<double>&>(fp0))) , ((void)())) nlohmann::detail::to_json_fn::operator()<nlohmann:
:basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double
, std::allocator, nlohmann::adl_serializer>, std::valarray<double>&>(nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std
::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>&, std::valarray<double>&) c
onst /home/firma/devel/json/include/nlohmann/detail/conversions/to_json.hpp:334
    nlohmann#5 0x5e3fe3 in decltype((nlohmann::(anonymous namespace)::to_json(fp, std::forward<std::valarray<double>&>(fp0))) , ((void)())) nlohmann::adl_ser
ializer<std::valarray<double>, void>::to_json<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, st
d::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>, std::valarray<double>&>(nlohmann::basic_json<std:
:map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator
, nlohmann::adl_serializer>&, std::valarray<double>&) /home/firma/devel/json/include/nlohmann/adl_serializer.hpp:45
    nlohmann#6 0x5e3fe3 in nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool,
 long, unsigned long, double, std::allocator, nlohmann::adl_serializer>::basic_json<std::valarray<double>&, std::valarray<double>, 0>(std::valarray<d
ouble>&) /home/firma/devel/json/include/nlohmann/json.hpp:1257
    nlohmann#7 0x5e3fe3 in _DOCTEST_ANON_FUNC_2() /home/firma/devel/json/test/src/unit-regression.cpp:1377
    nlohmann#8 0x77313e in doctest::Context::run() /home/firma/devel/json/test/thirdparty/doctest/doctest.h:5938:21
    nlohmann#9 0x777ae0 in main /home/firma/devel/json/test/thirdparty/doctest/doctest.h:6016:71
    nlohmann#10 0x7fae220532e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202e0)
    nlohmann#11 0x4a6479 in _start (/home/firma/devel/json/build/test/test-regression+0x4a6479)

The important thing to note here is that a std::valarray is *not* a STL
container, so the usual containter and iterator semantics don't apply.

Therefore we have to check if the container is non-empty before.
OmnipotentEntity pushed a commit to OmnipotentEntity/json that referenced this issue Oct 20, 2019
- Switch to clang-7
- Adapt PATH so that llvm-symbolizer can be found for useful stacktraces
- Adapt compile flags
  "-O0" ensures much faster compile times
  "-fno-sanitize-recover=all
  -fsanitize-recover=unsigned-integer-overflow" this fails the build on
  all issues except unsigned integer overflows. Not failing in this case
  is required in combination with the sanitizer suppression file as only
  recoverable errors can be suppressed.

The UBSAN suppression file ignores errors from stl_bvector.h (which
holds std::vector<bool>).

Clang reports that error as

SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/stl_bvector.h:158:20 in

      Start 34: test-deserialization_all
28/88 Test nlohmann#71: test-testsuites_default .............***Failed    0.32 sec
/usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/stl_bvector.h:158:20: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'unsigned int'
    #0 0x628f72 in std::_Bit_iterator_base::_M_bump_down() /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/stl_bvector.h:158:20
    nlohmann#1 0x628d16 in std::_Bit_iterator::operator--() /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/stl_bvector.h:251:7
    nlohmann#2 0x634aac in std::vector<bool, std::allocator<bool> >::pop_back() /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/stl_bvector.h:1010:7
    nlohmann#3 0x61eff0 in bool nlohmann::detail::parser<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer> >::sax_parse_internal<nlohmann::detail::json_sax_dom_parser<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer> > >(nlohmann::detail::json_sax_dom_parser<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer> >*) /home/firma/devel/json/include/nlohmann/detail/input/parser.hpp:439:28
    nlohmann#4 0x604864 in nlohmann::detail::parser<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer> >::parse(bool, nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>&) /home/firma/devel/json/include/nlohmann/detail/input/parser.hpp:116:13
    nlohmann#5 0x5f8079 in nlohmann::operator>>(std::istream&, nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>&) /home/firma/devel/json/include/nlohmann/json.hpp:6356:42
    nlohmann#6 0x5e1d92 in _DOCTEST_ANON_FUNC_21() /home/firma/devel/json/test/src/unit-testsuites.cpp:343:9
    nlohmann#7 0x7207fe in doctest::Context::run() /home/firma/devel/json/test/thirdparty/doctest/doctest.h:5938:21
    nlohmann#8 0x72681a in main /home/firma/devel/json/test/thirdparty/doctest/doctest.h:6016:71
    nlohmann#9 0x7f75d22362e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202e0)
    nlohmann#10 0x4c28b9 in _start (/home/firma/devel/json/build/test/test-testsuites+0x4c28b9)

The pop_back() in parser.hpp

      assert(not states.empty());
  ->  states.pop_back();

triggers the UBSAN report. But the assertion above ensure that we only
call pop_back() on an non-empty vector, therefore this is a STL library
bug and thus must be ignored for us.
OmnipotentEntity pushed a commit to OmnipotentEntity/json that referenced this issue Oct 20, 2019
Clang UBSAN complains with the following message when an empty std::valarray is passed in:

SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/valarray:571:14 in

2/2 Test nlohmann#68: test-regression_all ..............***Failed    4.68 sec
/usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/valarray:571:14: runtime error: reference binding to null pointer of type 'const do
uble'
    #0 0x6fbe57 in std::valarray<double>::operator[](unsigned long) const /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/valarray:
571:7
    nlohmann#1 0x6fbe57 in double const* std::begin<double>(std::valarray<double> const&) /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/v
alarray:1207
    nlohmann#2 0x6fbe57 in void nlohmann::detail::external_constructor<(nlohmann::detail::value_t)2>::construct<nlohmann::basic_json<std::map, std::vector, s
td::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_seri
alizer>, double, 0>(nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool
, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>&, std::valarray<double> const&) /home/firma/devel/json/include/nlohmann/deta
il/conversions/to_json.hpp:157
    nlohmann#3 0x5e3fe3 in void nlohmann::detail::to_json<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>
, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>, double, 0>(nlohmann::basic_json<std::map, std
::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohman
n::adl_serializer>&, std::valarray<double> const&) /home/firma/devel/json/include/nlohmann/detail/conversions/to_json.hpp:270:5
    nlohmann#4 0x5e3fe3 in decltype((to_json(fp, std::forward<std::valarray<double>&>(fp0))) , ((void)())) nlohmann::detail::to_json_fn::operator()<nlohmann:
:basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double
, std::allocator, nlohmann::adl_serializer>, std::valarray<double>&>(nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std
::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>&, std::valarray<double>&) c
onst /home/firma/devel/json/include/nlohmann/detail/conversions/to_json.hpp:334
    nlohmann#5 0x5e3fe3 in decltype((nlohmann::(anonymous namespace)::to_json(fp, std::forward<std::valarray<double>&>(fp0))) , ((void)())) nlohmann::adl_ser
ializer<std::valarray<double>, void>::to_json<nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, st
d::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>, std::valarray<double>&>(nlohmann::basic_json<std:
:map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator
, nlohmann::adl_serializer>&, std::valarray<double>&) /home/firma/devel/json/include/nlohmann/adl_serializer.hpp:45
    nlohmann#6 0x5e3fe3 in nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool,
 long, unsigned long, double, std::allocator, nlohmann::adl_serializer>::basic_json<std::valarray<double>&, std::valarray<double>, 0>(std::valarray<d
ouble>&) /home/firma/devel/json/include/nlohmann/json.hpp:1257
    nlohmann#7 0x5e3fe3 in _DOCTEST_ANON_FUNC_2() /home/firma/devel/json/test/src/unit-regression.cpp:1377
    nlohmann#8 0x77313e in doctest::Context::run() /home/firma/devel/json/test/thirdparty/doctest/doctest.h:5938:21
    nlohmann#9 0x777ae0 in main /home/firma/devel/json/test/thirdparty/doctest/doctest.h:6016:71
    nlohmann#10 0x7fae220532e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202e0)
    nlohmann#11 0x4a6479 in _start (/home/firma/devel/json/build/test/test-regression+0x4a6479)

The important thing to note here is that a std::valarray is *not* a STL
container, so the usual containter and iterator semantics don't apply.

Therefore we have to check if the container is non-empty before.
@Hoohya Hoohya mentioned this issue Jan 2, 2020
GerHobbelt pushed a commit to GerHobbelt/nlohmann-json that referenced this issue May 7, 2021
925316 pushed a commit to 925316/json that referenced this issue Sep 26, 2024
keep name spoofing menu button(nlohmann#14)
add smooth self-aim(nlohmann#7)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: enhancement/improvement solution: wontfix the issue will not be fixed (either it is impossible or deemed out of scope)
Projects
None yet
Development

No branches or pull requests

3 participants