Skip to content

[BIGSLEEP-438254142] PCRE2: heap-buffer-overflow read in match_ref due to missing boundary restoration in SCS

Moderate
NWilson published GHSA-c2gv-xgf5-5cc2 Aug 27, 2025

Package

PCRE2

Affected versions

10.45

Patched versions

10.46

Description

Details from PCRE2 team

We have released PCRE2 10.46, which is a security-only release, to address CVE-2025-58050.

Compared to 10.45, this release has only a minimal code change to prevent a read-past-the-end memory error, of arbitrary length. An attacker-controlled regex pattern is required, and it cannot be triggered by providing crafted subject (match) text. The (*ACCEPT) and (*scs:) pattern features must be used together.

Release 10.44 and earlier are not affected.

This could have implications of denial-of-service or information disclosure, and could potentially be used to escalate other vulnerabilities in a system (such as information disclosure being used to escalate the severity of an unrelated bug in another system).


Details as reported by Google Big Sleep security team below

We are tracking this issue with the public ID BIGSLEEP-438254142. Please use this identifier for reference in any future communication.

Vulnerability Details

A heap-buffer-overflow read vulnerability exists in the PCRE2 regular expression matching engine, specifically within the handling of the (*scs:...) (Scan SubString) verb when combined with (*ACCEPT) in src/pcre2_match.c.

The (*scs:...) verb is used to match a portion of the pattern against a specific captured substring rather than the main subject string. To achieve this, the engine temporarily modifies the match boundaries, specifically the mb->end_subject and mb->true_end_subject pointers in the match block, restricting them to the bounds of the specified substring[1].

5815: case OP_ASSERT_SCS:
5816:   {
...
5876: Lsaved_end_subject = mb->end_subject;
5877: Ltrue_end_extra = mb->true_end_subject - mb->end_subject;
5878: Lsaved_eptr = Feptr;
5879: Lsaved_moptions = mb->moptions;
5880:
5881: Feptr = mb->start_subject + Fovector[offset];
5882: mb->true_end_subject = mb->end_subject =
5883:   mb->start_subject + Fovector[offset + 1]; // *** 1 ***
5884: mb->moptions &= ~PCRE2_NOTEOL;

The vulnerability occurs when the pattern inside the (*scs:...) block succeeds via an immediate (*ACCEPT) [2]. In this specific scenario,, the engine correctly restores the current subject pointer (Feptr) to its position before the SCS assertion[3], but it fails to restore the original mb->end_subject and mb->true_end_subject values. These pointers remain incorrectly pointing to the end of the scanned substring.

5886: Lframe_type = GF_NOCAPTURE | Fop;
5887: for (;;)
5888:   {
5889:   group_frame_type = Lframe_type;
5890:   RMATCH(Fecode + 1 + LINK_SIZE + Lextra_size, RM38);
5891:   if (rrc == MATCH_ACCEPT)
5892:     {
5893:     memcpy(Fovector,
5894:           (char *)assert_accept_frame + offsetof(heapframe, ovector),
5895:           assert_accept_frame->offset_top * sizeof(PCRE2_SIZE));
5896:     Foffset_top = assert_accept_frame->offset_top;
5897:     Fmark = assert_accept_frame->mark;
5898:     break; // *** 2 ***
5899:     }
5900:
5901:   if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN)
5902:     {
5903:     mb->end_subject = Lsaved_end_subject;
5904:     mb->true_end_subject = mb->end_subject + Ltrue_end_extra;
5905:     mb->moptions = Lsaved_moptions;
5906:     RRETURN(rrc);
5907:     }
5908:
5909:   Fecode += GET(Fecode, 1);
5910:   if (*Fecode != OP_ALT)
5911:     {
5912:     mb->end_subject = Lsaved_end_subject;
5913:     mb->true_end_subject = mb->end_subject + Ltrue_end_extra;
5914:     mb->moptions = Lsaved_moptions;
5915:     RRETURN(MATCH_NOMATCH);
5916:     }
5917:   Lextra_size = 0;
5918:   }
5919:
5920: do Fecode += GET(Fecode, 1); while (*Fecode == OP_ALT);
5921: Fecode += 1 + LINK_SIZE;
5922: Feptr = Lsaved_eptr; // *** 3 ***
5923: break;

If a subsequent operation in the pattern, such as a backreference (e.g., \2), is attempted, the match_ref function is called. This function performs a bounds check (pcre2_match.c:488) before comparing the backreference:

