Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 9ac09ce

Browse files
authored
[Impeller] Fix unsafe access for clip stencil coverage (#39595)
1 parent 8cd648d commit 9ac09ce

File tree

2 files changed

+70
-2
lines changed

2 files changed

+70
-2
lines changed

impeller/entity/contents/clip_contents.cc

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,18 @@ Contents::StencilCoverage ClipContents::GetStencilCoverage(
4747
return {.type = StencilCoverage::Type::kAppend,
4848
.coverage = current_stencil_coverage};
4949
case Entity::ClipOperation::kIntersect:
50+
if (!geometry_) {
51+
return {.type = StencilCoverage::Type::kAppend,
52+
.coverage = std::nullopt};
53+
}
54+
auto coverage = geometry_->GetCoverage(entity.GetTransformation());
55+
if (!coverage.has_value() || !current_stencil_coverage.has_value()) {
56+
return {.type = StencilCoverage::Type::kAppend,
57+
.coverage = std::nullopt};
58+
}
5059
return {
5160
.type = StencilCoverage::Type::kAppend,
52-
.coverage = current_stencil_coverage->Intersection(
53-
geometry_->GetCoverage(entity.GetTransformation()).value()),
61+
.coverage = current_stencil_coverage->Intersection(coverage.value()),
5462
};
5563
}
5664
FML_UNREACHABLE();

impeller/entity/entity_unittests.cc

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1508,6 +1508,66 @@ TEST_P(EntityTest, ClipContentsShouldRenderIsCorrect) {
15081508
}
15091509
}
15101510

1511+
TEST_P(EntityTest, ClipContentsGetStencilCoverageIsCorrect) {
1512+
// Intersection: No stencil coverage, no geometry.
1513+
{
1514+
auto clip = std::make_shared<ClipContents>();
1515+
clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1516+
auto result = clip->GetStencilCoverage(Entity{}, Rect{});
1517+
1518+
ASSERT_FALSE(result.coverage.has_value());
1519+
}
1520+
1521+
// Intersection: No stencil coverage, with geometry.
1522+
{
1523+
auto clip = std::make_shared<ClipContents>();
1524+
clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1525+
clip->SetGeometry(Geometry::MakeFillPath(
1526+
PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath()));
1527+
auto result = clip->GetStencilCoverage(Entity{}, Rect{});
1528+
1529+
ASSERT_FALSE(result.coverage.has_value());
1530+
}
1531+
1532+
// Intersection: With stencil coverage, no geometry.
1533+
{
1534+
auto clip = std::make_shared<ClipContents>();
1535+
clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1536+
auto result =
1537+
clip->GetStencilCoverage(Entity{}, Rect::MakeLTRB(0, 0, 100, 100));
1538+
1539+
ASSERT_FALSE(result.coverage.has_value());
1540+
}
1541+
1542+
// Intersection: With stencil coverage, with geometry.
1543+
{
1544+
auto clip = std::make_shared<ClipContents>();
1545+
clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1546+
clip->SetGeometry(Geometry::MakeFillPath(
1547+
PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 50, 50)).TakePath()));
1548+
auto result =
1549+
clip->GetStencilCoverage(Entity{}, Rect::MakeLTRB(0, 0, 100, 100));
1550+
1551+
ASSERT_TRUE(result.coverage.has_value());
1552+
ASSERT_RECT_NEAR(result.coverage.value(), Rect::MakeLTRB(0, 0, 50, 50));
1553+
ASSERT_EQ(result.type, Contents::StencilCoverage::Type::kAppend);
1554+
}
1555+
1556+
// Difference: With stencil coverage, with geometry.
1557+
{
1558+
auto clip = std::make_shared<ClipContents>();
1559+
clip->SetClipOperation(Entity::ClipOperation::kDifference);
1560+
clip->SetGeometry(Geometry::MakeFillPath(
1561+
PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 50, 50)).TakePath()));
1562+
auto result =
1563+
clip->GetStencilCoverage(Entity{}, Rect::MakeLTRB(0, 0, 100, 100));
1564+
1565+
ASSERT_TRUE(result.coverage.has_value());
1566+
ASSERT_RECT_NEAR(result.coverage.value(), Rect::MakeLTRB(0, 0, 100, 100));
1567+
ASSERT_EQ(result.type, Contents::StencilCoverage::Type::kAppend);
1568+
}
1569+
}
1570+
15111571
TEST_P(EntityTest, RRectShadowTest) {
15121572
auto callback = [&](ContentContext& context, RenderPass& pass) {
15131573
static Color color = Color::Red();

0 commit comments

Comments
 (0)