[P1/高] SearchFilesTool walkDir 递归无深度限制,可触发栈溢出或长时间阻塞 #21

Open
opened 2026-07-21 21:55:49 +08:00 by thzxx · 0 comments
Owner

问题类型

缺陷 / 高 / 工具系统

文件位置

electron/harness/tools/built-in/filesystem.ts (SearchFilesTool)

问题描述

SearchFilesTool.walkDir 递归遍历目录,未限制:

  1. 递归深度:深层嵌套目录会触发栈溢出
  2. 总文件数:百万级文件会长时间阻塞主进程
  3. 符号链接循环:A -> B -> A 形成循环导致死循环

影响

  • 工具调用挂起或崩溃
  • 主进程阻塞导致 UI 无响应

建议修复

async walkDir(root: string, callback: (path) => void, options: {
  maxDepth: number = 20;
  maxFiles: number = 100_000;
  followSymlinks: boolean = false;
} = {}) {
  const visited = new Set<string>();
  let fileCount = 0;

  async function walk(current: string, depth: number) {
    if (depth > options.maxDepth || fileCount > options.maxFiles) return;

    const real = realpathSync(current);
    if (visited.has(real)) return; // 防止循环
    visited.add(real);

    const entries = await readdir(current, { withFileTypes: true });
    for (const entry of entries) {
      if (++fileCount > options.maxFiles) break;
      const fullPath = join(current, entry.name);
      if (entry.isDirectory()) {
        if (options.followSymlinks || !entry.isSymbolicLink()) {
          await walk(fullPath, depth + 1);
        }
      } else {
        callback(fullPath);
      }
    }
  }

  await walk(root, 0);
}

同时考虑用 worker_threads 避免阻塞主进程。

## 问题类型 缺陷 / 高 / 工具系统 ## 文件位置 `electron/harness/tools/built-in/filesystem.ts` (SearchFilesTool) ## 问题描述 SearchFilesTool.walkDir 递归遍历目录,未限制: 1. **递归深度**:深层嵌套目录会触发栈溢出 2. **总文件数**:百万级文件会长时间阻塞主进程 3. **符号链接循环**:A -> B -> A 形成循环导致死循环 ## 影响 - 工具调用挂起或崩溃 - 主进程阻塞导致 UI 无响应 ## 建议修复 ```ts async walkDir(root: string, callback: (path) => void, options: { maxDepth: number = 20; maxFiles: number = 100_000; followSymlinks: boolean = false; } = {}) { const visited = new Set<string>(); let fileCount = 0; async function walk(current: string, depth: number) { if (depth > options.maxDepth || fileCount > options.maxFiles) return; const real = realpathSync(current); if (visited.has(real)) return; // 防止循环 visited.add(real); const entries = await readdir(current, { withFileTypes: true }); for (const entry of entries) { if (++fileCount > options.maxFiles) break; const fullPath = join(current, entry.name); if (entry.isDirectory()) { if (options.followSymlinks || !entry.isSymbolicLink()) { await walk(fullPath, depth + 1); } } else { callback(fullPath); } } } await walk(root, 0); } ``` 同时考虑用 worker_threads 避免阻塞主进程。
thzxx added the ??????? labels 2026-07-21 21:55:49 +08:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: MetonaTeam/metona-ai-desktop#21