ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

systematic-debugging - defense-in-depth

systematic-debugging - defense-in-depth 纵深防御验证概述当您修复一个由无效数据引起的 Bug 时在一个地方添加验证似乎就足够了。但这一处检查可能会被不同的代码路径、重构或模拟mock绕过。核心原则在数据经过的每一层都进行验证。让这个 Bug 在结构上变得不可能。为什么需要多层单层验证“我们修好了这个 Bug”多层验证“我们让这个 Bug 变得不可能”不同层能捕获不同情况入口验证捕获大多数 Bug业务逻辑捕获边界情况环境守卫防止特定上下文中的危险调试日志在其他层失效时提供帮助四层验证第 1 层入口点验证目的在 API 边界拒绝明显无效的输入functioncreateProject(name:string,workingDirectory:string){if(!workingDirectory||workingDirectory.trim()){thrownewError(workingDirectory cannot be empty);}if(!existsSync(workingDirectory)){thrownewError(workingDirectory does not exist:${workingDirectory});}if(!statSync(workingDirectory).isDirectory()){thrownewError(workingDirectory is not a directory:${workingDirectory});}// ... 继续}第 2 层业务逻辑验证目的确保数据对该操作有意义functioninitializeWorkspace(projectDir:string,sessionId:string){if(!projectDir){thrownewError(projectDir required for workspace initialization);}// ... 继续}第 3 层环境守卫目的防止特定上下文中的危险操作asyncfunctiongitInit(directory:string){// 在测试中拒绝在临时目录之外执行 git initif(process.env.NODE_ENVtest){constnormalizednormalize(resolve(directory));consttmpDirnormalize(resolve(tmpdir()));if(!normalized.startsWith(tmpDir)){thrownewError(Refusing git init outside temp dir during tests:${directory});}}// ... 继续}第 4 层调试插桩目的为事后分析捕获上下文asyncfunctiongitInit(directory:string){conststacknewError().stack;logger.debug(About to git init,{directory,cwd:process.cwd(),stack,});// ... 继续}应用此模式当您发现一个 Bug 时追踪数据流- 错误值从哪里产生在哪里被使用梳理所有检查点- 列出数据经过的每一个点在每一层添加验证- 入口、业务、环境、调试测试每一层- 尝试绕过第 1 层验证第 2 层能否捕获会话中的实例Bug空的projectDir导致在源码目录执行git init数据流测试设置 → 空字符串Project.create(name, )WorkspaceManager.createWorkspace()在process.cwd()中执行git init添加的四层第 1 层Project.create()验证非空/存在/可写第 2 层WorkspaceManager验证 projectDir 非空第 3 层WorktreeManager在测试中拒绝在 tmpdir 之外执行 git init第 4 层执行 git init 前记录堆栈跟踪结果全部 1847 个测试通过Bug 无法复现关键见解四层都是必要的。在测试过程中每一层都捕获了其他层遗漏的 Bug不同的代码路径绕过了入口验证模拟mock绕过了业务逻辑检查不同平台上的边界情况需要环境守卫调试日志识别出结构性误用不要止步于一个验证点。在每一层都添加检查。
返回列表