Skip to content

Commit 74a4bd9

Browse files
authored
[ Fix ] : Paper crash occurring in SetLayoutPropsRecursive due to a null pointer dereference (#15016)
* Null pointer checks and validation in SetLayoutPropsRecursive to prevent crashes when shadow nodes are invalid or deleted * Change files * yarn format and lint:fix * removed deep copying of children * yarn lint:fix and format * review comment : removed redundant checks while calling SetLayoutPropsRecursive for child shadow nodes
1 parent 014a1eb commit 74a4bd9

File tree

2 files changed

+34
-11
lines changed

2 files changed

+34
-11
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "prerelease",
3+
"comment": "Null pointer checks and validation in SetLayoutPropsRecursive to prevent crashes when shadow nodes are invalid or deleted",
4+
"packageName": "react-native-windows",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}

vnext/Microsoft.ReactNative/Modules/NativeUIManager.cpp

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -931,8 +931,21 @@ void NativeUIManager::ApplyLayout(int64_t tag, float width, float height) {
931931
}
932932

933933
void NativeUIManager::SetLayoutPropsRecursive(int64_t tag) {
934-
ShadowNodeBase &shadowNode = static_cast<ShadowNodeBase &>(m_host->GetShadowNodeForTag(tag));
934+
if (!m_host) {
935+
return;
936+
}
937+
938+
auto *shadowNodePtr = m_host->FindShadowNodeForTag(tag);
939+
if (!shadowNodePtr) {
940+
return;
941+
}
942+
943+
ShadowNodeBase &shadowNode = static_cast<ShadowNodeBase &>(*shadowNodePtr);
935944
auto *pViewManager = shadowNode.GetViewManager();
945+
if (!pViewManager) {
946+
return;
947+
}
948+
936949
if (!pViewManager->IsNativeControlWithSelfLayout()) {
937950
for (const auto child : shadowNode.m_children) {
938951
SetLayoutPropsRecursive(child);
@@ -951,18 +964,21 @@ void NativeUIManager::SetLayoutPropsRecursive(int64_t tag) {
951964
float height = YGNodeLayoutGetHeight(yogaNode);
952965
auto view = shadowNode.GetView();
953966
auto pViewManager = shadowNode.GetViewManager();
954-
pViewManager->SetLayoutProps(shadowNode, view, left, top, width, height);
955-
if (shadowNode.m_onLayoutRegistered) {
956-
const auto hasLayoutChanged = !YogaFloatEquals(left, shadowNode.m_layout.Left) ||
957-
!YogaFloatEquals(top, shadowNode.m_layout.Top) || !YogaFloatEquals(width, shadowNode.m_layout.Width) ||
958-
!YogaFloatEquals(height, shadowNode.m_layout.Height);
959-
if (hasLayoutChanged) {
960-
React::JSValueObject layout{{"x", left}, {"y", top}, {"height", height}, {"width", width}};
961-
React::JSValueObject eventData{{"target", tag}, {"layout", std::move(layout)}};
962-
pViewManager->DispatchCoalescingEvent(tag, L"topLayout", MakeJSValueWriter(std::move(eventData)));
967+
968+
if (pViewManager) {
969+
pViewManager->SetLayoutProps(shadowNode, view, left, top, width, height);
970+
if (shadowNode.m_onLayoutRegistered) {
971+
const auto hasLayoutChanged = !YogaFloatEquals(left, shadowNode.m_layout.Left) ||
972+
!YogaFloatEquals(top, shadowNode.m_layout.Top) || !YogaFloatEquals(width, shadowNode.m_layout.Width) ||
973+
!YogaFloatEquals(height, shadowNode.m_layout.Height);
974+
if (hasLayoutChanged) {
975+
React::JSValueObject layout{{"x", left}, {"y", top}, {"height", height}, {"width", width}};
976+
React::JSValueObject eventData{{"target", tag}, {"layout", std::move(layout)}};
977+
pViewManager->DispatchCoalescingEvent(tag, L"topLayout", MakeJSValueWriter(std::move(eventData)));
978+
}
963979
}
980+
shadowNode.m_layout = {left, top, width, height};
964981
}
965-
shadowNode.m_layout = {left, top, width, height};
966982
}
967983
}
968984

0 commit comments

Comments
 (0)