perl: fix CVE-2026-15534

Apply upstream commits 568e6fd238867bb9e99fa3f47cba3169009239e0 and
54cf3d44cbbedd17d774e9a37921963e8fd5d0cb.

Assisted-by: Claude Code (Claude Opus 5)
Signed-off-by: Stig Palmquist <git@stig.io>
(cherry picked from commit 709e8699ab)
This commit is contained in:
Stig Palmquist
2026-08-09 18:59:53 +00:00
committed by Marcus Ramberg
parent f700426a5e
commit 0db31ab897
3 changed files with 101 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
CVE-2026-15534, upstream commit
568e6fd238867bb9e99fa3f47cba3169009239e0.
diff --git a/regexec.c b/regexec.c
index 35a727459c4a..29aa73c13cb9 100644
--- a/regexec.c
+++ b/regexec.c
@@ -9211,7 +9211,8 @@ NULL
reginfo->poscache_iter = reginfo->poscache_maxiter;
}
- if (reginfo->poscache_iter-- == 0) {
+ if (reginfo->poscache_iter == 1) {
+ reginfo->poscache_iter--;
/* initialise cache */
const SSize_t size = (reginfo->poscache_maxiter + 7)/8;
regmatch_info_aux *const aux = reginfo->info_aux;
@@ -9232,11 +9233,10 @@ NULL
);
}
- if (reginfo->poscache_iter < 0) {
+ if (reginfo->poscache_iter == 0) {
/* have we already failed at this position? */
SSize_t offset, mask;
- reginfo->poscache_iter = -1; /* stop eventual underflow */
offset = (FLAGS(scan) & 0xf) - 1
+ (locinput - reginfo->strbeg)
* (FLAGS(scan)>>4);
@@ -9252,6 +9252,8 @@ NULL
ST.cache_offset = offset;
ST.cache_mask = mask;
}
+ else
+ reginfo->poscache_iter--;
}
/* Prefer B over A for minimal matching. */

View File

@@ -0,0 +1,59 @@
CVE-2026-15534, upstream commit
54cf3d44cbbedd17d774e9a37921963e8fd5d0cb.
diff --git a/regexec.c b/regexec.c
index 29aa73c13cb9..66e0c0924059 100644
--- a/regexec.c
+++ b/regexec.c
@@ -9202,22 +9202,27 @@ NULL
if (!reginfo->poscache_maxiter) {
/* start the countdown: Postpone detection until we
* know the match is not *that* much linear. */
- reginfo->poscache_maxiter
- = (reginfo->strend - reginfo->strbeg + 1)
- * (FLAGS(scan)>>4);
- /* possible overflow for long strings and many CURLYX's */
- if (reginfo->poscache_maxiter < 0)
- reginfo->poscache_maxiter = I32_MAX;
- reginfo->poscache_iter = reginfo->poscache_maxiter;
+ STRLEN len = reginfo->strend - reginfo->strbeg;
+ /* number of participating WHILEMs */
+ U8 n = (FLAGS(scan)>>4);
+
+ /* Only do the calculations and enable the cache if it
+ * won't overflow. This test is equivalent to:
+ * ((len + 1) * n + 7) <= max(STRLEN)
+ */
+ if (len < ((~(STRLEN)0) - 7)/n) {
+ reginfo->poscache_maxiter = (len + 1) * n;
+ reginfo->poscache_iter = reginfo->poscache_maxiter;
+ }
}
if (reginfo->poscache_iter == 1) {
reginfo->poscache_iter--;
/* initialise cache */
- const SSize_t size = (reginfo->poscache_maxiter + 7)/8;
+ const STRLEN size = (reginfo->poscache_maxiter + 7)/8;
regmatch_info_aux *const aux = reginfo->info_aux;
if (aux->poscache) {
- if ((SSize_t)reginfo->poscache_size < size) {
+ if (reginfo->poscache_size < size) {
Renew(aux->poscache, size, char);
reginfo->poscache_size = size;
}
diff --git a/regexp.h b/regexp.h
index 057d9ac5011b..d5d40e0a5618 100644
--- a/regexp.h
+++ b/regexp.h
@@ -839,8 +839,8 @@ typedef struct {
char *cutpoint; /* (*COMMIT) position (if any) */
regmatch_info_aux *info_aux; /* extra fields that need cleanup */
regmatch_info_aux_eval *info_aux_eval; /* extra saved state for (?{}) */
- I32 poscache_maxiter; /* how many whilems todo before S-L cache kicks in */
- I32 poscache_iter; /* current countdown from _maxiter to zero */
+ STRLEN poscache_maxiter; /* how many whilems todo before S-L cache kicks in */
+ STRLEN poscache_iter; /* current countdown from _maxiter to zero */
STRLEN poscache_size; /* size of regmatch_info_aux.poscache */
bool intuit; /* re_intuit_start() is the top-level caller */
bool is_utf8_pat; /* regex is utf8 */

View File

@@ -36,6 +36,9 @@ let
commonPatches = [
# Do not look in /usr etc. for dependencies.
./no-sys-dirs.patch
./CVE-2026-15534-1.patch
./CVE-2026-15534-2.patch
]
# Fix build on Solaris on x86_64