tregex: limit re_rec() recursion depth - neatvi - [fork] simple vi-type editor … | |
git clone git://src.adamsgaard.dk/neatvi | |
Log | |
Files | |
Refs | |
README | |
--- | |
commit 9a863ba10653cfba7e99b4ed2d30b1474680bb38 | |
parent c7b521883bfdca0555a45ddf6e2dcb4b1ca3966a | |
Author: Ali Gholami Rudi <[email protected]> | |
Date: Thu, 13 Oct 2016 12:58:44 +0330 | |
regex: limit re_rec() recursion depth | |
Diffstat: | |
M regex.c | 73 +++++++++++++++++------------… | |
1 file changed, 40 insertions(+), 33 deletions(-) | |
--- | |
diff --git a/regex.c b/regex.c | |
t@@ -4,8 +4,9 @@ | |
#include <string.h> | |
#include "regex.h" | |
-#define NGRPS 64 | |
-#define NREPS 128 | |
+#define NGRPS 64 /* maximum number of groups */ | |
+#define NREPS 128 /* maximum repetitions */ | |
+#define NDEPT 256 /* re_rec() recursion depth limit */ | |
#define MAX(a, b) ((a) < (b) ? (b) : (a)) | |
#define LEN(a) (sizeof(a) / sizeof((a)[0])) | |
t@@ -61,6 +62,7 @@ struct rstate { | |
char *s; /* the current position in the string */ | |
char *o; /* the beginning of the string */ | |
int flg; /* flags passed to regcomp() and regexec() */ | |
+ int dep; /* re_rec() depth */ | |
}; | |
/* regular expression tree; used for parsing */ | |
t@@ -338,11 +340,11 @@ static struct rnode *rnode_atom(char **pat) | |
if ((*pat)[0] == '*' || (*pat)[0] == '?') { | |
rnode->mincnt = 0; | |
rnode->maxcnt = (*pat)[0] == '*' ? -1 : 1; | |
- (*pat)++; | |
+ *pat += 1; | |
} | |
if ((*pat)[0] == '+') { | |
rnode->mincnt = 1; | |
- rnode->maxcnt = NREPS; | |
+ rnode->maxcnt = -1; | |
*pat += 1; | |
} | |
if ((*pat)[0] == '{') { | |
t@@ -354,7 +356,7 @@ static struct rnode *rnode_atom(char **pat) | |
if (**pat == ',') { | |
(*pat)++; | |
if ((*pat)[0] == '}') | |
- rnode->maxcnt = NREPS; | |
+ rnode->maxcnt = -1; | |
while (isdigit((unsigned char) **pat)) | |
rnode->maxcnt = rnode->maxcnt * 10 + *(*pat)++… | |
} else { | |
t@@ -530,35 +532,39 @@ void regfree(regex_t *preg) | |
static int re_rec(struct regex *re, struct rstate *rs) | |
{ | |
- struct rinst *ri = &re->p[rs->pc]; | |
- if (ri->ri == RI_ATOM) { | |
- if (ratom_match(&ri->ra, rs)) | |
- return 1; | |
- rs->pc++; | |
- return re_rec(re, rs); | |
- } | |
- if (ri->ri == RI_MARK) { | |
- if (ri->mark < NGRPS) | |
- rs->mark[ri->mark] = rs->s - rs->o; | |
- rs->pc++; | |
- return re_rec(re, rs); | |
- } | |
- if (ri->ri == RI_JUMP) { | |
- rs->pc = ri->a1; | |
- return re_rec(re, rs); | |
- } | |
- if (ri->ri == RI_FORK) { | |
- struct rstate base = *rs; | |
- rs->pc = ri->a1; | |
- if (!re_rec(re, rs)) | |
- return 0; | |
- *rs = base; | |
- rs->pc = ri->a2; | |
- return re_rec(re, rs); | |
+ struct rinst *ri = NULL; | |
+ if (++(rs->dep) >= NDEPT) | |
+ return 1; | |
+ while (1) { | |
+ ri = &re->p[rs->pc]; | |
+ if (ri->ri == RI_ATOM) { | |
+ if (ratom_match(&ri->ra, rs)) | |
+ return 1; | |
+ rs->pc++; | |
+ continue; | |
+ } | |
+ if (ri->ri == RI_MARK) { | |
+ if (ri->mark < NGRPS) | |
+ rs->mark[ri->mark] = rs->s - rs->o; | |
+ rs->pc++; | |
+ continue; | |
+ } | |
+ if (ri->ri == RI_JUMP) { | |
+ rs->pc = ri->a1; | |
+ continue; | |
+ } | |
+ if (ri->ri == RI_FORK) { | |
+ struct rstate base = *rs; | |
+ rs->pc = ri->a1; | |
+ if (!re_rec(re, rs)) | |
+ return 0; | |
+ *rs = base; | |
+ rs->pc = ri->a2; | |
+ continue; | |
+ } | |
+ break; | |
} | |
- if (ri->ri == RI_MATCH) | |
- return 0; | |
- return 1; | |
+ return ri->ri != RI_MATCH; | |
} | |
static int re_recmatch(struct regex *re, struct rstate *rs, int nsub, regmatch… | |
t@@ -567,6 +573,7 @@ static int re_recmatch(struct regex *re, struct rstate *rs… | |
rs->pc = 0; | |
for (i = 0; i < LEN(rs->mark); i++) | |
rs->mark[i] = -1; | |
+ rs->dep = 0; | |
if (!re_rec(re, rs)) { | |
for (i = 0; i < nsub; i++) { | |
psub[i].rm_so = i * 2 < LEN(rs->mark) ? rs->mark[i * 2… |