Chrome · V8
CVE-2026-14409
Logic Error in V8
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
GetConstructorHelpersrc/objects/js-objects.cc |
modified | |
JSGlobalObjectsrc/objects/js-objects.h |
modified | |
JSGlobalProxysrc/objects/js-objects.h |
modified |
Files Changed
src/objects/js-function.ccsrc/objects/js-function.hsrc/objects/js-objects.ccsrc/objects/js-objects.hsrc/objects/lookup.ccsrc/objects/lookup.h
Patch
From 5b5f77018c9296911170b4f886570c1735e97919 Mon Sep 17 00:00:00 2001 From: Dominik Inführ <[email protected]> Date: Tue, 19 May 2026 15:24:07 +0200 Subject: [PATCH] [objects] Prevent allocations in JSReceiver::GetConstructor() The heap snapshot generator uses GetConstructor() to provide a better object name. However, this method allocates in some cases. This CL removes this allocation by passing the already existing AllocationPolicy to the GetDebugName() methods as well. Bug: 513810921 Change-Id: I3f7abd2c7bfb5cf61d25390a77d7718d6409f1b5 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7858355 Commit-Queue: Dominik Inführ <[email protected]> Reviewed-by: Igor Sheludko <[email protected]> Cr-Commit-Position: refs/heads/main@{#107510} --- diff --git a/src/objects/js-function.cc b/src/objects/js-function.cc index 119c7f3..d6a945f 100644 --- a/src/objects/js-function.cc +++ b/src/objects/js-function.cc @@ -1366,7 +1366,8 @@ } // namespace DirectHandle<String> JSFunction::GetDebugName( - Isolate* isolate, DirectHandle<JSFunction> function) { + Isolate* isolate, DirectHandle<JSFunction> function, + AllowAllocation allow_allocation) { // Below we use the same fast-path that we already established for // Function.prototype.bind(), where we avoid a slow "name" property // lookup if the DescriptorArray for the |function| still has the @@ -1386,7 +1387,7 @@ if (IsString(*name)) return Cast<String>(name); } return SharedFunctionInfo::DebugName( - isolate, direct_handle(function->shared(), isolate)); + isolate, direct_handle(function->shared(), isolate), allow_allocation); } bool JSFunction::SetName(Isolate* isolate, DirectHandle<JSFunction> function, diff --git a/src/objects/js-function.h b/src/objects/js-function.h index 18d98f3..89e6b75 100644 --- a/src/objects/js-function.h +++ b/src/objects/js-function.h @@ -455,8 +455,9 @@ // The function's name if it is configured, otherwise shared function info // debug name. - static DirectHandle<String> GetDebugName(Isolate* isolate, - DirectHandle<JSFunction> function); + static DirectHandle<String> GetDebugName( + Isolate* isolate, DirectHandle<JSFunction> function, + AllowAllocation allow_allocation = AllowAllocation::kYes); // The function's string representation implemented according to // ES6 section 19.2.3.5 Function.prototype.toString ( ). diff --git a/src/objects/js-objects.cc b/src/objects/js-objects.cc index 77bc101..f218fd6 100644 --- a/src/objects/js-objects.cc +++ b/src/objects/js-objects.cc @@ -168,7 +168,7 @@ } Handle<Object> JSReceiver::GetDataProperty(LookupIterator* it, - AllocationPolicy allocation_policy) { + AllowAllocation allow_allocation) { for (;; it->Next()) { switch (it->state()) { case LookupIterator::INTERCEPTOR: @@ -209,7 +209,7 @@ case LookupIterator::TYPED_ARRAY_INDEX_NOT_FOUND: return it->isolate()->factory()->undefined_value(); case LookupIterator::DATA: - return it->GetDataValue(allocation_policy); + return it->GetDataValue(allow_allocation); case LookupIterator::NOT_FOUND: return it->isolate()->factory()->undefined_value(); case LookupIterator::MODULE_NAMESPACE: { @@ -601,6 +601,7 @@ namespace { std::pair<MaybeDirectHandle<JSFunction>, DirectHandle<String>> GetConstructorHelper(Isolate* isolate, DirectHandle<JSReceiver> receiver) { + DisallowGarbageCollection no_gc; // If the object was instantiated simply with base == new.target, the // constructor on the map provides the most accurate name. // Don't provide the info for prototypes, since their constructors are @@ -613,7 +614,7 @@ DirectHandle<JSFunction> constructor = Cast<JSFunction>(maybe_constructor); DirectHandle<String> name = - JSFunction::GetDebugName(isolate, constructor); + JSFunction::GetDebugName(isolate, constructor, AllowAllocation::kNo); if (name->length() != 0 && !name->Equals(ReadOnlyRoots(isolate).Object_string())) { return std::make_pair(indirect_handle(constructor, isolate), name); @@ -636,8 +637,8 @@ LookupIterator it_to_string_tag( isolate, receiver, isolate->factory()->to_string_tag_symbol(), current, LookupIterator::OWN_SKIP_INTERCEPTOR); - auto maybe_to_string_tag = JSReceiver::GetDataProperty( - &it_to_string_tag, AllocationPolicy::kAllocationDisallowed); + auto maybe_to_string_tag = + JSReceiver::GetDataProperty(&it_to_string_tag, AllowAllocation::kNo); if (IsString(*maybe_to_string_tag)) { return std::make_pair(MaybeHandle<JSFunction>(), Cast<String>(maybe_to_string_tag)); @@ -673,12 +674,13 @@ LookupIterator it_constructor( isolate, receiver, isolate->factory()->constructor_string(), current, LookupIterator::OWN_SKIP_INTERCEPTOR); - auto maybe_constructor = JSReceiver::GetDataProperty( - &it_constructor, AllocationPolicy::kAllocationDisallowed); + auto maybe_constructor = + JSReceiver::GetDataProperty(&it_constructor, AllowAllocation::kNo); if (IsJSFunction(*maybe_constructor)) { auto constructor = Cast<JSFunction>(maybe_constructor); auto name = SharedFunctionInfo::DebugName( - isolate, direct_handle(constructor->shared(), isolate)); + isolate, direct_handle(constructor->shared(), isolate), + AllowAllocation::kNo); if (name->length() != 0 && !name->Equals(ReadOnlyRoots(isolate).Object_string())) { diff --git a/src/objects/js-objects.h b/src/objects/js-objects.h index 2585096..9ef4c49 100644 --- a/src/objects/js-objects.h +++ b/src/objects/js-objects.h @@ -23,10 +23,6 @@ namespace v8::internal { -// Enum for functions that offer a second mode that does not cause allocations. -// Used in conjunction with LookupIterator and unboxed double fields. -enum class AllocationPolicy { kAllocationAllowed, kAllocationDisallowed }; - enum InstanceType : uint16_t; class JSGlobalObject; class JSGlobalProxy; @@ -335,8 +331,8 @@ DirectHandle<JSReceiver> object, DirectHandle<Name> name); V8_EXPORT_PRIVATE static Handle<Object> GetDataProperty( - LookupIterator* it, AllocationPolicy allocation_policy = - AllocationPolicy::kAllocationAllowed); + LookupIterator* it, + AllowAllocation allow_allocation = AllowAllocation::kYes); // Retrieves a permanent object identity hash code. The undefined value might // be returned in case no hash was created yet. diff --git a/src/objects/lookup.cc b/src/objects/lookup.cc index 681b70c..bf5ba6a 100644 --- a/src/objects/lookup.cc +++ b/src/objects/lookup.cc @@ -996,7 +996,7 @@ } DirectHandle<Object> LookupIterator::FetchValue( - AllocationPolicy allocation_policy) const { + AllowAllocation allow_allocation) const { Tagged<Object> result; DCHECK_NE(state_, STRING_LOOKUP_START_OBJECT); DCHECK(!IsWasmObject(*holder_)); @@ -1020,8 +1020,8 @@ DirectHandle<JSObject> holder = GetHolder<JSObject>(); FieldIndex field_index = FieldIndex::ForDetails(holder->map(), property_details_); - if (allocation_policy == AllocationPolicy::kAllocationDisallowed && - field_index.is_inobject() && field_index.is_double()) { + if (allow_allocation == AllowAllocation::kNo && field_index.is_inobject() && + field_index.is_double()) { return isolate_->factory()->undefined_value(); } return JSObject::FastPropertyAt( @@ -1132,7 +1132,7 @@ } Handle<Object> LookupIterator::GetStringPropertyValue( - AllocationPolicy allocation_policy) const { + AllowAllocation allow_allocation) const { DCHECK_EQ(state_, STRING_LOOKUP_START_OBJECT); if (IsElement()) { DirectHandle<String> string = Cast<String>(lookup_start_object_); @@ -1149,9 +1149,9 @@ } Handle<Object> LookupIterator::GetDataValue( - AllocationPolicy allocation_policy) const { + AllowAllocation allow_allocation) const { DCHECK_EQ(DATA, state_); - return indirect_handle(FetchValue(allocation_policy), isolate_); + return indirect_handle(FetchValue(allow_allocation), isolate_); } DirectHandle<Object> LookupIterator::GetDataValue(SeqCstAccessTag tag) const { diff --git a/src/objects/lookup.h b/src/objects/lookup.h index f1807b2..d5666a3 100644 --- a/src/objects/lookup.h +++ b/src/objects/lookup.h @@ -262,10 +262,9 @@
Loading diff…
Original Bug Report
The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.
References
On This Page