fix(desk): 清空共享区槽表并按版本拒绝旧 app

现场:所有窗口消失、任务栏多出若干图标,点击后 explorer 以
[0E] rip=0x4061e8 cr2=0x1207e8fff 缺页退出。

原因:desk_format 只清 DeskHeader,没有清 0x100 起的 WinSlot 表。
DESK_SHM_SIZE 从 8MB 提到 32MB 后,mm.malloc 拿到的内存不再恰好全零
(混入 bootloader/固件遗留数据),随机 used/active 被当成窗口,
合成时按垃圾 fb_off 越界读像素。

- desk_format 先 memset 整个控制区(0x000000 ~ 0x200000)
- 分配槽位时整槽清零,避免复用残留
- DESK_VERSION 1 → 2,desk_ready 校验版本:
  旧 app 按旧 WinSlot 偏移读写会写坏共享区,现在直接拒绝挂载
- render_window_rows 校验 fb_off 范围,坏槽位只跳过,不再拖崩合成器
This commit is contained in:
TermiNexus committed 2026-10-27 12:52:23 +08:00
1 parent 8e94458fc2
commit 6ecd891f64
2 files changed
+14 -1

No files matched your search

+6
View File
@@ -459,6 +459,8 @@ class DeskServer:
for i in range(desk.DESK_MAX_WIN):
s: desk.WinSlot* = self.slot(i)
if s.used == 0:
# 槽位复用前整块清零:避免上一任窗口的 pid/几何/缓冲区偏移残留。
string.memset(s, 0, desk.desk_slot_size())
cap_px: int = w * content_h
buf_off: uint32 = desk.desk_arena_alloc(self.shm, uint32(cap_px) * uint32(4))
if buf_off == uint32(0): return -1
@@ -1202,6 +1204,10 @@ class DeskServer:
buf: uint32* = uint32*(self.shm + uint64(s.fb_off))
fw: int = int(s.fb_w)
fh: int = int(s.fb_h)
# 槽表被写坏时宁可跳过该窗口,也不要按越界 fb_off 读像素把整个合成器带崩。
need_bytes: uint64 = uint64(fw) * uint64(fh) * uint64(4)
if s.fb_off < uint32(desk.DESK_OFF_ARENA) or uint64(s.fb_off) + need_bytes > uint64(desk.DESK_SHM_SIZE):
return
content_y0: int = wy + th + TITLE_GAP
r: int = WIN_RADIUS
yy: int = y0
+8 -1
View File
@@ -29,7 +29,7 @@ from stdint import *
# 32MB:1920×1080 全屏窗口的内容缓冲约 7.3MB,最大化需要足够 arena。
define DESK_SHM_SIZE = 33554432
define DESK_MAGIC = 0x4B534544 # 'DESK'
define DESK_VERSION = 1
define DESK_VERSION = 2 # WinSlot 布局变更必须 +1,旧 app 拒绝挂载
define DESK_MAX_WIN = 8
define DESK_TITLE_MAX = 32
@@ -213,6 +213,9 @@ def desk_map(fd: int) -> uint64:
def desk_format(base: uint64, fb_w: uint32, fb_h: uint32, fb_pitch: uint32):
"""explorer 专用:初始化共享区头与各环。"""
# 先清空整个控制区(头 + 窗口槽表 + 各环):共享区来自 mm.malloc,不能假设为 0。
# 否则槽表里的随机 used/active 会被当成"多出来的窗口",合成器还会按垃圾 fb_off 取像素。
string.memset(rawptr(base), 0, uint64(DESK_OFF_ARENA))
h: DeskHeader* = DeskHeader*(base + desk_header_off())
string.memset(h, 0, DeskHeader.__sizeof__())
h.magic = uint32(DESK_MAGIC)
@@ -236,6 +239,10 @@ def desk_ready(base: uint64) -> int:
h: DeskHeader* = DeskHeader*(base + desk_header_off())
if h.magic != uint32(DESK_MAGIC):
return 0
# 共享结构布局变了(WinSlot 增字段)就拒绝挂载:旧 app 按错偏移读写会把
# 头部/槽表/别人的像素缓冲写坏,比"连不上"危险得多。
if h.version != uint32(DESK_VERSION):
return 0
return h.ready
def desk_arena_alloc(base: uint64, size: uint32) -> uint32: