diff --git a/tests/YGNodeChildTest.cpp b/tests/YGNodeChildTest.cpp index 0b7148dd52..fe8a0a5a15 100644 --- a/tests/YGNodeChildTest.cpp +++ b/tests/YGNodeChildTest.cpp @@ -5,6 +5,8 @@ * LICENSE file in the root directory of this source tree. */ +#include + #include #include @@ -66,3 +68,43 @@ TEST(YogaTest, removed_child_can_be_reused_with_valid_layout) { YGNodeFreeRecursive(root); } + +TEST(YogaTest, swap_child_with_out_of_bounds_index_is_rejected) { + YGNodeRef root = YGNodeNew(); + YGNodeRef child = YGNodeNew(); + YGNodeInsertChild(root, child, 0); + + // Replacing an existing index works. + YGNodeRef replacement = YGNodeNew(); + YGNodeSwapChild(root, replacement, 0); + ASSERT_EQ(replacement, YGNodeGetChild(root, 0)); + + // An index past the last child is rejected rather than reading and writing + // out of bounds on the underlying children vector. + YGNodeRef stray = YGNodeNew(); + ASSERT_THROW(YGNodeSwapChild(root, stray, 1), std::logic_error); + + YGNodeFree(stray); + YGNodeFree(child); + YGNodeFreeRecursive(root); +} + +TEST(YogaTest, insert_child_with_out_of_bounds_index_is_rejected) { + YGNodeRef root = YGNodeNew(); + + YGNodeRef first = YGNodeNew(); + YGNodeInsertChild(root, first, 0); + + // Appending at the end (index == child count) is allowed. + YGNodeRef second = YGNodeNew(); + YGNodeInsertChild(root, second, 1); + ASSERT_EQ(2u, YGNodeGetChildCount(root)); + + // An index beyond the end is rejected rather than constructing an invalid + // iterator into the children vector. + YGNodeRef stray = YGNodeNew(); + ASSERT_THROW(YGNodeInsertChild(root, stray, 5), std::logic_error); + + YGNodeFree(stray); + YGNodeFreeRecursive(root); +} diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 7a4068efee..b2149b631d 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -142,6 +142,11 @@ void YGNodeInsertChild( !owner->hasMeasureFunc(), "Cannot add child: Nodes with measure functions cannot have children."); + yoga::assertFatalWithNode( + owner, + index <= owner->getChildCount(), + "Cannot insert child: index out of bounds."); + owner->insertChild(child, index); child->setOwner(owner); owner->markDirtyAndPropagate(); @@ -154,6 +159,11 @@ void YGNodeSwapChild( auto owner = resolveRef(ownerRef); auto child = resolveRef(childRef); + yoga::assertFatalWithNode( + owner, + index < owner->getChildCount(), + "Cannot swap child: index out of bounds."); + owner->replaceChild(child, index); child->setOwner(owner); }