This is an automated email from the ASF dual-hosted git repository.

reshke pushed a commit to branch backport_cve
in repository https://gitbox.apache.org/repos/asf/cloudberry.git

commit 16364f5175be793cd1442cab9dce53c1ac447d5c
Author: Masahiko Sawada <[email protected]>
AuthorDate: Mon Aug 10 06:38:23 2026 -0700

    Fix potential buffer overrun in regexp match/split functions.
    
    setup_regexp_matches() sizes the buffer used to convert matched
    substrings back from pg_wchar form at the smaller of maxlen*eml and
    the original string's byte length, on the assumption that such a
    conversion cannot produce more bytes than the string it came
    from. That assumption holds only for validly encoded input. But
    pg_mb2wchar_with_len() silently accepts bytes that are invalid in the
    database encoding, turning each such byte into one pg_wchar, and
    converting that back can take more bytes than the input did. A string
    made of such bytes therefore overruns the conversion buffer by up to
    its own length, corrupting the following memory. regexp_match(),
    regexp_matches(), regexp_split_to_table() and regexp_split_to_array()
    are all affected.
    
    Fix by dropping the tighter bound and always allocating maxlen*eml + 1
    bytes.
    
    Reported-by: Francesco Verardi <[email protected]>
    Author: Masahiko Sawada <[email protected]>
    Reviewed-by: Tom Lane <[email protected]>
    Backpatch-through: 14
    Security: CVE-2026-14664
---
 src/backend/utils/adt/regexp.c | 25 +++++++++++++------------
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/src/backend/utils/adt/regexp.c b/src/backend/utils/adt/regexp.c
index d43a0577ee4..e0e0bc0bfac 100644
--- a/src/backend/utils/adt/regexp.c
+++ b/src/backend/utils/adt/regexp.c
@@ -1444,7 +1444,7 @@ setup_regexp_matches(text *orig_str, text *pattern, 
pg_re_flags *re_flags,
 
        /* convert string to pg_wchar form for matching */
        orig_len = VARSIZE_ANY_EXHDR(orig_str);
-       wide_str = (pg_wchar *) palloc(sizeof(pg_wchar) * (orig_len + 1));
+       wide_str = palloc_array(pg_wchar, orig_len + 1);
        wide_len = pg_mb2wchar_with_len(VARDATA_ANY(orig_str), wide_str, 
orig_len);
 
        /* set up the compiled pattern */
@@ -1580,23 +1580,24 @@ setup_regexp_matches(text *orig_str, text *pattern, 
pg_re_flags *re_flags,
 
        if (eml > 1)
        {
-               int64           maxsiz = eml * (int64) maxlen;
                int                     conv_bufsiz;
 
                /*
                 * Make the conversion buffer large enough for any substring of
-                * interest.
+                * interest. We can't use the original string's byte length as a
+                * tighter bound, because that assumes the input is validly 
encoded;
+                * but pg_mb2wchar_with_len() can accept strings that are 
invalid in
+                * the database encoding, and converting such a character back 
to
+                * multibyte form can take more bytes than it did in the input.
                 *
-                * Worst case: assume we need the maximum size (maxlen*eml), 
but take
-                * advantage of the fact that the original string length in 
bytes is
-                * an upper bound on the byte length of any fetched substring 
(and we
-                * know that len+1 is safe to allocate because the varlena 
header is
-                * longer than 1 byte).
+                * This can't overflow, nor exceed what palloc will accept: 
maxlen is
+                * at most wide_len, which is at most orig_len, and we have 
already
+                * successfully allocated (orig_len + 1) * sizeof(pg_wchar) 
bytes for
+                * wide_str. That relies on eml being no more than 
sizeof(pg_wchar),
+                * which is true of all supported encodings.
                 */
-               if (maxsiz > orig_len)
-                       conv_bufsiz = orig_len + 1;
-               else
-                       conv_bufsiz = maxsiz + 1;       /* safe since maxsiz < 
2^30 */
+               Assert(eml <= sizeof(pg_wchar));
+               conv_bufsiz = maxlen * eml + 1;
 
                matchctx->conv_buf = palloc(conv_bufsiz);
                matchctx->conv_bufsiz = conv_bufsiz;


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to