From 4be012d36dc5b7b6f548321c407efb541ef40112 Mon Sep 17 00:00:00 2001 From: Ramya Eliger Date: Mon, 24 Aug 2026 23:07:47 +0530 Subject: [PATCH 1/2] fix array index overflow in set_at_pointer --- include/boost/json/impl/pointer.ipp | 6 ++++++ test/pointer.cpp | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/include/boost/json/impl/pointer.ipp b/include/boost/json/impl/pointer.ipp index 0004c85d7..ecf81e6d9 100644 --- a/include/boost/json/impl/pointer.ipp +++ b/include/boost/json/impl/pointer.ipp @@ -455,6 +455,12 @@ value::set_at_pointer( if( n >= opts.max_created_elements ) return nullptr; + // arr.size() + n + 1 equals index + 1; reject the value that + // would wrap so the resize count and the returned pointer stay + // in bounds + if( index == std::size_t(-1) ) + return nullptr; + arr.resize( arr.size() + n + 1 ); } diff --git a/test/pointer.cpp b/test/pointer.cpp index 6b658befc..e54f80663 100644 --- a/test/pointer.cpp +++ b/test/pointer.cpp @@ -312,6 +312,26 @@ class pointer_test BOOST_TEST( *result == 0 ); BOOST_TEST( result == &jv.at_pointer("/4") ); + // an index equal to std::size_t(-1) makes the element count index + 1 + // wrap to zero; the array must not be resized and no pointer past its + // end may be returned + opts = {}; + opts.max_created_elements = std::size_t(-1); + jv = array{0}; + { + std::string const ptr = + "/" + std::to_string(std::size_t(-1)); + BOOST_TEST_THROWS_WITH_LOCATION( jv.set_at_pointer(ptr, 1, opts) ); + BOOST_TEST(( jv == array{0} )); + + system::error_code ec; + result = jv.set_at_pointer(ptr, 1, ec, opts); + BOOST_TEST( !result ); + BOOST_TEST( ec == error::not_found ); + BOOST_TEST( hasLocation(ec) ); + BOOST_TEST(( jv == array{0} )); + } + opts = {}; opts.create_arrays = false; opts.create_objects = false; From 5ac03f4c6de91b368ebb1766732be136d34f18e0 Mon Sep 17 00:00:00 2001 From: Ramya Eliger Date: Thu, 27 Aug 2026 15:01:05 +0530 Subject: [PATCH 2/2] report array_too_large for out-of-range set_at_pointer index --- include/boost/json/impl/pointer.ipp | 10 ++++++---- test/pointer.cpp | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/include/boost/json/impl/pointer.ipp b/include/boost/json/impl/pointer.ipp index ecf81e6d9..a6a05d84d 100644 --- a/include/boost/json/impl/pointer.ipp +++ b/include/boost/json/impl/pointer.ipp @@ -455,11 +455,13 @@ value::set_at_pointer( if( n >= opts.max_created_elements ) return nullptr; - // arr.size() + n + 1 equals index + 1; reject the value that - // would wrap so the resize count and the returned pointer stay - // in bounds - if( index == std::size_t(-1) ) + // the resulting size, index + 1, would either exceed the + // array's size limit or wrap to 0 when index == size_t(-1) + if( index >= array::max_size() ) + { + BOOST_JSON_FAIL( ec, error::array_too_large ); return nullptr; + } arr.resize( arr.size() + n + 1 ); } diff --git a/test/pointer.cpp b/test/pointer.cpp index e54f80663..7a2ffcbb8 100644 --- a/test/pointer.cpp +++ b/test/pointer.cpp @@ -327,7 +327,7 @@ class pointer_test system::error_code ec; result = jv.set_at_pointer(ptr, 1, ec, opts); BOOST_TEST( !result ); - BOOST_TEST( ec == error::not_found ); + BOOST_TEST( ec == error::array_too_large ); BOOST_TEST( hasLocation(ec) ); BOOST_TEST(( jv == array{0} )); }