Skip to content

Commit 810c205

Browse files
NickGerlemanfacebook-github-bot
authored andcommitted
Fix "swapLeftAndRight" unsafe static_cast (#42721)
Summary: Pull Request resolved: #42721 If left and right are swapped, this code assumes every yoga layoutable shadownode is a view, and mutates its props as if they were ViewProps. This is not safe, and could lead to memory corruption. Changelog: [Internal] Reviewed By: rozele Differential Revision: D53213652 fbshipit-source-id: c43e0f80fdd5889761317c1243ccc0ab392e3443
1 parent 044b50b commit 810c205

File tree

2 files changed

+54
-58
lines changed

2 files changed

+54
-58
lines changed

packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp

Lines changed: 52 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -863,13 +863,12 @@ yoga::Config& YogaLayoutableShadowNode::initializeYogaConfig(
863863
void YogaLayoutableShadowNode::swapStyleLeftAndRight() {
864864
ensureUnsealed();
865865

866-
swapLeftAndRightInYogaStyleProps(*this);
867-
swapLeftAndRightInViewProps(*this);
866+
swapLeftAndRightInYogaStyleProps();
867+
swapLeftAndRightInViewProps();
868868
}
869869

870-
void YogaLayoutableShadowNode::swapLeftAndRightInYogaStyleProps(
871-
const YogaLayoutableShadowNode& shadowNode) {
872-
auto yogaStyle = shadowNode.yogaNode_.style();
870+
void YogaLayoutableShadowNode::swapLeftAndRightInYogaStyleProps() {
871+
auto yogaStyle = yogaNode_.style();
873872

874873
// Swap Yoga node values, position, padding and margin.
875874

@@ -906,66 +905,65 @@ void YogaLayoutableShadowNode::swapLeftAndRightInYogaStyleProps(
906905
yogaStyle.setMargin(yoga::Edge::Right, yoga::value::undefined());
907906
}
908907

909-
shadowNode.yogaNode_.setStyle(yogaStyle);
910-
}
911-
912-
void YogaLayoutableShadowNode::swapLeftAndRightInViewProps(
913-
const YogaLayoutableShadowNode& shadowNode) {
914-
auto& typedCasting = static_cast<const ViewProps&>(*shadowNode.props_);
915-
auto& props = const_cast<ViewProps&>(typedCasting);
916-
917-
// Swap border node values, borderRadii, borderColors and borderStyles.
918-
919-
if (props.borderRadii.topLeft.has_value()) {
920-
props.borderRadii.topStart = props.borderRadii.topLeft;
921-
props.borderRadii.topLeft.reset();
908+
if (yogaStyle.border(yoga::Edge::Left).isDefined()) {
909+
yogaStyle.setBorder(yoga::Edge::Start, yogaStyle.border(yoga::Edge::Left));
910+
yogaStyle.setBorder(yoga::Edge::Left, yoga::value::undefined());
922911
}
923912

924-
if (props.borderRadii.bottomLeft.has_value()) {
925-
props.borderRadii.bottomStart = props.borderRadii.bottomLeft;
926-
props.borderRadii.bottomLeft.reset();
913+
if (yogaStyle.border(yoga::Edge::Right).isDefined()) {
914+
yogaStyle.setBorder(yoga::Edge::End, yogaStyle.border(yoga::Edge::Right));
915+
yogaStyle.setBorder(yoga::Edge::Right, yoga::value::undefined());
927916
}
928917

929-
if (props.borderRadii.topRight.has_value()) {
930-
props.borderRadii.topEnd = props.borderRadii.topRight;
931-
props.borderRadii.topRight.reset();
932-
}
918+
yogaNode_.setStyle(yogaStyle);
919+
}
933920

934-
if (props.borderRadii.bottomRight.has_value()) {
935-
props.borderRadii.bottomEnd = props.borderRadii.bottomRight;
936-
props.borderRadii.bottomRight.reset();
937-
}
921+
void YogaLayoutableShadowNode::swapLeftAndRightInViewProps() {
922+
if (auto viewShadowNode = dynamic_cast<ViewShadowNode*>(this)) {
923+
// TODO: Do not mutate props directly.
924+
auto& props =
925+
const_cast<ViewShadowNodeProps&>(viewShadowNode->getConcreteProps());
938926

939-
if (props.borderColors.left.has_value()) {
940-
props.borderColors.start = props.borderColors.left;
941-
props.borderColors.left.reset();
942-
}
927+
// Swap border node values, borderRadii, borderColors and borderStyles.
928+
if (props.borderRadii.topLeft.has_value()) {
929+
props.borderRadii.topStart = props.borderRadii.topLeft;
930+
props.borderRadii.topLeft.reset();
931+
}
943932

944-
if (props.borderColors.right.has_value()) {
945-
props.borderColors.end = props.borderColors.right;
946-
props.borderColors.right.reset();
947-
}
933+
if (props.borderRadii.bottomLeft.has_value()) {
934+
props.borderRadii.bottomStart = props.borderRadii.bottomLeft;
935+
props.borderRadii.bottomLeft.reset();
936+
}
948937

949-
if (props.borderStyles.left.has_value()) {
950-
props.borderStyles.start = props.borderStyles.left;
951-
props.borderStyles.left.reset();
952-
}
938+
if (props.borderRadii.topRight.has_value()) {
939+
props.borderRadii.topEnd = props.borderRadii.topRight;
940+
props.borderRadii.topRight.reset();
941+
}
953942

954-
if (props.borderStyles.right.has_value()) {
955-
props.borderStyles.end = props.borderStyles.right;
956-
props.borderStyles.right.reset();
957-
}
943+
if (props.borderRadii.bottomRight.has_value()) {
944+
props.borderRadii.bottomEnd = props.borderRadii.bottomRight;
945+
props.borderRadii.bottomRight.reset();
946+
}
958947

959-
if (props.yogaStyle.border(yoga::Edge::Left).isDefined()) {
960-
props.yogaStyle.setBorder(
961-
yoga::Edge::Start, props.yogaStyle.border(yoga::Edge::Left));
962-
props.yogaStyle.setBorder(yoga::Edge::Left, yoga::value::undefined());
963-
}
948+
if (props.borderColors.left.has_value()) {
949+
props.borderColors.start = props.borderColors.left;
950+
props.borderColors.left.reset();
951+
}
964952

965-
if (props.yogaStyle.border(yoga::Edge::Right).isDefined()) {
966-
props.yogaStyle.setBorder(
967-
yoga::Edge::End, props.yogaStyle.border(yoga::Edge::Right));
968-
props.yogaStyle.setBorder(yoga::Edge::Right, yoga::value::undefined());
953+
if (props.borderColors.right.has_value()) {
954+
props.borderColors.end = props.borderColors.right;
955+
props.borderColors.right.reset();
956+
}
957+
958+
if (props.borderStyles.left.has_value()) {
959+
props.borderStyles.start = props.borderStyles.left;
960+
props.borderStyles.left.reset();
961+
}
962+
963+
if (props.borderStyles.right.has_value()) {
964+
props.borderStyles.end = props.borderStyles.right;
965+
props.borderStyles.right.reset();
966+
}
969967
}
970968
}
971969

packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,16 +190,14 @@ class YogaLayoutableShadowNode : public LayoutableShadowNode {
190190
* - border(Left|Right)Width → border(Start|End)Width
191191
* - border(Left|Right)Color → border(Start|End)Color
192192
*/
193-
static void swapLeftAndRightInViewProps(
194-
const YogaLayoutableShadowNode& shadowNode);
193+
void swapLeftAndRightInViewProps();
195194
/*
196195
* In yoga node passed as argument, reassigns following values
197196
* - (left|right) → (start|end)
198197
* - margin(Left|Right) → margin(Start|End)
199198
* - padding(Left|Right) → padding(Start|End)
200199
*/
201-
static void swapLeftAndRightInYogaStyleProps(
202-
const YogaLayoutableShadowNode& shadowNode);
200+
void swapLeftAndRightInYogaStyleProps();
203201

204202
/*
205203
* Combine a base yoga::Style with aliased properties which should be

0 commit comments

Comments
 (0)