master hovercats/oakiss / pkg / musl / patch / 0008-regex-reject-invalid-digit-back-reference-in-BRE.patch
 1From b6bfb0cbc7e56b560b1a928b6136c3ef89015743 Mon Sep 17 00:00:00 2001
 2From: Szabolcs Nagy <nsz@port70.net>
 3Date: Mon, 23 Mar 2026 17:33:20 +0000
 4Subject: [PATCH] regex: reject invalid \digit back reference in BRE
 5
 6in BRE \n matches the nth subexpression, but regcomp did not check if
 7the nth subexpression was complete or not, only that there were more
 8subexpressions overall than the largest backref.
 9
10fix regcomp to error if the referenced subexpression is incomplete.
11the bug could cause an infinite loop in regexec:
12
13 regcomp(&re, "\\(^a*\\1\\)*", 0);
14 regexec(&re, "aa", 0, 0, 0);
15
16since BRE has backreferences, any application accepting a BRE from
17untrusted sources is already vulnerable to an attacker-controlled
18near-infinite (exponential-time) loop, but this particular case where
19the loop is actually infinite can and should be avoided.
20
21ERE is not affected since the language an ERE describes is actually
22regular.
23
24Reported-by: Simon Resch <simon.resch@code-intelligence.com>
25---
26 src/regex/regcomp.c | 6 ++++++
27 1 file changed, 6 insertions(+)
28
29diff --git a/src/regex/regcomp.c b/src/regex/regcomp.c
30index fb24556e..b4b81968 100644
31--- a/src/regex/regcomp.c
32+++ b/src/regex/regcomp.c
33@@ -409,6 +409,8 @@ typedef struct {
34 	int position;
35 	/* The highest back reference or -1 if none seen so far. */
36 	int max_backref;
37+	/* Bit mask of submatch IDs that can be back referenced. */
38+	int backref_ok;
39 	/* Compilation flags. */
40 	int cflags;
41 } tre_parse_ctx_t;
42@@ -769,6 +771,8 @@ static reg_errcode_t marksub(tre_parse_ctx_t *ctx, tre_ast_node_t *node, int sub
43 	node->submatch_id = subid;
44 	node->num_submatches++;
45 	ctx->n = node;
46+	if (subid < 10)
47+		ctx->backref_ok |= 1<<subid;
48 	return REG_OK;
49 }
50 
51@@ -864,6 +868,8 @@ static reg_errcode_t parse_atom(tre_parse_ctx_t *ctx, const char *s)
52 			if (!ere && (unsigned)*s-'1' < 9) {
53 				/* back reference */
54 				int val = *s - '0';
55+				if (!(ctx->backref_ok & 1<<val))
56+					return REG_ESUBREG;
57 				node = tre_ast_new_literal(ctx->mem, BACKREF, val, ctx->position++);
58 				ctx->max_backref = MAX(val, ctx->max_backref);
59 			} else {
60-- 
612.49.0
62