Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f12a678f authored by Vishnu Nair's avatar Vishnu Nair
Browse files

Fix unsafe layer hierarchy access

We may modify the layer hierarchy while updating
relative layers. Fix this by retrieving the list of descendants
and then attaching or detaching it from their relative
parent.

Test: presubmit
Fixes: 344113039
Flag: EXEMPT bugfixes
Change-Id: I7aff5085794aeeb0bbba90decaf4cec13d0d2485
parent a1046a89
Loading
Loading
Loading
Loading
+25 −16
Original line number Diff line number Diff line
@@ -260,27 +260,36 @@ void LayerHierarchyBuilder::detachFromRelativeParent(LayerHierarchy* hierarchy)
    hierarchy->mParent->updateChild(hierarchy, LayerHierarchy::Variant::Attached);
}

void LayerHierarchyBuilder::attachHierarchyToRelativeParent(LayerHierarchy* root) {
    if (root->mLayer) {
        attachToRelativeParent(root);
    }
    for (auto& [child, childVariant] : root->mChildren) {
std::vector<LayerHierarchy*> LayerHierarchyBuilder::getDescendants(LayerHierarchy* root) {
    std::vector<LayerHierarchy*> hierarchies;
    hierarchies.push_back(root);
    std::vector<LayerHierarchy*> descendants;
    for (size_t i = 0; i < hierarchies.size(); i++) {
        LayerHierarchy* hierarchy = hierarchies[i];
        if (hierarchy->mLayer) {
            descendants.push_back(hierarchy);
        }
        for (auto& [child, childVariant] : hierarchy->mChildren) {
            if (childVariant == LayerHierarchy::Variant::Detached ||
                childVariant == LayerHierarchy::Variant::Attached) {
            attachHierarchyToRelativeParent(child);
                hierarchies.push_back(child);
            }
        }
    }
    return descendants;
}

void LayerHierarchyBuilder::detachHierarchyFromRelativeParent(LayerHierarchy* root) {
    if (root->mLayer) {
        detachFromRelativeParent(root);
void LayerHierarchyBuilder::attachHierarchyToRelativeParent(LayerHierarchy* root) {
    std::vector<LayerHierarchy*> hierarchiesToAttach = getDescendants(root);
    for (LayerHierarchy* hierarchy : hierarchiesToAttach) {
        attachToRelativeParent(hierarchy);
    }
    for (auto& [child, childVariant] : root->mChildren) {
        if (childVariant == LayerHierarchy::Variant::Detached ||
            childVariant == LayerHierarchy::Variant::Attached) {
            detachHierarchyFromRelativeParent(child);
}

void LayerHierarchyBuilder::detachHierarchyFromRelativeParent(LayerHierarchy* root) {
    std::vector<LayerHierarchy*> hierarchiesToDetach = getDescendants(root);
    for (LayerHierarchy* hierarchy : hierarchiesToDetach) {
        detachFromRelativeParent(hierarchy);
    }
}

+1 −0
Original line number Diff line number Diff line
@@ -218,6 +218,7 @@ private:
    void detachFromParent(LayerHierarchy*);
    void attachToRelativeParent(LayerHierarchy*);
    void detachFromRelativeParent(LayerHierarchy*);
    std::vector<LayerHierarchy*> getDescendants(LayerHierarchy*);
    void attachHierarchyToRelativeParent(LayerHierarchy*);
    void detachHierarchyFromRelativeParent(LayerHierarchy*);
    void init(const std::vector<std::unique_ptr<RequestedLayerState>>&);