vg_lite_hal: 修复空闲块合并不校验地址相邻 + 分配遍历加防死循环护栏 - #72
Open
zylugl wants to merge 1 commit into
Open
Conversation
在 Edgi-Talk(PSE84)上启用 LVGL VGLite GPU 渲染(GC555)后,遇到 UI 线程无声卡死(无断言、无 HardFault)。逐层定位到 `vg_lite_hal_allocate_contiguous()` 中堆链表遍历死循环,根本原因是本文件堆管理实现的两处缺陷:
### 缺陷 1:`vg_lite_hal_free_contiguous()` 合并不相邻空闲块
原实现合并前/后节点时只判断 `status == 0`(空闲),**不校验地址是否相邻**,并用 `min()` 调整 offset:
```c
if (pos->status == 0) {
node->size += pos->size;
if (node->offset > pos->offset)
node->offset = pos->offset; /* 两个不相邻块被合并成一个"假象块" */
...
}
```
当相邻链表节点对应的显存块并不连续时,会合并出一个覆盖空洞的"假象空闲块",其 size/offset 与实际不符;该块后续被分配出去即形成 use-after-free,进而写坏链表指针。
### 缺陷 2:`vg_lite_hal_allocate_contiguous()` 遍历无护栏
链表一旦被破坏(哪怕由其他原因,如越界写),反向遍历会沿损坏的 `prev` 指针无限循环或访问野指针,表现为整个线程卡死且无任何日志。
## 修复内容
1. **合并前校验地址相邻**:仅当邻居空闲且 `node->offset + node->size == pos->offset`(后邻)/ `pos->offset + pos->size == node->offset`(前邻)时才合并,同时把两个 for 循环简化为单次判断(原循环体末尾无条件 `break`,实际只执行一次)。
2. **分配遍历加护栏**:检测 NULL 指针、自环,并以 256 步为上限,发现链表损坏时打印错误并返回 `VG_LITE_OUT_OF_RESOURCES`,不再挂死调用线程。
## 验证
- 硬件:KIT_PSE84_EVAL_EPC2,RT-Thread 5.0.2,LVGL 9.2 + VGLite(`LV_USE_DRAW_VG_LITE=1`)
- 修复前:首帧渲染即挂死(栈溢出诱发堆链表损坏后,分配遍历死循环)
- 修复后:UI 正常渲染(填充、圆角、渐变、文本均走 GPU),长时间运行无异常;故意破坏链表时返回错误而非挂死
Collaborator
|
不建议直接修改英飞凌官方库文件的代码,如果有问题可以去英飞凌官方的仓库提交PR,谢谢 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
在 Edgi-Talk(PSE84)上启用 LVGL VGLite GPU 渲染(GC555)后,遇到 UI 线程无声卡死(无断言、无 HardFault)。逐层定位到
vg_lite_hal_allocate_contiguous()中堆链表遍历死循环,根本原因是本文件堆管理实现的两处缺陷:缺陷 1:
vg_lite_hal_free_contiguous()合并不相邻空闲块原实现合并前/后节点时只判断
status == 0(空闲),不校验地址是否相邻,并用min()调整 offset:当相邻链表节点对应的显存块并不连续时,会合并出一个覆盖空洞的"假象空闲块",其 size/offset 与实际不符;该块后续被分配出去即形成 use-after-free,进而写坏链表指针。
缺陷 2:
vg_lite_hal_allocate_contiguous()遍历无护栏链表一旦被破坏(哪怕由其他原因,如越界写),反向遍历会沿损坏的
prev指针无限循环或访问野指针,表现为整个线程卡死且无任何日志。修复内容
node->offset + node->size == pos->offset(后邻)/pos->offset + pos->size == node->offset(前邻)时才合并,同时把两个 for 循环简化为单次判断(原循环体末尾无条件break,实际只执行一次)。VG_LITE_OUT_OF_RESOURCES,不再挂死调用线程。验证
LV_USE_DRAW_VG_LITE=1)