Skip to content

[reflectx] DeepCopy 环检测只挂 Pointer 分支——map/slice 自引用栈溢出打崩进程 #426

Closed

Description

@zy84338719

位置

oekit/pkg @ origin/main

  • reflectx/copy.go:93-101 —— case reflect.Pointer:visited[v.Pointer()] 登记 + 自引用环终止
  • reflectx/copy.go:54 —— case reflect.Map:无 visited 登记
  • reflectx/copy.go:64 —— case reflect.Slice:无 visited 登记

为什么错

环检测只挂在 Pointer 分支。但不经 Pointer 也能成环:

m := map[string]any{}
m["self"] = m        // map 自引用——Map 分支直接递归,visited 无登记
s := []any{nil}
s[0] = s              // slice 头自引用——同理

Pointer 分支的 visited[v.Pointer()] 只保护 *T 指针解引用环(copy.go:97-101 注释「自引用环在此终止」)——Map/Slice 分支对同族环零防护,递归深度无上限直至 goroutine stack exceeds fatal(进程崩溃,非 error)。

影响

拷贝含自引用/互引用 map、slice 的结构(缓存快照、父指针邻接表、序列化中间态)→ 整进程 stack overflow 崩溃;「深拷贝可返回 error」的调用方契约被 fatal 短路。#420 是 errors 链成环的同族问题(另一域,已单独立项),reflectx 这面是拷贝器本体。

修法

Map/Slice 分支同样防护。reflect 限制:v.Pointer() 可用于 Slice(首元素地址),Map 不可用——务实方案:

  1. Slice:v.Pointer() 进 visited(与 Pointer 分支同键语义);
  2. Map:v.Pointer() 不支持 → 深度上限(如 64 层)+ 显式错误返回,或以 reflect.ValueOf 之外的稳定键(如遍历父链比对 v.Len()+类型 启发式不可靠——直接深度上限最稳);
  3. 无论方案,环/超深必须返回 error 而非 fatal,对齐本包「拷贝可失败」的既有错误面;
  4. 回归测试:map 自引用、slice 自引用、双向互引 map 三例断言返回 error(非 crash)。

去重

Activity

  1. moved this from Todo to In Progress in oekit Issue 大盘on Nov 12, 2026
  2. added a commit that references this issue on Nov 12, 2026
  3. zy84338719 commented on Nov 12, 2026

    @zy84338719
    ContributorAuthor

    已合入修复 ✅(无 SemVer 发布:本次改动不发版本)

    变更内容

    reflectx DeepCopy Map/Slice 分支与 Pointer 同口径先注册再下探 visited,自引用不再 stack overflow

    合入:PR #429(https://github.com/oekit/pkg/pull/429),merge commit 6ee91ff5,2026-11-12T18:18:08Z

    CI:link ✅ / Lint & Test / Test ✅ / Lint & Test / Lint ✅ / Zero Third-Party Deps ✅

  4. moved this from In Progress to Done in oekit Issue 大盘on Nov 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions