jsoncons icon indicating copy to clipboard operation
jsoncons copied to clipboard

Compile error on i386 with `-Werror=free-nonheap-object`

Open Harry-Chen opened this issue 2 months ago • 7 comments

Describe the bug

The following build error occurred when building for i386 on Debian with GCC 15.2.0:

[3/147] /usr/lib/ccache/c++  -I/build/package/package/include -I/build/package/package/test -I/build/package/package/test/thirdparty -I/build/package/package/test/thirdparty/catch -g -O2 -ffile-prefix-map=/build/package/package=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -Werror=maybe-uninitialized -Wnon-virtual-dtor -Werror=stringop-overflow -Werror -Wall -Wextra -Wcast-align -Wcast-qual -Wimplicit-fallthrough -Wsign-compare -pedantic -Wnonnull -Wnull-dereference -Werror=nonnull -MD -MT test/CMakeFiles/unit_tests.dir/bson/src/bson_cursor_tests.cpp.o -MF test/CMakeFiles/unit_tests.dir/bson/src/bson_cursor_tests.cpp.o.d -o test/CMakeFiles/unit_tests.dir/bson/src/bson_cursor_tests.cpp.o -c /build/package/package/test/bson/src/bson_cursor_tests.cpp
FAILED: test/CMakeFiles/unit_tests.dir/bson/src/bson_cursor_tests.cpp.o 
/usr/lib/ccache/c++  -I/build/package/package/include -I/build/package/package/test -I/build/package/package/test/thirdparty -I/build/package/package/test/thirdparty/catch -g -O2 -ffile-prefix-map=/build/package/package=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -Werror=maybe-uninitialized -Wnon-virtual-dtor -Werror=stringop-overflow -Werror -Wall -Wextra -Wcast-align -Wcast-qual -Wimplicit-fallthrough -Wsign-compare -pedantic -Wnonnull -Wnull-dereference -Werror=nonnull -MD -MT test/CMakeFiles/unit_tests.dir/bson/src/bson_cursor_tests.cpp.o -MF test/CMakeFiles/unit_tests.dir/bson/src/bson_cursor_tests.cpp.o.d -o test/CMakeFiles/unit_tests.dir/bson/src/bson_cursor_tests.cpp.o -c /build/package/package/test/bson/src/bson_cursor_tests.cpp
In file included from /usr/include/i386-linux-gnu/c++/15/bits/c++allocator.h:33,
                 from /usr/include/c++/15/bits/allocator.h:46,
                 from /usr/include/c++/15/bits/alloc_traits.h:39,
                 from /usr/include/c++/15/ext/alloc_traits.h:36,
                 from /usr/include/c++/15/bits/hashtable_policy.h:39,
                 from /usr/include/c++/15/bits/hashtable.h:37,
                 from /usr/include/c++/15/bits/unordered_map.h:33,
                 from /usr/include/c++/15/unordered_map:43,
                 from /usr/include/c++/15/functional:65,
                 from /build/package/package/include/jsoncons_ext/bson/bson_cursor.hpp:11,
                 from /build/package/package/test/bson/src/bson_cursor_tests.cpp:8:
In member function ‘void std::__new_allocator<_Tp>::deallocate(_Tp*, size_type) [with _Tp = long long unsigned int]’,
    inlined from ‘static void std::allocator_traits<std::allocator<_Tp1> >::deallocate(allocator_type&, pointer, size_type) [with _Tp = long long unsigned int]’ at /usr/include/c++/15/bits/alloc_traits.h:649:23,
    inlined from ‘void jsoncons::basic_bigint<Allocator>::dynamic_storage::destroy(const real_allocator_type&) [with Allocator = std::allocator<unsigned char>]’ at /build/package/package/include/jsoncons/utility/bigint.hpp:275:71,
    inlined from ‘void jsoncons::basic_bigint<Allocator>::destroy() [with Allocator = std::allocator<unsigned char>]’ at /build/package/package/include/jsoncons/utility/bigint.hpp:1545:34,
    inlined from ‘jsoncons::basic_bigint<Allocator>::~basic_bigint() [with Allocator = std::allocator<unsigned char>]’ at /build/package/package/include/jsoncons/utility/bigint.hpp:359:16,
    inlined from ‘void jsoncons::basic_bigint<Allocator>::unnormalize(jsoncons::basic_bigint<Allocator>&, int, int) const [with Allocator = std::allocator<unsigned char>]’ at /build/package/package/include/jsoncons/utility/bigint.hpp:1668:20,
    inlined from ‘void jsoncons::basic_bigint<Allocator>::divide(jsoncons::basic_bigint<Allocator>, jsoncons::basic_bigint<Allocator>&, jsoncons::basic_bigint<Allocator>&, bool) const [with Allocator = std::allocator<unsigned char>]’ at /build/package/package/include/jsoncons/utility/bigint.hpp:1536:24:
/usr/include/c++/15/bits/new_allocator.h:172:66: error: ‘void operator delete(void*, std::size_t)’ called on a pointer to an unallocated object ‘4294967295’ [-Werror=free-nonheap-object]
  172 |         _GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(__p, __n));
      |                                                                  ^
cc1plus: all warnings being treated as errors

