Chrome · V8
CVE-2025-13721
Race in V8
Overview
Medium
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Files Changed
src/objects/js-objects-inl.h
Patch
From b8b01791845cb77d5482f299310e9bfdcd012842 Mon Sep 17 00:00:00 2001
From: Nikolaos Papaspyrou <nikolaos@chromium.org>
Date: Tue, 21 Oct 2025 13:31:10 +0200
Subject: [PATCH] [objects] Avoid race in JSObject::GetEmbedderFieldCount
This CL fixes JSObject::GetEmbedderFieldCount, so that it only reads
the map's instance size field once. This avoids calculating an
inconsistent result, in case the map is concurrently updated.
Bug: 355120682
Change-Id: Ia6e003896998227b5b5bd88cc480b4bc1adbf9f2
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7066814
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Nikolaos Papaspyrou <nikolaos@chromium.org>
Cr-Commit-Position: refs/heads/main@{#103247}
---
diff --git a/src/objects/js-objects-inl.h b/src/objects/js-objects-inl.h
index f439860..e2d85ab 100644
--- a/src/objects/js-objects-inl.h
+++ b/src/objects/js-objects-inl.h
@@ -352,16 +352,22 @@
// static
int JSObject::GetEmbedderFieldCount(Tagged<Map> map) {
- int instance_size = map->instance_size();
+ // We inline some code from Map::instance_size and Map::GetInObjectProperties
+ // here, to avoid reading the map's instance size field twice.
+ // See https://crbug.com/355120682.
+ int instance_size_in_words = map->instance_size_in_words();
+ int instance_size = instance_size_in_words << kTaggedSizeLog2;
if (instance_size == kVariableSizeSentinel) return 0;
// Embedder fields are located after the object header, whereas in-object
// properties are located at the end of the object. We don't have to round up
// the header size here because division by kEmbedderDataSlotSizeInTaggedSlots
// will swallow potential padding in case of (kTaggedSize !=
// kSystemPointerSize) anyway.
+ int in_object_properties =
+ instance_size_in_words - map->GetInObjectPropertiesStartInWords();
return (((instance_size - GetEmbedderFieldsStartOffset(map)) >>
kTaggedSizeLog2) -
- map->GetInObjectProperties()) /
+ in_object_properties) /
kEmbedderDataSlotSizeInTaggedSlots;
}
Loading diff…
Original Bug Report
reported by ma...@google.com
cctest/test-inobject-slack-tracking/SubclassTypedArrayBuiltinNoInlineNew starts flaking
Failing test: cctest/test-inobject-slack-tracking/SubclassTypedArrayBuiltinNoInlineNew Failure link: https://cr-buildbucket.appspot.com/build/8741558669677733889 Link to Flako run: http://ci.chromium.org/b/8741554664431477521/infra Suspected commit: https://chromium-review.googlesource.com/c/v8/v8/+/5696786
Crash type: DCHECK failure
Crash state: JSObject::MayHaveEmbedderFields(map) implies UncheckedCast<JSObject>(obj)->GetEm
Error summary:
Fatal error in ../../src/objects/objects-body-descriptors-inl.h, line 109
Debug check failed: JSObject::MayHaveEmbedderFields(map) implies UncheckedCast<JSObject>(obj)->GetEmbedderFieldCount() == 0.
#FailureMessage Object: 0x16b84a738 ==== C stack trace ===============================
0 libv8_libbase.dylib 0x0000000105f01148 v8::base::debug::StackTrace::StackTrace() + 24
1 libv8_libplatform.dylib 0x0000000105f44f28 v8::platform::(anonymous namespace)::PrintStackTrace() + 116
2 libv8_libbase.dylib 0x0000000105ee4930 V8_Fatal(char const*, int, char const*, ...) + 352
3 libv8_libbase.dylib 0x0000000105ee4264 v8::base::SetFatalFunction(void (*)(char const*, int, char const*)) + 0
4 libv8_for_testing.dylib 0x000000010e324434 void v8::internal::BodyDescriptorBase::IterateJSObjectBodyWithoutEmbedderFieldsImpl<v8::internal::ConcurrentMarkingVisitor>(v8::internal::Tagged<v8::internal::Map>, v8::internal::Tagged<v8::internal::HeapObject>, int, int, v8::internal::ConcurrentMarkingVisitor*) + 304
5 libv8_for_testing.dylib 0x000000010e326194 int v8::internal::HeapVisitor<int, v8::internal::ConcurrentMarkingVisitor>::VisitJSObjectSubclass<v8::internal::JSTypedArray, v8::internal::JSTypedArray::BodyDescriptor>(v8::internal::Tagged<v8::internal::Map>, v8::internal::Tagged<v8::internal::JSTypedArray>) + 136
6 libv8_for_testing.dylib 0x000000010e306870 v8::internal::ConcurrentMarking::RunMajor(v8::JobDelegate*, v8::base::EnumSet<v8::internal::CodeFlushMode, int>, unsigned int, bool) + 988
7 libv8_for_testing.dylib 0x000000010e366940 v8::internal::ConcurrentMarking::JobTaskMajor::Run(v8::JobDelegate*) + 480
8 libv8_libplatform.dylib 0x0000000105f43bd8 v8::platform::DefaultJobWorker::Run() + 260
Crash analysis hash: 3bdc04fbe0e20d5d823e093abdd16035
References
On This Page