Medium chrome Logic Error 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactOff by one error in V8
DescriptionOff by one error in V8
ComponentV8
Bug ClassLogic Error
Tracker439758498
Fix commit5666bca708c0 (v8/v8) +2/-1
CISA KEVNot listed
CreditedGoogle Big Sleep
Disclosed2025-09-30

Changed Functions

FunctionChangeNotes
for
src/runtime/runtime-regexp.cc
modified

Files Changed

  • src/runtime/runtime-regexp.cc
From 5666bca708c0a2f888b78e34281b00ed20356cb2 Mon Sep 17 00:00:00 2001
From: pthier <[email protected]>
Date: Thu, 21 Aug 2025 18:08:08 +0200
Subject: [PATCH] [regexp] Fix OOB read in RegExpMatchGlobalAtom_OneCharPattern

We were loading (just not accessing) a character potentially beyond
the allocated string subject buffer.

Fixed: 439758498
Change-Id: I250670122c765640602b20e6640d604c9d33be03
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/6871496
Commit-Queue: Patrick Thier <[email protected]>
Commit-Queue: Igor Sheludko <[email protected]>
Auto-Submit: Patrick Thier <[email protected]>
Reviewed-by: Igor Sheludko <[email protected]>
Cr-Commit-Position: refs/heads/main@{#101982}
---

diff --git a/src/runtime/runtime-regexp.cc b/src/runtime/runtime-regexp.cc
index dbc9ae1..e2fe84e 100644
--- a/src/runtime/runtime-regexp.cc
+++ b/src/runtime/runtime-regexp.cc
@@ -2236,7 +2236,8 @@
   // last_match_block already contains the last match position, so use a special
   // vector with lane 0 set to extract the last_match_index later.
   const auto scalar_last_match_vec = hw::FirstN(tag, 1);
-  for (SChar c = *block; block < end; c = *(++block)) {
+  for (; block < end; ++block) {
+    SChar c = *block;
     if (c != static_cast<const SChar>(pattern)) continue;
     matches++;
     last_match_block = block;
Loading diff…

Original Bug Report

reported by [email protected]

V8: off-by-one error in RegExp matching leads to OOB read

Bug Details

There is an off-by-one error in the implementation of RegExp matching for the case of a single-character atom, specifically in the function RegExpMatchGlobalAtom_OneCharPattern [1]. This function is optimized for SIMD and processes multiple characters at the same time. In case the input string is not an exact multiple of the stride, a scalar loop processes the remaining characters at the end [2]:

  for (SChar c = *block; block < end; c = *(++block)) {
    ...
  }

Here, since the pointer is first incremented and then dereferenced, it will cause an out-of-bounds read in the last iteration. The below test case demonstrated this by causing a segmentation fault when reading past the end of a page. However, as the bug only leads to an out-of-bounds read, and the read value is never used, this bug should not have any security implications apart from the potential to cause a crash.

[1] https://source.chromium.org/chromium/chromium/src/+/main:v8/src/runtime/runtime-regexp.cc;l=2165;drc=efb8f67f80edf4fa39c5488d07b45b1e690c0c6f

[2] https://source.chromium.org/chromium/chromium/src/+/main:v8/src/runtime/runtime-regexp.cc;l=2241;drc=efb8f67f80edf4fa39c5488d07b45b1e690c0c6f

Affected Version(s)

The issue has been successfully reproduced:

  • at HEAD (commit 625de227c339c41b4a947a03fb74a30eba0afe3f)
  • in stable release 13.9.205.16 (b07b4e9376489c7f7c0ff2af5eceb4261b3bb784)

Reproduction

Test Case

const length = 4;
const pattern = /a/g;
for (let i = 0; i < 500000; i++) {
    let subject = 'b'.repeat(length);
    subject.match(pattern);
}

Build Instructions

Follow the instructions at https://v8.dev/docs/build. The crash was verified on a debug build:

gm.py x64.debug

Command

./out/x64.debug/d8 crash.js

ASan Report

AddressSanitizer:DEADLYSIGNAL
=================================================================
==754958==ERROR: AddressSanitizer: SEGV on unknown address 0x79fd002c0000 (pc 0x7f3e7493423f bp 0x7fff9cec6140 sp 0x7fff9cec5d00 T0)
==754958==The signal is caused by a READ memory access.
    #0 0x7f3e7493423f in void v8::internal::(anonymous namespace)::RegExpMatchGlobalAtom_OneCharPattern<unsigned char, unsigned char>(v8::internal::Isolate*, v8::base::Vector<unsigned char const>, unsigned char, int, int*, int*, v8::internal::PerThreadAssertScope<false, (v8::internal::PerThreadAssertType)1, (v8::internal::PerThreadAssertType)2> const&) src/runtime/runtime-regexp.cc:2241:43
    #1 0x7f3e74933595 in v8::internal::(anonymous namespace)::RegExpMatchGlobalAtom_Dispatch(v8::internal::Isolate*, v8::internal::String::FlatContent const&, v8::internal::String::FlatContent const&, bool, int, int*, int*, v8::internal::PerThreadAssertScope<false, (v8::internal::PerThreadAssertType)1, (v8::internal::PerThreadAssertType)2> const&) src/runtime/runtime-regexp.cc:2326:9
    #2 0x7f3e7491f871 in v8::internal::__RT_impl_Runtime_RegExpMatchGlobalAtom(v8::internal::Arguments<(v8::internal::ArgumentsType)0>, v8::internal::Isolate*) src/runtime/runtime-regexp.cc:2404:5
    #3 0x7f3e7491ea48 in v8::internal::Runtime_RegExpMatchGlobalAtom(int, unsigned long*, v8::internal::Isolate*) src/runtime/runtime-regexp.cc:2358:1
    #4 0x7f3e710e5f7c in Builtins_CEntry_Return1_ArgvOnStack_NoBuiltinExit setup-isolate-deserialize.cc
    #5 0x7f3e71541280 in Builtins_RegExpMatchFast setup-isolate-deserialize.cc
    #6 0x7f3e7169f8b8 in Builtins_StringPrototypeMatch setup-isolate-deserialize.cc
    #7 0x7f3ed0c00fee  (<unknown module>)
    #8 0x7f3e70c72966 in Builtins_JSEntryTrampoline setup-isolate-deserialize.cc
    #9 0x7f3e70c726aa in Builtins_JSEntry setup-isolate-deserialize.cc
    #10 0x7f3e727468d6 in v8::internal::GeneratedCode<unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, long, unsigned long**>::Call(unsigned long, unsigned long, unsigned long, unsigned long, long, unsigned long**) src/execution/simulator.h:212:12
    #11 0x7f3e7273eeee in v8::internal::(anonymous namespace)::Invoke(v8::internal::Isolate*, v8::internal::(anonymous namespace)::InvokeParams const&) src/execution/execution.cc:442:22
    #12 0x7f3e7273fd96 in v8::internal::Execution::CallScript(v8::internal::Isolate*, v8::internal::DirectHandle<v8::internal::JSFunction>, v8::internal::DirectHandle<v8::internal::Object>, v8::internal::DirectHandle<v8::internal::Object>) src/execution/execution.cc:542:10
    #13 0x7f3e71aefb98 in v8::Script::Run(v8::Local<v8::Context>, v8::Local<v8::Data>) src/api/api.cc:1968:7
    #14 0x7f3e71aef41d in v8::Script::Run(v8::Local<v8::Context>) src/api/api.cc:1932:10
    #15 0x55c8d09def2c in v8::Shell::ExecuteString(v8::Isolate*, v8::Local<v8::String>, v8::Local<v8::String>, v8::Shell::ReportExceptions, v8::Global<v8::Value>*) src/d8/d8.cc:1033:44
    #16 0x55c8d0a14f7b in v8::SourceGroup::Execute(v8::Isolate*) src/d8/d8.cc:5322:10
    #17 0x55c8d0a20ec0 in v8::Shell::RunMainIsolate(v8::Isolate*, bool) src/d8/d8.cc:6274:37
    #18 0x55c8d0a2075e in v8::Shell::RunMain(v8::Isolate*, bool) src/d8/d8.cc:6182:18
    #19 0x55c8d0a23544 in v8::Shell::Main(int, char**) src/d8/d8.cc:7049:18
    #20 0x55c8d0a23f81 in main src/d8/d8.cc:7141:43
    #21 0x7f3e66143ca7 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
==754958==Register values:
rax = 0x000079fd002c0000  rbx = 0x00007fff9cec5d00  rcx = 0x0000000000000061  rdx = 0xf5f5f5f5f5f5f5f5  
rdi = 0x00007b3e63d717e0  rsi = 0x00007fff9cec5bc0  rbp = 0x00007fff9cec6140  rsp = 0x00007fff9cec5d00  
 r8 = 0x00000ffff39d8b74   r9 = 0x00007fff9cec5baf  r10 = 0x00000ffff39d8b75  r11 = 0x00001000739d0b70  
r12 = 0x00007b3e053c0000  r13 = 0x00007e4e651e1080  r14 = 0x00000f67cc7ae2d0  r15 = 0xf3f30000f1f1f1f1  
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV src/runtime/runtime-regexp.cc:2241:43 in void v8::internal::(anonymous namespace)::RegExpMatchGlobalAtom_OneCharPattern<unsigned char, unsigned char>(v8::internal::Isolate*, v8::base::Vector<unsigned char const>, unsigned char, int, int*, int*, v8::internal::PerThreadAssertScope<false, (v8::internal::PerThreadAssertType)1, (v8::internal::PerThreadAssertType)2> const&)
==754958==ABORTING

Reporter Credit

Google Big Sleep

Disclosure Policy

Our assessment concluded that this finding has NO security impact. Therefore, we are NOT applying a disclosure deadline to this report.

However, if your internal review indicates a security risk to your users, please email [email protected] immediately to arrange a standard disclosure deadline.

For more information, visit https://goo.gle/bigsleep

View on issue tracker