From af6c78e34498d63ad35a95d97d9e2c735638cbe8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Thu, 22 Oct 2026 20:34:10 +0200 Subject: [PATCH] musl: apply Rich Felker's CVE-2026-107891 patch https://www.openwall.com/lists/musl/2026/10/21/1 --- lib/libc/musl/src/regex/regcomp.c | 41 ++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/lib/libc/musl/src/regex/regcomp.c b/lib/libc/musl/src/regex/regcomp.c index fb24556ebe12e33cd07d86a7953e2ce30f45c3b7..706bb5f1a8b36c66105e4ba2c8e0e1ae910c770b 100644 --- a/lib/libc/musl/src/regex/regcomp.c +++ b/lib/libc/musl/src/regex/regcomp.c @@ -1674,6 +1674,12 @@ tre_add_tags(tre_mem_t mem, tre_stack_t *stack, tre_ast_node_t *tree, AST to TNFA compilation routines. */ +/* check if a+b overflows for a,b in [0,INT_MAX] */ +static int check_add(unsigned a, unsigned b) +{ + return a + b > INT_MAX; +} + typedef enum { COPY_RECURSE, COPY_SET_RESULT_PTR @@ -1725,6 +1731,8 @@ tre_copy_ast(tre_mem_t mem, tre_stack_t *stack, tre_ast_node_t *ast, /* XXX - e.g. [ab] has only one position but two nodes, so we are creating holes in the state space here. Not fatal, just wastes memory. */ + if (check_add(pos, *pos_add)) + return REG_ESPACE; pos += *pos_add; num_copied++; } @@ -1820,6 +1828,8 @@ tre_copy_ast(tre_mem_t mem, tre_stack_t *stack, tre_ast_node_t *ast, break; } } + if (check_add(*pos_add, num_copied)) + return REG_ESPACE; *pos_add += num_copied; return status; } @@ -1864,6 +1874,8 @@ tre_expand_ast(tre_mem_t mem, tre_stack_t *stack, tre_ast_node_t *ast, tre_literal_t *lit= node->obj; if (!IS_SPECIAL(lit) || IS_BACKREF(lit)) { + if (check_add(lit->position, pos_add)) + return REG_ESPACE; lit->position += pos_add; if (lit->position > max_pos) max_pos = lit->position; @@ -1992,6 +2004,8 @@ tre_expand_ast(tre_mem_t mem, tre_stack_t *stack, tre_ast_node_t *ast, } iter_depth--; + if (check_add(pos_add_total, pos_add - pos_add_last)) + return REG_ESPACE; pos_add_total += pos_add - pos_add_last; if (iter_depth == 0) pos_add = pos_add_total; @@ -2004,6 +2018,8 @@ tre_expand_ast(tre_mem_t mem, tre_stack_t *stack, tre_ast_node_t *ast, } } + if (check_add(*position, pos_add_total)) + return REG_ESPACE; *position += pos_add_total; /* `max_pos' should never be larger than `*position' if the above @@ -2705,9 +2721,19 @@ regcomp(regex_t *restrict preg, const char *restrict regex, int cflags) /* Parse context. */ tre_parse_ctx_t parse_ctx; + /* Limits: before tre_expand_ast, int values like position, subid or + * num_tags are bounded by 2x input length, used stack entries are + * bounded by 16x input length. input length is checked upfront to + * avoid overflows before expand. later, values that can grow big are + * bounds checked via check_add and xcalloc. */ + const int input_limit = 1024000; + const int stack_limit = 8*input_limit; + if (strnlen(regex, input_limit) >= input_limit) + return REG_ESPACE; + /* Allocate a stack used throughout the compilation process for various purposes. */ - stack = tre_stack_new(512, 1024000, 128); + stack = tre_stack_new(512, stack_limit, 128); if (!stack) return REG_ESPACE; /* Allocate a fast memory allocator. */ @@ -2795,9 +2821,12 @@ regcomp(regex_t *restrict preg, const char *restrict regex, int cflags) for example "a*" or "ab*". Figure out a simple way to detect this possibility. */ tmp_ast_l = tree; - tmp_ast_r = tre_ast_new_literal(mem, 0, 0, parse_ctx.position++); + tmp_ast_r = tre_ast_new_literal(mem, 0, 0, parse_ctx.position); if (tmp_ast_r == NULL) ERROR_EXIT(REG_ESPACE); + if (check_add(parse_ctx.position, 1)) + ERROR_EXIT(REG_ESPACE); + parse_ctx.position++; tree = tre_ast_new_catenation(mem, tmp_ast_l, tmp_ast_r); if (tree == NULL) @@ -2807,22 +2836,22 @@ regcomp(regex_t *restrict preg, const char *restrict regex, int cflags) if (errcode != REG_OK) ERROR_EXIT(errcode); - counts = xmalloc(sizeof(int) * parse_ctx.position); + counts = xcalloc(sizeof(int), parse_ctx.position); if (counts == NULL) ERROR_EXIT(REG_ESPACE); - offs = xmalloc(sizeof(int) * parse_ctx.position); + offs = xcalloc(sizeof(int), parse_ctx.position); if (offs == NULL) ERROR_EXIT(REG_ESPACE); - for (i = 0; i < parse_ctx.position; i++) - counts[i] = 0; tre_ast_to_tnfa(tree, NULL, counts, NULL); add = 0; for (i = 0; i < parse_ctx.position; i++) { offs[i] = add; + if (check_add(add, counts[i] + 1)) + ERROR_EXIT(REG_ESPACE); add += counts[i] + 1; counts[i] = 0; } -- 2.54.0