488: if ((PCRE2_SIZE)(mb->end_subject - eptr) < length) return 1;
489: if (memcmp(p, eptr, CU2BYTES(length)) != 0) return -1;  /* No match */

If the current pointer (eptr) is already beyond the incorrectly shortened mb->end_subject, the subtraction results in an underflow. Because the result is cast to PCRE2_SIZE (an unsigned type), the result is a very large positive number. This causes the bounds check to pass incorrectly (the large number is not less than length).

The code then proceeds to call memcmp using the current pointer eptr, which is beyond the actual end of the allocated haystack buffer, leading to a heap-buffer-overflow read.

This vulnerability may potentially lead to information disclosure if the out-of-bounds data read during the memcmp affects the final match result in a way observable by the attacker.

Affected Version(s)

The issue has been successfully reproduced:

  • at HEAD (commit 7c7a27442279f5b53cd9c1c320e7a5fa662b48e7)

  • in stable release 10.45

Reproduction

The vulnerability can be demonstrated by running pcre2test binary compiled with AddressSanitizer on a malicious input.

Test Case

/(a)(b+)(*scs:(1)a(*ACCEPT))(\2)/
abbb

Build Instructions

git clone https://github.com/PCRE2Project/pcre2.git
cd pcre2
./autogen.sh
CFLAGS="-fsanitize=address -g -fno-omit-frame-pointer" LDFLAGS="-fsanitize=address" ./configure
make -j$(nproc)

Command

LD_LIBRARY_PATH=./.libs ./.libs/pcre2test repro.txt

ASan Report

==2249605==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x529000004200 at pc 0x7fdc916c4162 bp 0x7ffe6a0356c0 sp 0x7ffe6a034e80
READ of size 3 at 0x529000004200 thread T0
    #0 0x7fdc916c4161 in MemcmpInterceptorCommon(void*, int (*)(void const*, void const*, unsigned long), void const*, void const*, unsigned long) ../../..
/../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:814
    #1 0x7fdc916c4b33 in memcmp ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:845
    #2 0x7fdc916c4b33 in memcmp ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:840
    #3 0x7fdc91543cee in match_ref src/pcre2_match.c:489
    #4 0x7fdc9159f629 in match src/pcre2_match.c:5262
    #5 0x7fdc915b2c4f in pcre2_match_8 src/pcre2_match.c:7901
    #6 0x563f4b3ac41c in process_data src/pcre2test.c:9145
    #7 0x563f4b3b3154 in main src/pcre2test.c:10869
    #8 0x7fdc912faca7 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #9 0x7fdc912fad64 in __libc_start_main_impl ../csu/libc-start.c:360
    #10 0x563f4b38f9c0 in _start (pcre2/.libs/pcre2test+0x199c0) (BuildId: 327568290
45f06cb308e0e3da83b56f6be796b50)

0x529000004200 is located 0 bytes after 16384-byte region [0x529000000200,0x529000004200)
allocated by thread T0 here:
    #0 0x7fdc916f3b58 in realloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:85
    #1 0x563f4b3a7700 in process_data src/pcre2test.c:8063
    #2 0x563f4b3b3154 in main src/pcre2test.c:10869
    #3 0x7fdc912faca7 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58

