Skip to content

Commit 6c83352

Browse files
NickGerlemanmeta-codesync[bot]
authored andcommitted
Fix hard errors in filter parsing (facebook#55675)
Summary: Pull Request resolved: facebook#55675 `filterTypeFromString()` throws `std::invalid_argument` on unknown filter names, which crashes in `parseFilterRawValue` where it's called without try/catch. Change the return type to `std::optional<FilterType>` and return `std::nullopt` instead of throwing. Update callers in `FilterPropsConversions.h` to check the optional and gracefully return empty results. Changelog: [Internal] Reviewed By: mdvacca Differential Revision: D94052729 fbshipit-source-id: 5d5976eb9ef3ce0a37d9dcd067c2bb85df89c67f
1 parent a04904c commit 6c83352

3 files changed

Lines changed: 69 additions & 53 deletions

File tree

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

Lines changed: 55 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -45,64 +45,64 @@ parseProcessedFilter(const PropsParserContext &context, const RawValue &value, s
4545

4646
auto rawFilterFunction = static_cast<std::unordered_map<std::string, RawValue>>(rawFilterPrimitive);
4747
FilterFunction filterFunction{};
48-
try {
49-
filterFunction.type = filterTypeFromString(rawFilterFunction.begin()->first);
50-
if (filterFunction.type == FilterType::DropShadow) {
51-
auto rawDropShadow = static_cast<std::unordered_map<std::string, RawValue>>(rawFilterFunction.begin()->second);
52-
DropShadowParams dropShadowParams{};
53-
54-
auto offsetX = rawDropShadow.find("offsetX");
55-
react_native_expect(offsetX != rawDropShadow.end());
56-
if (offsetX == rawDropShadow.end()) {
57-
result = {};
58-
return;
59-
}
48+
auto filterType = filterTypeFromString(rawFilterFunction.begin()->first);
49+
if (!filterType.has_value()) {
50+
LOG(ERROR) << "Could not parse FilterFunction: " << rawFilterFunction.begin()->first;
51+
result = {};
52+
return;
53+
}
54+
filterFunction.type = *filterType;
55+
if (filterFunction.type == FilterType::DropShadow) {
56+
auto rawDropShadow = static_cast<std::unordered_map<std::string, RawValue>>(rawFilterFunction.begin()->second);
57+
DropShadowParams dropShadowParams{};
58+
59+
auto offsetX = rawDropShadow.find("offsetX");
60+
react_native_expect(offsetX != rawDropShadow.end());
61+
if (offsetX == rawDropShadow.end()) {
62+
result = {};
63+
return;
64+
}
6065

61-
react_native_expect(offsetX->second.hasType<Float>());
62-
if (!offsetX->second.hasType<Float>()) {
63-
result = {};
64-
return;
65-
}
66-
dropShadowParams.offsetX = (Float)offsetX->second;
66+
react_native_expect(offsetX->second.hasType<Float>());
67+
if (!offsetX->second.hasType<Float>()) {
68+
result = {};
69+
return;
70+
}
71+
dropShadowParams.offsetX = (Float)offsetX->second;
6772

68-
auto offsetY = rawDropShadow.find("offsetY");
69-
react_native_expect(offsetY != rawDropShadow.end());
70-
if (offsetY == rawDropShadow.end()) {
71-
result = {};
72-
return;
73-
}
74-
react_native_expect(offsetY->second.hasType<Float>());
75-
if (!offsetY->second.hasType<Float>()) {
73+
auto offsetY = rawDropShadow.find("offsetY");
74+
react_native_expect(offsetY != rawDropShadow.end());
75+
if (offsetY == rawDropShadow.end()) {
76+
result = {};
77+
return;
78+
}
79+
react_native_expect(offsetY->second.hasType<Float>());
80+
if (!offsetY->second.hasType<Float>()) {
81+
result = {};
82+
return;
83+
}
84+
dropShadowParams.offsetY = (Float)offsetY->second;
85+
86+
auto standardDeviation = rawDropShadow.find("standardDeviation");
87+
if (standardDeviation != rawDropShadow.end()) {
88+
react_native_expect(standardDeviation->second.hasType<Float>());
89+
if (!standardDeviation->second.hasType<Float>()) {
7690
result = {};
7791
return;
7892
}
79-
dropShadowParams.offsetY = (Float)offsetY->second;
80-
81-
auto standardDeviation = rawDropShadow.find("standardDeviation");
82-
if (standardDeviation != rawDropShadow.end()) {
83-
react_native_expect(standardDeviation->second.hasType<Float>());
84-
if (!standardDeviation->second.hasType<Float>()) {
85-
result = {};
86-
return;
87-
}
88-
dropShadowParams.standardDeviation = (Float)standardDeviation->second;
89-
}
90-
91-
auto color = rawDropShadow.find("color");
92-
if (color != rawDropShadow.end()) {
93-
fromRawValue(context.contextContainer, context.surfaceId, color->second, dropShadowParams.color);
94-
}
93+
dropShadowParams.standardDeviation = (Float)standardDeviation->second;
94+
}
9595

96-
filterFunction.parameters = dropShadowParams;
97-
} else {
98-
filterFunction.parameters = (float)rawFilterFunction.begin()->second;
96+
auto color = rawDropShadow.find("color");
97+
if (color != rawDropShadow.end()) {
98+
fromRawValue(context.contextContainer, context.surfaceId, color->second, dropShadowParams.color);
9999
}
100-
filter.push_back(std::move(filterFunction));
101-
} catch (const std::exception &e) {
102-
LOG(ERROR) << "Could not parse FilterFunction: " << e.what();
103-
result = {};
104-
return;
100+
101+
filterFunction.parameters = dropShadowParams;
102+
} else {
103+
filterFunction.parameters = (float)rawFilterFunction.begin()->second;
105104
}
105+
filter.push_back(filterFunction);
106106
}
107107

108108
result = filter;
@@ -313,11 +313,15 @@ inline std::optional<FilterFunction> parseFilterRawValue(const PropsParserContex
313313
}
314314
return {};
315315
} else {
316+
auto filterType = filterTypeFromString(filterKey);
317+
if (!filterType.has_value()) {
318+
return {};
319+
}
316320
if (auto amount = coerceAmount(rawFilter.begin()->second)) {
317321
if (*amount < 0.0f) {
318322
return {};
319323
}
320-
return FilterFunction{.type = filterTypeFromString(filterKey), .parameters = *amount};
324+
return FilterFunction{.type = *filterType, .parameters = *amount};
321325
}
322326
return {};
323327
}

packages/react-native/ReactCommon/react/renderer/components/view/tests/ConversionsTest.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,4 +239,15 @@ TEST(ConversionsTest, unprocessed_filter_objects_multiple_objects) {
239239
EXPECT_TRUE(filters.empty());
240240
}
241241

242+
TEST(ConversionsTest, unprocessed_filter_objects_unknown_type) {
243+
RawValue value{
244+
folly::dynamic::array(folly::dynamic::object("unknown-filter", 5))};
245+
246+
std::vector<FilterFunction> filters;
247+
parseUnprocessedFilter(
248+
PropsParserContext{-1, ContextContainer{}}, value, filters);
249+
250+
EXPECT_TRUE(filters.empty());
251+
}
252+
242253
} // namespace facebook::react

packages/react-native/ReactCommon/react/renderer/graphics/Filter.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <react/renderer/graphics/Color.h>
1111
#include <react/renderer/graphics/Float.h>
1212

13+
#include <optional>
1314
#include <string>
1415
#include <string_view>
1516
#include <variant>
@@ -29,7 +30,7 @@ enum class FilterType {
2930
DropShadow
3031
};
3132

32-
inline FilterType filterTypeFromString(std::string_view filterName)
33+
inline std::optional<FilterType> filterTypeFromString(std::string_view filterName)
3334
{
3435
if (filterName == "blur") {
3536
return FilterType::Blur;
@@ -52,7 +53,7 @@ inline FilterType filterTypeFromString(std::string_view filterName)
5253
} else if (filterName == "dropShadow") {
5354
return FilterType::DropShadow;
5455
} else {
55-
throw std::invalid_argument(std::string(filterName));
56+
return std::nullopt;
5657
}
5758
}
5859

0 commit comments

Comments
 (0)