Issue #162: Check stack overflow during regexp compilation.

Only bother checking during the first compilation pass that counts
the size of the program.
This commit is contained in:
Tor Andersson
2022-05-17 15:31:50 +02:00
parent db110ea88e
commit 160ae29578

View File

@@ -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");