SUMMARY: AddressSanitizer: heap-buffer-overflow ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:814 in MemcmpInterceptorCom
mon(void*, int (*)(void const*, void const*, unsigned long), void const*, void const*, unsigned long)
Shadow bytes around the buggy address:
  0x529000003f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x529000004000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x529000004080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x529000004100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x529000004180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x529000004200:[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x529000004280: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x529000004300: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x529000004380: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x529000004400: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x529000004480: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==2249605==ABORTING

Reporter Credit

Google Big Sleep

Disclosure Policy

This bug is subject to a 90-day disclosure deadline. If a fix for this issue is made available to users before the end of the 90-day deadline, this bug report will become public 30 days after the fix was made available. Otherwise, this bug report will become public at the deadline. The scheduled deadline is 2025-11-10.

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

Severity

Moderate

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v4 base metrics

Exploitability Metrics
Attack Vector Network
Attack Complexity Low
Attack Requirements None
Privileges Required None
User interaction None
Vulnerable System Impact Metrics
Confidentiality Low
Integrity None
Availability Low
Subsequent System Impact Metrics
Confidentiality Low
Integrity None
Availability Low

CVSS v4 base metrics

Exploitability Metrics
Attack Vector: This metric reflects the context by which vulnerability exploitation is possible. This metric value (and consequently the resulting severity) will be larger the more remote (logically, and physically) an attacker can be in order to exploit the vulnerable system. The assumption is that the number of potential attackers for a vulnerability that could be exploited from across a network is larger than the number of potential attackers that could exploit a vulnerability requiring physical access to a device, and therefore warrants a greater severity.
Attack Complexity: This metric captures measurable actions that must be taken by the attacker to actively evade or circumvent existing built-in security-enhancing conditions in order to obtain a working exploit. These are conditions whose primary purpose is to increase security and/or increase exploit engineering complexity. A vulnerability exploitable without a target-specific variable has a lower complexity than a vulnerability that would require non-trivial customization. This metric is meant to capture security mechanisms utilized by the vulnerable system.
Attack Requirements: This metric captures the prerequisite deployment and execution conditions or variables of the vulnerable system that enable the attack. These differ from security-enhancing techniques/technologies (ref Attack Complexity) as the primary purpose of these conditions is not to explicitly mitigate attacks, but rather, emerge naturally as a consequence of the deployment and execution of the vulnerable system.
Privileges Required: This metric describes the level of privileges an attacker must possess prior to successfully exploiting the vulnerability. The method by which the attacker obtains privileged credentials prior to the attack (e.g., free trial accounts), is outside the scope of this metric. Generally, self-service provisioned accounts do not constitute a privilege requirement if the attacker can grant themselves privileges as part of the attack.
User interaction: This metric captures the requirement for a human user, other than the attacker, to participate in the successful compromise of the vulnerable system. This metric determines whether the vulnerability can be exploited solely at the will of the attacker, or whether a separate user (or user-initiated process) must participate in some manner.
Vulnerable System Impact Metrics
Confidentiality: This metric measures the impact to the confidentiality of the information managed by the VULNERABLE SYSTEM due to a successfully exploited vulnerability. Confidentiality refers to limiting information access and disclosure to only authorized users, as well as preventing access by, or disclosure to, unauthorized ones.
Integrity: This metric measures the impact to integrity of a successfully exploited vulnerability. Integrity refers to the trustworthiness and veracity of information. Integrity of the VULNERABLE SYSTEM is impacted when an attacker makes unauthorized modification of system data. Integrity is also impacted when a system user can repudiate critical actions taken in the context of the system (e.g. due to insufficient logging).
Availability: This metric measures the impact to the availability of the VULNERABLE SYSTEM resulting from a successfully exploited vulnerability. While the Confidentiality and Integrity impact metrics apply to the loss of confidentiality or integrity of data (e.g., information, files) used by the system, this metric refers to the loss of availability of the impacted system itself, such as a networked service (e.g., web, database, email). Since availability refers to the accessibility of information resources, attacks that consume network bandwidth, processor cycles, or disk space all impact the availability of a system.
Subsequent System Impact Metrics
Confidentiality: This metric measures the impact to the confidentiality of the information managed by the SUBSEQUENT SYSTEM due to a successfully exploited vulnerability. Confidentiality refers to limiting information access and disclosure to only authorized users, as well as preventing access by, or disclosure to, unauthorized ones.
Integrity: This metric measures the impact to integrity of a successfully exploited vulnerability. Integrity refers to the trustworthiness and veracity of information. Integrity of the SUBSEQUENT SYSTEM is impacted when an attacker makes unauthorized modification of system data. Integrity is also impacted when a system user can repudiate critical actions taken in the context of the system (e.g. due to insufficient logging).
Availability: This metric measures the impact to the availability of the SUBSEQUENT SYSTEM resulting from a successfully exploited vulnerability. While the Confidentiality and Integrity impact metrics apply to the loss of confidentiality or integrity of data (e.g., information, files) used by the system, this metric refers to the loss of availability of the impacted system itself, such as a networked service (e.g., web, database, email). Since availability refers to the accessibility of information resources, attacks that consume network bandwidth, processor cycles, or disk space all impact the availability of a system.
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:L/SC:L/SI:N/SA:L

CVE ID

CVE-2025-58050

Weaknesses

Out-of-bounds Read

The product reads data past the end, or before the beginning, of the intended buffer. Learn more on MITRE.