Looks like there is a delete operator called on address -1 (which equals UINT32_MAX, i.e. 4294967295). I tried to read the code from bigint.hpp, but have not discovered anything obvious. Please investigate whether there is an architecture-related issue.

The full log could be obtained here.

Enumerate the steps to reproduce the bug

Just build with the specified configuration.

What compiler, architecture, and operating system?

  • Compiler: GCC 15.2.0
  • Architecture: i386
  • Operating system: Debian sid

What jsoncons library version?

  • [x] Latest release 1.4.3
  • [ ] Other release ______
  • [ ] master

Harry-Chen avatar Oct 23 '25 14:10 Harry-Chen

Thanks for reporting this, we'll have a look.

danielaparker avatar Oct 24 '25 04:10 danielaparker

I can't replicate this on any of the environments we test on, but we've made some changes to the bigint class, can you repeat the test using the code on master? To see if anything has changed? Thanks.

danielaparker avatar Nov 01 '25 00:11 danielaparker

@danielaparker The issue persists in the latest master commit (ce44fe675). You could try these steps to reproduce:

  • install g++-i686-linux-gnu in debian trixie
  • configure project by CC=i686-linux-gnu-gcc CXX=i686-linux-gnu-g++ CXXFLAGS='-fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -Werror=maybe-uninitialized -Wnon-virtual-dtor -Werror=stringop-overflow -Werror -Wall -Wextra -Wcast-align -Wcast-qual -Wimplicit-fallthrough -Wsign-compare -pedantic -Wnonnull -Wnull-dereference -Werror=nonnull' cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo
  • build the project by cmake --build .

Still same errors: /usr/i686-linux-gnu/include/c++/14/bits/new_allocator.h:172:33: error: ‘void operator delete(void*, std::size_t)’ called on a pointer to an unallocated object ‘4294967295’ [-Werror=free-nonheap-object]

Harry-Chen avatar Nov 02 '25 14:11 Harry-Chen

Raising this issue was helpful because it motivated improvements in the implementation of bigint. But I can't replicate it in the environments I have access to, using your compile time options. It's not flagged by the sanitizers and static analyzers in our CI workflow. VS and clang analyzers don't complain, nor does PVS Studio.

bigint can hold either inlined storage or allocated storage, depending on the size of the number, but there are checks to make sure that only allocated storage is ever deallocated. I've added a fuzzer integrated with Google OSS-fuzz that covers the lines of code identified by your report, and we'll see if that reveals anything. But given that there a number of false positives reported for free-nonheap-object on GCC Bugzilla, I'm inclined to think that this is another one.

danielaparker avatar Nov 19 '25 04:11 danielaparker

@danielaparker Thank you for your investigation into this issue! I agree that this might be another false positive. So I will temporarily ignore these error when packaging for debian. We could wait some time add see if later release of GCC could resolve this.

Harry-Chen avatar Nov 19 '25 07:11 Harry-Chen

@danielaparker More nits after ignoring these errors: some unit tests failed on i686. The detailed logs can be retrieved from https://ci.debian.net/packages/j/jsoncons/testing/i386/66453183/. Some lines that might be useful:

3136s 1/1 Test #1: unit_tests .......................***Failed    2.62 sec
3136s d8 55 48 ff ff 7f ff ff ff 7f 7f 
3136s 82 fa ff 7f ff ff fa 7f 7f ff ff 
3136s 
3136s 
3136s ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3136s unit_tests is a Catch v2.13.10 host application.
3136s Run with -? for options
3136s 
3136s -------------------------------------------------------------------------------
3136s cbor typed array tests
3136s   Tag 85, float32, little endian
3136s -------------------------------------------------------------------------------
3136s ./test/cbor/src/cbor_typed_array_tests.cpp:742
3136s ...............................................................................
3136s 
3136s ./test/cbor/src/cbor_typed_array_tests.cpp:38: FAILED:
3136s   CHECK( (u == v) )
3136s with expansion:
3136s   false
3136s 
3136s d8 56 50 ff ff ff ff ff ff ef ff ff ff ff ff ff ff ef 7f 
3136s 82 fb ff ef ff ff ff ff ff ff fb 7f ef ff ff ff ff ff ff 
3136s 
3136s -------------------------------------------------------------------------------
3136s cbor typed array tests
3136s   Tag 86, float64, little endian
3136s -------------------------------------------------------------------------------
3136s ./test/cbor/src/cbor_typed_array_tests.cpp:773
3136s ...............................................................................
3136s 
3136s ./test/cbor/src/cbor_typed_array_tests.cpp:38: FAILED:
3136s   CHECK( (u == v) )
3136s with expansion:
3136s   false

...


3136s ===============================================================================
3136s test cases:   838 |   837 passed | 1 failed
3136s assertions: 20292 | 20290 passed | 2 failed
3136s 
3136s 
3136s 
3136s 0% tests passed, 1 tests failed out of 1
3136s 
3136s Total Test time (real) =   2.62 sec
3136s 
3136s The following tests FAILED:
3136s 	  1 - unit_tests (Failed)

Looks like there are actual encoding / decoding issues. Please look into it when available, or I can create a new issue if that is more appropriate.

Harry-Chen avatar Nov 23 '25 13:11 Harry-Chen

I think this is unrelated, please create a new issue, thanks.

danielaparker avatar Nov 25 '25 04:11 danielaparker