Version in base suite: 10.46-1~deb13u2 Base version: pcre2_10.46-1~deb13u2 Target version: pcre2_10.46-1~deb13u3 Base file: /srv/ftp-master.debian.org/ftp/pool/main/p/pcre2/pcre2_10.46-1~deb13u2.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/p/pcre2/pcre2_10.46-1~deb13u3.dsc debian/changelog | 8 ++++++++ src/pcre2_jit_compile.c | 21 +++++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff -u pcre2-10.46/debian/changelog pcre2-10.46/debian/changelog --- pcre2-10.46/debian/changelog +++ pcre2-10.46/debian/changelog @@ -1,3 +1,11 @@ +pcre2 (10.46-1~deb13u3) trixie-security; urgency=high + + * Non-maintainer upload by the Security Team. + * GHSA-r9hj-j2rw-4q3m: Fix large JIT stack allocation (Closes: #1149217) + * For release, revert platform-specific test case + + -- Salvatore Bonaccorso Mon, 28 Sep 2026 16:07:53 +0200 + pcre2 (10.46-1~deb13u2) trixie; urgency=high * Use upstream backports of security fixes from 10.48 diff -u pcre2-10.46/src/pcre2_jit_compile.c pcre2-10.46/src/pcre2_jit_compile.c --- pcre2-10.46/src/pcre2_jit_compile.c +++ pcre2-10.46/src/pcre2_jit_compile.c @@ -103,7 +103,7 @@ /* Growth rate for stack allocated by the OS. Should be the multiply of page size. */ -#define STACK_GROWTH_RATE 8192 +#define STACK_GROWTH_RATE (sljit_sw)8192 /* Enable to check that the allocation could destroy temporaries. */ #if defined SLJIT_DEBUG && SLJIT_DEBUG @@ -468,6 +468,8 @@ BOOL local_quit_available; /* Currently in a positive assertion. */ BOOL in_positive_assertion; + /* More than STACK_GROWTH_RATE / 2 stack memory is allocated. */ + BOOL large_stack_allocation; /* Newline control. */ int nltype; sljit_u32 nlmax; @@ -3386,6 +3388,8 @@ DEFINE_COMPILER; SLJIT_ASSERT(size > 0); +if (size > (STACK_GROWTH_RATE / (SSIZE_OF(sw) * 2))) + common->large_stack_allocation = TRUE; OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * SSIZE_OF(sw)); #ifdef DESTROY_REGISTERS OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 12345); @@ -13768,7 +13772,20 @@ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL1, STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0); -OP2(SLJIT_SUB, SLJIT_R1, 0, STACK_LIMIT, 0, SLJIT_IMM, STACK_GROWTH_RATE); +if (common->large_stack_allocation) + { + SLJIT_COMPILE_ASSERT((STACK_GROWTH_RATE & (STACK_GROWTH_RATE - 1)) == 0, stack_growth_must_be_power_of_2); + // Negative difference. The positive difference would also use the same amount + // of operations, but the last subtraction emits several instructions on x86. + OP2(SLJIT_SUB, SLJIT_R1, 0, STACK_TOP, 0, STACK_LIMIT, 0); + // Minimum extra space after allocation. + OP2(SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, (STACK_GROWTH_RATE / 2)); + // Rounds down negative numbers. + OP2(SLJIT_AND, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, ~(STACK_GROWTH_RATE - 1)); + OP2(SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, STACK_LIMIT, 0); + } +else + OP2(SLJIT_SUB, SLJIT_R1, 0, STACK_LIMIT, 0, SLJIT_IMM, STACK_GROWTH_RATE); OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, stack)); OP1(SLJIT_MOV, STACK_LIMIT, 0, TMP2, 0);