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);