Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion Source/ASDisplayNode.mm
Original file line number Diff line number Diff line change
Expand Up @@ -2114,11 +2114,18 @@ - (void)_insertSubnode:(ASDisplayNode *)subnode atSubnodeIndex:(NSInteger)subnod
__instanceLock__.lock();
NSUInteger subnodesCount = _subnodes.count;
__instanceLock__.unlock();

if (subnodeIndex > subnodesCount || subnodeIndex < 0) {
ASDisplayNodeFailAssert(@"Cannot insert a subnode at index %ld. Count is %ld", (long)subnodeIndex, (long)subnodesCount);
return;
}


// Check if subnode is already a in _subnodes. If so make sure the subnodeIndex will not be out of bounds once we call [subnode removeFromSupernode]
if (subnode.supernode == self && subnodeIndex >= subnodesCount) {
ASDisplayNodeFailAssert(@"node %@ is already a subnode of %@. index %ld will be out of bounds once we call [subnode removeFromSupernode]. This can be caused by using automaticallyManagesSubnodes while also calling addSubnode explicitly.", subnode, self, subnodeIndex);
return;
}

// Disable appearance methods during move between supernodes, but make sure we restore their state after we do our thing
ASDisplayNode *oldParent = subnode.supernode;
BOOL disableNotifications = shouldDisableNotificationsForMovingBetweenParents(oldParent, self);
Expand Down
11 changes: 11 additions & 0 deletions Tests/ASDisplayNodeTests.mm
Original file line number Diff line number Diff line change
Expand Up @@ -2783,4 +2783,15 @@ - (void)testPlaceholder
XCTAssertTrue(hasPlaceholderLayer);
}

- (void)testInsertExistingSubnode
{
DeclareNodeNamed(parent);
DeclareNodeNamed(child);

[parent addSubnode:child];
// Previously this would cause a crash. We now protect inserting an already existing subnode out of bounds
XCTAssertThrows([parent insertSubnode:child atIndex:1]);
XCTAssertTrue(parent.subnodes.count == 1);
}

@end