Skip to content

fix: personalization resource destroy callbacks had inverted null check#808

Open
felixonmars wants to merge 1 commit intolinuxdeepin:masterfrom
felixonmars:inverted-resource-check
Open

fix: personalization resource destroy callbacks had inverted null check#808
felixonmars wants to merge 1 commit intolinuxdeepin:masterfrom
felixonmars:inverted-resource-check

Conversation

@felixonmars
Copy link
Copy Markdown
Member

@felixonmars felixonmars commented Mar 30, 2026

All 4 wl_resource destroy callbacks in personalization_manager_impl.cpp had an inverted null check introduced by commit 56c8376:

    if (resource)   // always true in a destroy callback
        return;     // function returns immediately, doing nothing

    wl_list_remove(...)  // never reached
    delete context;      // never reached

This meant wl_list_remove was never called, leaving freed wl_resource objects as dangling links in manager->resources. When a Wayland client disconnects, wl_client_destroy frees the resource memory while stale links remain in the list. Subsequent wl_list_insert/wl_list_remove operations on the same list then write to freed memory, corrupting the heap and causing crashes.

Fix by inverting the check to if (!resource).

Summary by Sourcery

Bug Fixes:

  • Correct wl_resource destroy callbacks for personalization window, wallpaper, cursor, and manager contexts so their cleanup logic runs as intended when resources are destroyed.

@deepin-ci-robot
Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: felixonmars

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Mar 30, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Fixes inverted null checks in all four Wayland personalization wl_resource destroy callbacks so that cleanup code (list removal and context deletion) now runs correctly and avoids heap corruption from dangling list links.

Sequence diagram for wl_resource destroy callback fix

sequenceDiagram
    participant WaylandClient
    participant wl_client as wl_client
    participant wl_resource as wl_resource
    participant Manager as treeland_personalization_manager_v1

    WaylandClient->>wl_client: disconnect()
    wl_client->>wl_resource: wl_resource_destroy(resource)
    wl_resource->>Manager: treeland_personalization_manager_resource_destroy(resource)
    alt resource_is_null
        Manager-->>Manager: return
    else resource_is_not_null
        Manager->>Manager: treeland_personalization_manager_v1.from_resource(resource)
        Manager->>Manager: wl_list_remove(resource_link)
        Manager->>Manager: delete context
    end
Loading

Flow diagram for corrected null check in destroy callbacks

flowchart TD
    A[wlr_destroy_callback called with resource] --> B{resource is null?}
    B -- Yes --> C[Return immediately]
    B -- No --> D[Lookup context via from_resource]
    D --> E[Remove resource from manager resources list]
    E --> F[Delete context object]
    F --> G[Return from destroy callback]
Loading

File-Level Changes

Change Details Files
Correct the null-check condition in all personalization wl_resource destroy callbacks so they early-return only on null resources and perform proper cleanup otherwise.
  • Invert the condition in personalization_window_context_resource_destroy so it returns only when the wl_resource pointer is null.
  • Invert the condition in personalization_wallpaper_context_resource_destroy so it returns only when the wl_resource pointer is null.
  • Invert the condition in personalization_cursor_context_resource_destroy so it returns only when the wl_resource pointer is null.
  • Invert the condition in treeland_personalization_manager_resource_destroy so it returns only when the wl_resource pointer is null, ensuring manager lookup and cleanup are executed.
src/modules/personalization/impl/personalization_manager_impl.cpp

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • Since Wayland destroy callbacks are not invoked with a null wl_resource, consider either removing the null check entirely or replacing it with an assertion to make the intended invariant explicit.
  • All four destroy callbacks share identical null-check and cleanup patterns; consider factoring this into a small helper or template to reduce duplication and avoid this class of inverted-condition bug in the future.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Since Wayland destroy callbacks are not invoked with a null wl_resource, consider either removing the null check entirely or replacing it with an assertion to make the intended invariant explicit.
- All four destroy callbacks share identical null-check and cleanup patterns; consider factoring this into a small helper or template to reduce duplication and avoid this class of inverted-condition bug in the future.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@felixonmars felixonmars force-pushed the inverted-resource-check branch 2 times, most recently from 58de62e to dcc6c72 Compare March 30, 2026 07:32
The wl_resource destroy callbacks in the personalization manager had
multiple lifetime and teardown bugs introduced by commit 56c8376.
The same class of bugs also existed in font_impl.cpp and
appearance_impl.cpp where they had been copy-pasted to new context
types:

1. Inverted null check: if (resource) return; caused the destroy
   handlers to return immediately, so cleanup never ran.
   (personalization_manager_impl.cpp only)

2. Double wl_list_remove: wl_list_remove(wl_resource_get_link(resource))
   is invalid inside the destroy callback because libwayland core
   (remove_and_destroy_resource) already calls wl_list_remove on
   resource->link BEFORE invoking the destroy callback.  Calling it a
   second time operates on stale prev/next pointers and corrupts the
   manager->resources list, producing a heap use-after-free write
   confirmed by Valgrind:
     "Invalid write of size 8 / Address is 32 bytes inside a block of
      size 128 free'd" in wl_list_remove <- remove_and_destroy_resource
      <- wl_client_destroy <- wl_display_flush_clients.
   Fixed in: personalization_manager_impl.cpp, font_impl.cpp,
             appearance_impl.cpp.

3. Missing wl_resource_set_user_data(resource, nullptr): without
   clearing user data before delete, any from_resource() call inside
   signal handlers emitted by beforeDestroy() could observe a dangling
   C++ object pointer.
   Fixed in: personalization_manager_impl.cpp, font_impl.cpp,
             appearance_impl.cpp.

4. Shared manager lifetime bug: the manager destroy callback must not
   delete treeland_personalization_manager_v1 from a single bound
   wl_resource destroy path, because the manager is shared across
   bindings/contexts and owned by the display lifetime.
   (personalization_manager_impl.cpp only)

This keeps per-resource context destruction 1:1 with their wl_resource,
while leaving the shared manager owned by create()/display teardown.
@felixonmars felixonmars force-pushed the inverted-resource-check branch from dcc6c72 to bf3ecc6 Compare March 30, 2026 08:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants