From 0db31ab897e7cfb87530330abc229b88790b6084 Mon Sep 17 00:00:00 2001 From: Stig Palmquist Date: Sun, 9 Aug 2026 18:59:53 +0000 Subject: [PATCH] perl: fix CVE-2026-15534 Apply upstream commits 568e6fd238867bb9e99fa3f47cba3169009239e0 and 54cf3d44cbbedd17d774e9a37921963e8fd5d0cb. Assisted-by: Claude Code (Claude Opus 5) Signed-off-by: Stig Palmquist (cherry picked from commit 709e8699ab3e17bfdaf02e11cf0e8e2996491360) --- .../interpreters/perl/CVE-2026-15534-1.patch | 39 ++++++++++++ .../interpreters/perl/CVE-2026-15534-2.patch | 59 +++++++++++++++++++ .../interpreters/perl/interpreter.nix | 3 + 3 files changed, 101 insertions(+) create mode 100644 pkgs/development/interpreters/perl/CVE-2026-15534-1.patch create mode 100644 pkgs/development/interpreters/perl/CVE-2026-15534-2.patch diff --git a/pkgs/development/interpreters/perl/CVE-2026-15534-1.patch b/pkgs/development/interpreters/perl/CVE-2026-15534-1.patch new file mode 100644 index 000000000000..fc8ee2f29ea9 --- /dev/null +++ b/pkgs/development/interpreters/perl/CVE-2026-15534-1.patch @@ -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. */ diff --git a/pkgs/development/interpreters/perl/CVE-2026-15534-2.patch b/pkgs/development/interpreters/perl/CVE-2026-15534-2.patch new file mode 100644 index 000000000000..b5d0ff5ed3d0 --- /dev/null +++ b/pkgs/development/interpreters/perl/CVE-2026-15534-2.patch @@ -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 */ diff --git a/pkgs/development/interpreters/perl/interpreter.nix b/pkgs/development/interpreters/perl/interpreter.nix index 4b308c156f02..ae75db2ead90 100644 --- a/pkgs/development/interpreters/perl/interpreter.nix +++ b/pkgs/development/interpreters/perl/interpreter.nix @@ -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