Skip to content

Conversation

@18202781743
Copy link
Contributor

@18202781743 18202781743 commented Feb 11, 2026

Changed the context parameter in QObject::connect from 'this' to
'deviceItem' for the Device::pairedChanged signal connection. This
prevents potential dangling pointer issues when the deviceItem object
is deleted while signals are still being processed. The original code
used 'this' as context, which could lead to accessing invalid memory if
deviceItem was destroyed before the slot execution.

Influence:

  1. Test Bluetooth device pairing state changes
  2. Verify device removal and addition scenarios
  3. Check memory usage and stability during device operations
  4. Test with multiple Bluetooth adapters and devices
  5. Verify no crashes occur when devices are disconnected or removed

fix: 更改信号上下文以防止野指针问题

将 QObject::connect 中 Device::pairedChanged 信号的上下文参数从 'this'
改为 'deviceItem'。这可以防止当 deviceItem 对象被删除而信号仍在处理时可
能出现的野指针问题。原始代码使用 'this' 作为上下文,如果 deviceItem 在槽
函数执行前被销毁,可能导致访问无效内存。

Influence:

  1. 测试蓝牙设备配对状态变化
  2. 验证设备移除和添加场景
  3. 检查设备操作期间的内存使用和稳定性
  4. 测试多个蓝牙适配器和设备
  5. 验证设备断开或移除时不会发生崩溃

PMS: BUG-350859

Summary by Sourcery

Bug Fixes:

  • Prevent potential dangling pointer/use-after-free by binding Device::pairedChanged connection to the device item instead of the adapter item.

@sourcery-ai
Copy link

sourcery-ai bot commented Feb 11, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Adjusts the QObject::connect context for the Device::pairedChanged signal so that the connection is tied to the lifetime of the corresponding Bluetooth device UI item instead of the adapter item, preventing dangling-pointer access when the UI item is destroyed.

Sequence diagram for updated Device::pairedChanged connection context

sequenceDiagram
    participant BluetoothAdapterItem
    participant Device
    participant DeviceItem
    participant PluginStandardItem

    BluetoothAdapterItem->>Device: connect(Device::pairedChanged, context=deviceItem, lambda)
    BluetoothAdapterItem->>DeviceItem: create DeviceItem for Device

    rect rgb(230,230,250)
        Device->>DeviceItem: emit pairedChanged(paired)
        activate DeviceItem
        DeviceItem->>DeviceItem: lambda(paired)
        alt DeviceItem has valid device and standardItem
            DeviceItem->>DeviceItem: device()
            DeviceItem->>PluginStandardItem: standardItem()
            PluginStandardItem-->>PluginStandardItem: update pairing state
        else DeviceItem or device was destroyed
            DeviceItem-->>DeviceItem: lambda not invoked (auto disconnected)
        end
        deactivate DeviceItem
    end

    rect rgb(255,240,245)
        BluetoothAdapterItem-->>DeviceItem: destroy DeviceItem
        note over DeviceItem,Device: QObject disconnects connections with context=deviceItem
        Device-->>Device: later emit pairedChanged
        Device-->>Device: no slot invoked (connection removed)
    end
Loading

Class diagram for BluetoothAdapterItem and DeviceItem connection change

classDiagram
    class BluetoothAdapterItem {
        - adapter : Adapter*
        + onDeviceAdded(device : Device*) void
        + connectDevice(device : Device*, adapter : Adapter*) signal
    }

    class Device {
        + paired : bool
        + pairedChanged(paired : bool) signal
    }

    class DeviceItem {
        - devicePtr : Device*
        - standardItemPtr : PluginStandardItem*
        + device() Device*
        + standardItem() PluginStandardItem*
    }

    class PluginStandardItem {
        + setPaired(paired : bool) void
    }

    BluetoothAdapterItem --> Device : uses in onDeviceAdded
    BluetoothAdapterItem --> DeviceItem : creates deviceItem
    DeviceItem --> Device : holds
    DeviceItem --> PluginStandardItem : holds

    note for BluetoothAdapterItem "Device::pairedChanged connected with context=deviceItem instead of this"
Loading

File-Level Changes

Change Details Files
Tie Device::pairedChanged signal connection lifetime to the BluetoothDeviceItem instead of the BluetoothAdapterItem to avoid callbacks into freed memory.
  • Change QObject::connect context argument from the adapter item (this) to the per-device UI item (deviceItem) for the Device::pairedChanged signal.
  • Keep the lambda capture and body intact so the behavior on paired state changes is unchanged aside from the connection’s lifetime semantics.
