State the frame stack invariants of json_sax_dom_parser as assertions
clang-tidy's static analyzer analyzes the forwarding SAX handlers of the error recovery tests (RecoveringDomParser, BasicRecoveringParser) as entry points, with the state of their json_sax_dom_parser member unknown. It then assumes a frame stack of capacity 0 that grow() cannot enlarge (clang-analyzer-security.ArrayBound) and a collected container without an enclosing frame (clang-analyzer-core.NonNullParamChecker). Neither can happen: the stack starts with local_capacity frames, and only a container inside another one is collected. Assert both, which also lets the analyzer discard these paths. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
2 files changed
+8
No files matched your search
@@ -749,6 +749,8 @@ class json_sax_dom_parser
|
|||||||
JSON_HEDLEY_NEVER_INLINE
|
JSON_HEDLEY_NEVER_INLINE
|
||||||
void grow()
|
void grow()
|
||||||
{
|
{
|
||||||
|
// the stack starts with local_capacity frames and only grows
|
||||||
|
JSON_ASSERT(capacity != 0);
|
||||||
const std::size_t new_capacity = capacity * 2;
|
const std::size_t new_capacity = capacity * 2;
|
||||||
std::unique_ptr<frame[]> new_heap(new frame[new_capacity]); // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
std::unique_ptr<frame[]> new_heap(new frame[new_capacity]); // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||||
std::copy(data, data + count, new_heap.get());
|
std::copy(data, data + count, new_heap.get());
|
||||||
@@ -914,6 +916,8 @@ class json_sax_dom_parser
|
|||||||
/// directly if the value was the one too many.
|
/// directly if the value was the one too many.
|
||||||
void place_container(const frame& f, frame* enclosing, BasicJsonType&& value, const bool enclosing_is_innermost)
|
void place_container(const frame& f, frame* enclosing, BasicJsonType&& value, const bool enclosing_is_innermost)
|
||||||
{
|
{
|
||||||
|
// a container without a slot of its own is collected for an enclosing one
|
||||||
|
JSON_ASSERT(f.slot != nullptr || enclosing != nullptr);
|
||||||
if (f.slot != nullptr)
|
if (f.slot != nullptr)
|
||||||
{
|
{
|
||||||
*f.slot = std::move(value);
|
*f.slot = std::move(value);
|
||||||
|
|||||||
Generated
+4
@@ -16529,6 +16529,8 @@ class json_sax_dom_parser
|
|||||||
JSON_HEDLEY_NEVER_INLINE
|
JSON_HEDLEY_NEVER_INLINE
|
||||||
void grow()
|
void grow()
|
||||||
{
|
{
|
||||||
|
// the stack starts with local_capacity frames and only grows
|
||||||
|
JSON_ASSERT(capacity != 0);
|
||||||
const std::size_t new_capacity = capacity * 2;
|
const std::size_t new_capacity = capacity * 2;
|
||||||
std::unique_ptr<frame[]> new_heap(new frame[new_capacity]); // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
std::unique_ptr<frame[]> new_heap(new frame[new_capacity]); // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||||
std::copy(data, data + count, new_heap.get());
|
std::copy(data, data + count, new_heap.get());
|
||||||
@@ -16694,6 +16696,8 @@ class json_sax_dom_parser
|
|||||||
/// directly if the value was the one too many.
|
/// directly if the value was the one too many.
|
||||||
void place_container(const frame& f, frame* enclosing, BasicJsonType&& value, const bool enclosing_is_innermost)
|
void place_container(const frame& f, frame* enclosing, BasicJsonType&& value, const bool enclosing_is_innermost)
|
||||||
{
|
{
|
||||||
|
// a container without a slot of its own is collected for an enclosing one
|
||||||
|
JSON_ASSERT(f.slot != nullptr || enclosing != nullptr);
|
||||||
if (f.slot != nullptr)
|
if (f.slot != nullptr)
|
||||||
{
|
{
|
||||||
*f.slot = std::move(value);
|
*f.slot = std::move(value);
|
||||||
|
|||||||
Reference in new issue
Block a user