CVE-2026-10935
Overview
Files Changed
src/ast/scopes.cctest/message/fail/regress-tdz-closure.jstest/message/fail/regress-tdz-closure.out
Patch
From ad07ea9d88fd5c2a529d35fb4ebec046f5404b99 Mon Sep 17 00:00:00 2001 From: Toon Verwaest <[email protected]> Date: Tue, 14 Apr 2026 17:52:20 +0200 Subject: [PATCH] [ast] Fix hole check elision for hoisted functions in sloppy eval - Move the hoisting check before the dynamic scope check in Scope::Lookup to ensure access_position is correctly updated for hoisted functions before entering LookupSloppyEval. - Propagate the hole check requirement from the shadowed local variable to the dynamic proxy for kDynamicLocal variables. Bug: 501898683 Change-Id: Iadd58a8161cff6911eb113aa24a5e2a2f6564969 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7749487 Commit-Queue: Toon Verwaest <[email protected]> Reviewed-by: Leszek Swirski <[email protected]> Commit-Queue: Leszek Swirski <[email protected]> Auto-Submit: Toon Verwaest <[email protected]> Cr-Commit-Position: refs/heads/main@{#106473} --- diff --git a/src/ast/scopes.cc b/src/ast/scopes.cc index c002a08..66e2137 100644 --- a/src/ast/scopes.cc +++ b/src/ast/scopes.cc @@ -1154,6 +1154,7 @@ DCHECK(was_added); var->AllocateTo(location, index); var->set_initializer_position(lookup_result.initializer_position); + return var; } @@ -2278,6 +2279,12 @@ } if (scope->outer_scope_ == outer_scope_end) break; + if (scope->is_hoisted_in_context()) { + *access_position = scope->outer_scope()->start_position(); + } else if (scope->is_eval_scope()) { + *access_position = scope->AsDeclarationScope()->eval_position(); + } + if (V8_UNLIKELY(scope->is_dynamic_scope())) { DCHECK(!scope->is_script_scope()); if (scope->is_declaration_scope() && @@ -2293,12 +2300,6 @@ CHECK(scope->is_debug_evaluate_scope()); return cache_scope->NonLocal(proxy->raw_name(), VariableMode::kDynamic); } - - if (scope->is_hoisted_in_context()) { - *access_position = scope->outer_scope()->start_position(); - } else if (scope->is_eval_scope()) { - *access_position = scope->AsDeclarationScope()->eval_position(); - } force_context_allocation |= scope->is_function_scope(); scope = scope->outer_scope_; diff --git a/test/message/fail/regress-tdz-closure.js b/test/message/fail/regress-tdz-closure.js new file mode 100644 index 0000000..7c2135a --- /dev/null +++ b/test/message/fail/regress-tdz-closure.js @@ -0,0 +1,12 @@ +// Copyright 2026 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +(() => { + const v1 = __f_9(); + function __f_9() { + const v5 = new Map(); + v5.set(v1); + eval(""); + } +})(); diff --git a/test/message/fail/regress-tdz-closure.out b/test/message/fail/regress-tdz-closure.out new file mode 100644 index 0000000..cec5663 --- /dev/null +++ b/test/message/fail/regress-tdz-closure.out @@ -0,0 +1,10 @@ +# Copyright 2026 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +*%(basename)s:9: ReferenceError: Cannot access 'v1' before initialization + v5.set(v1); + ^ +ReferenceError: Cannot access 'v1' before initialization + at __f_9 (*%(basename)s:9:16) + at *%(basename)s:6:16 + at *%(basename)s:12:3
Regression Test / PoC
diff --git a/test/message/fail/regress-tdz-closure.js b/test/message/fail/regress-tdz-closure.js
new file mode 100644
index 0000000..7c2135a
--- /dev/null
+++ b/test/message/fail/regress-tdz-closure.js
@@ -0,0 +1,12 @@
+// Copyright 2026 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(() => {
+ const v1 = __f_9();
+ function __f_9() {
+ const v5 = new Map();
+ v5.set(v1);
+ eval("");
+ }
+})();
diff --git a/test/message/fail/regress-tdz-closure.out b/test/message/fail/regress-tdz-closure.out
new file mode 100644
index 0000000..cec5663
--- /dev/null
+++ b/test/message/fail/regress-tdz-closure.out
@@ -0,0 +1,10 @@
+# Copyright 2026 the V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+*%(basename)s:9: ReferenceError: Cannot access 'v1' before initialization
+ v5.set(v1);
+ ^
+ReferenceError: Cannot access 'v1' before initialization
+ at __f_9 (*%(basename)s:9:16)
+ at *%(basename)s:6:16
+ at *%(basename)s:12:3
Original Bug Report
DCHECK failure in instance_type != HOLE_TYPE in objects-inl.h
Detailed Report: https://clusterfuzz.com/testcase?key=5458184361771008
Fuzzer: None Job Type: linux_asan_d8_v8_arm_dbg Platform Id: linux
Crash Type: DCHECK failure Crash Address: Crash State: instance_type != HOLE_TYPE in objects-inl.h
Sanitizer: address (ASAN)
Regressed: https://clusterfuzz.com/revisions?job=linux_asan_d8_v8_arm_dbg&range=106396:106397
Reproducer Testcase: https://clusterfuzz.com/download?testcase_id=5458184361771008
Issue filed automatically.
To reproduce this, please build the target in this report and run it against the reproducer testcase. Please use the GN arguments provided at bottom of this report when building the binary.
If you have trouble reproducing, please also export the environment variables listed under “[Environment]” in the crash stacktrace.
If you have any feedback on reproducing test cases, let us know at https://forms.gle/Yh3qCYFveHj6E5jz5 so we can improve.