plugins/dde-dock/bluetooth/componments/bluetoothadapteritem.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

@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 found 1 issue, and left some high level feedback:

  • Changing the connection context to deviceItem helps, but the lambda still captures this, so if the adapter item is destroyed before the slot runs, you can still get a dangling pointer; consider removing the capture of this or restructuring the logic so it doesn’t rely on the adapter’s lifetime inside this slot.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Changing the connection context to `deviceItem` helps, but the lambda still captures `this`, so if the adapter item is destroyed before the slot runs, you can still get a dangling pointer; consider removing the capture of `this` or restructuring the logic so it doesn’t rely on the adapter’s lifetime inside this slot.

## Individual Comments

### Comment 1
<location> `plugins/dde-dock/bluetooth/componments/bluetoothadapteritem.cpp:230` </location>
<code_context>
         }
     });
-    connect(device, &Device::pairedChanged, this, [this, deviceItem](const bool paired) {
+    connect(device, &Device::pairedChanged, deviceItem, [this, deviceItem](const bool paired) {
         if (deviceItem && deviceItem->device()) {
             PluginStandardItem *item = deviceItem->standardItem();
</code_context>

<issue_to_address>
**issue (bug_risk):** Changing the connection context to `deviceItem` while still capturing `this` can introduce a use-after-free risk.

With `this` as the old connection context, destroying `BluetoothAdapterItem` automatically disconnected the signal, so any lambda capturing `this` could no longer run. Now the context is `deviceItem`, but the lambda still captures `this`, so if `BluetoothAdapterItem` is destroyed while `deviceItem` is still alive and `Device::pairedChanged` is emitted, the lambda may dereference a dangling `this`.

Since the lambda body doesn’t use `this`, you can safely drop it from the capture list (e.g. `[deviceItem]`, or `[]` if you access `deviceItem` another way). If you do need `this`, either keep `this` as the connection context or use a safe indirection such as `QPointer` to avoid a potential use-after-free.
</issue_to_address>

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.

}
});
connect(device, &Device::pairedChanged, this, [this, deviceItem](const bool paired) {
connect(device, &Device::pairedChanged, deviceItem, [this, deviceItem](const bool paired) {
Copy link

Choose a reason for hiding this comment

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

issue (bug_risk): Changing the connection context to deviceItem while still capturing this can introduce a use-after-free risk.

With this as the old connection context, destroying BluetoothAdapterItem automatically disconnected the signal, so any lambda capturing this could no longer run. Now the context is deviceItem, but the lambda still captures this, so if BluetoothAdapterItem is destroyed while deviceItem is still alive and Device::pairedChanged is emitted, the lambda may dereference a dangling this.

Since the lambda body doesn’t use this, you can safely drop it from the capture list (e.g. [deviceItem], or [] if you access deviceItem another way). If you do need this, either keep this as the connection context or use a safe indirection such as QPointer to avoid a potential use-after-free.

BLumia
BLumia previously approved these changes Feb 11, 2026
Changed the context parameter in QObject::connect from 'this' to
'deviceItem' for the Device::pairedChanged signal connection. This
prevents potential dangling pointer issues when the deviceItem object
is deleted while signals are still being processed. The original code
used 'this' as context, which could lead to accessing invalid memory if
deviceItem was destroyed before the slot execution.

Influence:
1. Test Bluetooth device pairing state changes
2. Verify device removal and addition scenarios
3. Check memory usage and stability during device operations
4. Test with multiple Bluetooth adapters and devices
5. Verify no crashes occur when devices are disconnected or removed

fix: 更改信号上下文以防止野指针问题

将 QObject::connect 中 Device::pairedChanged 信号的上下文参数从 'this'
改为 'deviceItem'。这可以防止当 deviceItem 对象被删除而信号仍在处理时可
能出现的野指针问题。原始代码使用 'this' 作为上下文,如果 deviceItem 在槽
函数执行前被销毁,可能导致访问无效内存。

Influence:
1. 测试蓝牙设备配对状态变化
2. 验证设备移除和添加场景
3. 检查设备操作期间的内存使用和稳定性
4. 测试多个蓝牙适配器和设备
5. 验证设备断开或移除时不会发生崩溃

PMS: BUG-350859
@deepin-ci-robot
Copy link

deepin pr auto review

这段代码是关于 DDE 桌面环境蓝牙插件中 BluetoothAdapterItem 类的修改。经过审查,主要涉及版权年份更新和信号槽连接的上下文对象调整。以下是详细的审查意见:

1. 代码逻辑与语法分析

修改点 1:版权年份更新

-// SPDX-FileCopyrightText: 2016 - 2022 UnionTech Software Technology Co., Ltd.
+// SPDX-FileCopyrightText: 2016 - 2026 UnionTech Software Technology Co., Ltd.
  • 分析:这仅是元数据的更新,不影响程序逻辑。
  • 建议:确保 2026 年是预期的维护截止年份,通常建议根据实际维护情况动态更新,或者直接省略结束年份(例如 2016 -)以表示持续维护。

修改点 2:信号槽连接上下文对象修改

-    connect(device, &Device::pairedChanged, this, [this, deviceItem](const bool paired) {
+    connect(device, &Device::pairedChanged, deviceItem, [this, deviceItem](const bool paired) {
  • 分析
    • 原代码connect(sender, signal, this, lambda)。接收者是 BluetoothAdapterItem(即 this)。这意味着只要 BluetoothAdapterItem 存在,连接就保持有效。
    • 修改后connect(sender, signal, deviceItem, lambda)。接收者变成了 deviceItem。这意味着当 deviceItem 被销毁(例如蓝牙设备移除)时,Qt 会自动断开这个连接。
  • 逻辑影响:这是一个非常关键的改进
    • 原代码潜在风险:如果 deviceItem 被删除了,但 BluetoothAdapterItem 还在,且 device 对象依然发出了 pairedChanged 信号,Lambda 表达式会被执行。此时 Lambda 捕获的 deviceItem 指针变成了悬空指针(Dangling Pointer)。虽然 Lambda 内部有 if (deviceItem && ...) 的检查,但访问已释放内存的指针本身在 C++ 中属于未定义行为,可能导致程序崩溃。
    • 修改后优势:将上下文设置为 deviceItem,确保了当 deviceItem 析构时,信号连接自动断开。Lambda 表达式将不再被调用,从而安全地避免了悬空指针的访问。

2. 代码质量与规范

  • Lambda 捕获:Lambda 中捕获了 [this, deviceItem]
    • this 是必须的,因为需要访问成员或发射信号。
    • deviceItem 是必须的,用于在回调中操作具体的设备项。
    • 由于修改了上下文对象为 deviceItem,Qt 保证了 deviceItem 存在时 Lambda 才会被调用,因此代码安全性得到了提升。
  • Lambda 内部检查if (deviceItem && deviceItem->device())
    • 在修改上下文为 deviceItem 后,deviceItem 为空指针的可能性大大降低(除非手动传入空指针,但在此处 onDeviceAdded 逻辑中似乎不太可能)。
    • 保留这个检查是良好的防御性编程习惯,建议保留。

3. 代码性能

  • 性能影响:无显著性能影响。connect 操作仅在添加设备时执行一次。修改上下文对象不会增加运行时开销。

4. 代码安全

  • 安全性提升:如逻辑分析所述,该修改显著提高了内存安全性,有效防止了“Use-After-Free”(释放后使用)类型的崩溃。
  • 潜在隐患检查
    • 需要确认 deviceItem 的生命周期是否严格受控。如果 deviceItem 是在栈上创建或者被其他机制提前销毁,而 device 对象(信号发送者)依然存在并活跃,那么断开连接是期望的行为。
    • 如果 device 对象的生命周期短于 deviceItem,则此修改无副作用。
    • 结论:在典型的 Qt Model/Item 架构中,Item 通常随数据(Device)的移除而销毁,因此将连接绑定到 Item 的生命周期是正确的做法。

总结与改进建议

这段代码的修改是正确且必要的,主要解决了潜在的内存访问安全问题。

改进建议:

  1. 版权年份:建议确认 2026 是否为硬性截止日期,或者考虑改为 2016 - 以表示持续维护。
  2. 代码注释:鉴于这是一个涉及内存安全的关键修改,建议在代码旁添加简短注释,说明为何将上下文设置为 deviceItem(即:确保在设备项销毁时自动断开连接,防止悬空指针访问)。

建议添加的注释示例:

    // 使用 deviceItem 作为上下文对象,确保在 deviceItem 销毁时自动断开连接,防止访问悬空指针
    connect(device, &Device::pairedChanged, deviceItem, [this, deviceItem](const bool paired) {
        if (deviceItem && deviceItem->device()) {
            // ... 原有逻辑

@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: 18202781743, BLumia

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

@18202781743 18202781743 merged commit 1cd2097 into linuxdeepin:master Feb 12, 2026
10 checks passed
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.

3 participants