From 160ae29578054dc09fd91e5401ef040d52797e61 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Tue, 17 May 2022 15:31:50 +0200 Subject: [PATCH 1/3] Issue #162: Check stack overflow during regexp compilation. Only bother checking during the first compilation pass that counts the size of the program. --- regexp.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/regexp.c b/regexp.c index 9d16867..8a43fef 100644 --- a/regexp.c +++ b/regexp.c @@ -622,25 +622,26 @@ struct Reinst { Reinst *y; }; -static int count(struct cstate *g, Renode *node) +static int count(struct cstate *g, Renode *node, int depth) { int min, max, n; if (!node) return 0; + if (++depth > REG_MAXREC) die(g, "stack overflow"); switch (node->type) { default: return 1; - case P_CAT: return count(g, node->x) + count(g, node->y); - case P_ALT: return count(g, node->x) + count(g, node->y) + 2; + case P_CAT: return count(g, node->x, depth) + count(g, node->y, depth); + case P_ALT: return count(g, node->x, depth) + count(g, node->y, depth) + 2; case P_REP: min = node->m; max = node->n; - if (min == max) n = count(g, node->x) * min; - else if (max < REPINF) n = count(g, node->x) * max + (max - min); - else n = count(g, node->x) * (min + 1) + 2; + if (min == max) n = count(g, node->x, depth) * min; + else if (max < REPINF) n = count(g, node->x, depth) * max + (max - min); + else n = count(g, node->x, depth) * (min + 1) + 2; if (n < 0 || n > REG_MAXPROG) die(g, "program too large"); return n; - case P_PAR: return count(g, node->x) + 2; - case P_PLA: return count(g, node->x) + 2; - case P_NLA: return count(g, node->x) + 2; + case P_PAR: return count(g, node->x, depth) + 2; + case P_PLA: return count(g, node->x, depth) + 2; + case P_NLA: return count(g, node->x, depth) + 2; } } @@ -903,7 +904,7 @@ Reprog *regcompx(void *(*alloc)(void *ctx, void *p, int n), void *ctx, putchar('\n'); #endif - n = 6 + count(&g, node); + n = 6 + count(&g, node, 0); if (n < 0 || n > REG_MAXPROG) die(&g, "program too large"); -- 2.20.1