Commit 40b49b6c6b2 for nodejs
commit 40b49b6c6b2a97e9384da15e81ad3209e736f77f
Author: René <contact.9a5d6388@renegade334.me.uk>
Date: Fri Nov 13 17:20:54 2026 +0000
deps: V8: backport a05177279022
Original commit message:
[temporal] Compute zoneinfo64.res length from ResB index table
ICU4C's offsetTOCLookupFn sets UDataMemory::length = -1 for the last
entry in a .dat archive (which occurs for zoneinfo64.res in small-icu
builds where zu.res is excluded), and pointerTOCLookupFn sets length = -1
for all entries in pointer TOC builds.
When UDataMemory::length is -1, compute the bundle byte length from the
ResB header offset (udata_getMemory(memory) - data) and the
self-describing URES_INDEX_BUNDLE_TOP word in the ResB index table,
matching ICU4C's res_init() in uresdata.cpp. Also check USING_SYSTEM_ICU
in addition to V8_ENABLE_TEMPORAL_SYSTEMICU when deciding whether
internal udatamem.h is available.
Bug: 576986967
Change-Id: I7a2c881eb3891a97eafb244f71aa405ff2434b51
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/8642579
Commit-Queue: Manish Goregaokar <manishearth@google.com>
Reviewed-by: Rezvan Mahdavi Hezaveh <rezvan@chromium.org>
Cr-Commit-Position: refs/heads/main@{#111181}
Refs: https://github.com/v8/v8/commit/a0517727902272117b79281998dc0d5d4da0fa49
Co-authored-by: Renegade334 <contact.9a5d6388@renegade334.me.uk>
PR-URL: https://github.com/nodejs/node/pull/67416
Refs: https://issues.chromium.org/issues/576986967
Refs: https://github.com/nodejs/node/issues/62676
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Steven R Loomis <srl295@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
diff --git a/common.gypi b/common.gypi
index f8588b82311..91efcb7cb87 100644
--- a/common.gypi
+++ b/common.gypi
@@ -50,7 +50,7 @@
# Reset this number to 0 on major V8 upgrades.
# Increment by one for each non-official patch applied to deps/v8.
- 'v8_embedder_string': '-node.11',
+ 'v8_embedder_string': '-node.12',
##### V8 defaults for Node.js #####
diff --git a/deps/v8/src/objects/js-temporal-zoneinfo64.cc b/deps/v8/src/objects/js-temporal-zoneinfo64.cc
index 007d63589c5..cc1ebb21fda 100644
--- a/deps/v8/src/objects/js-temporal-zoneinfo64.cc
+++ b/deps/v8/src/objects/js-temporal-zoneinfo64.cc
@@ -11,7 +11,7 @@
#include "temporal_rs/TimeZone.hpp"
#ifdef V8_INTL_SUPPORT
-#ifndef V8_ENABLE_TEMPORAL_SYSTEMICU
+#if !defined(V8_ENABLE_TEMPORAL_SYSTEMICU) && !defined(USING_SYSTEM_ICU)
// ICU internal header file
#include "udatamem.h"
#else
@@ -58,7 +58,7 @@ ZoneInfo64Provider::ZoneInfo64Provider() {
provider = temporal_rs::Provider::empty();
return;
}
-#ifndef V8_ENABLE_TEMPORAL_SYSTEMICU
+#if !defined(V8_ENABLE_TEMPORAL_SYSTEMICU) && !defined(USING_SYSTEM_ICU)
// NOT udata_getLength: this ignores the header,
// and we're parsing resb files with the header
auto length = memory->length;
@@ -71,6 +71,51 @@ ZoneInfo64Provider::ZoneInfo64Provider() {
auto length = shadowMemory->length;
auto data = shadowMemory->data;
#endif
+ DCHECK_WITH_MSG(data != nullptr, "ICU4C returned nullptr");
+ if (data == nullptr) {
+ provider = temporal_rs::Provider::empty();
+ return;
+ }
+ // ICU4C sets length = -1 for the last entry in an offset TOC (.dat) archive
+ // (e.g. when zoneinfo64.res is the final entry in a small-icu build) and for
+ // all entries in a pointer TOC archive. Determine the exact byte length of
+ // the ResB bundle from its self-describing index table (see res_init() in
+ // ICU4C's uresdata.cpp).
+ int32_t resb_length = -1;
+ const void* body = udata_getMemory(memory);
+ if (body != nullptr) {
+ ptrdiff_t header_length =
+ static_cast<const uint8_t*>(body) - static_cast<const uint8_t*>(data);
+ constexpr uint32_t kUresIndexBundleTop = 3;
+ constexpr ptrdiff_t kMinResbBytes = static_cast<ptrdiff_t>(
+ (1 + 1 + kUresIndexBundleTop) * sizeof(uint32_t));
+ if (header_length >= 0 && header_length % 4 == 0 &&
+ (length == -1 || length >= header_length + kMinResbBytes)) {
+ const uint32_t* body_32 = static_cast<const uint32_t*>(body);
+ // body_32[0] is the root resource word; body_32[1..] is indexes[].
+ // indexes[URES_INDEX_LENGTH] & 0xff holds the length of indexes[].
+ uint32_t index_length = body_32[1] & 0xff;
+ if (index_length > kUresIndexBundleTop) {
+ // indexes[URES_INDEX_BUNDLE_TOP] is the number of 32-bit words in the
+ // bundle body.
+ uint32_t bundle_top = body_32[1 + kUresIndexBundleTop];
+ if (bundle_top >= 1 + index_length && bundle_top <= 0x1000000) {
+ resb_length = static_cast<int32_t>(header_length) +
+ static_cast<int32_t>(bundle_top * sizeof(uint32_t));
+ }
+ }
+ }
+ }
+ DCHECK_WITH_MSG(resb_length != -1,
+ "zoneinfo64.res should have a valid ResB index table");
+ DCHECK_IMPLIES(length != -1, resb_length <= length);
+ if (resb_length == -1 || (length != -1 && resb_length > length)) {
+ provider = temporal_rs::Provider::empty();
+ return;
+ }
+ if (length == -1) {
+ length = resb_length;
+ }
// This really shouldn't happen: ICU4C pads these files
// to 4 when baking them in
DCHECK_WITH_MSG(length % 4 == 0, "ICU4C should pad udata to uint32_t");
@@ -80,7 +125,6 @@ ZoneInfo64Provider::ZoneInfo64Provider() {
provider = temporal_rs::Provider::empty();
return;
}
- DCHECK_WITH_MSG(data != nullptr, "ICU4C returned nullptr");
const uint32_t* data_32 = static_cast<const uint32_t*>(data);
std::span<const uint32_t> data_span(data_32, length / 4);