Lines 86-96
Link Here
|
86 |
#endif |
86 |
#endif |
87 |
|
87 |
|
88 |
/* === regcomp.c === */ |
88 |
/* === regcomp.c === */ |
89 |
static void p_ere(struct parse *p, int stop); |
89 |
static void p_ere(struct parse *p, int stop, size_t reclimit); |
90 |
static void p_ere_exp(struct parse *p); |
90 |
static void p_ere_exp(struct parse *p, size_t reclimit); |
91 |
static void p_str(struct parse *p); |
91 |
static void p_str(struct parse *p); |
92 |
static void p_bre(struct parse *p, int end1, int end2); |
92 |
static void p_bre(struct parse *p, int end1, int end2, size_t reclimit); |
93 |
static int p_simp_re(struct parse *p, int starordinary); |
93 |
static int p_simp_re(struct parse *p, int starordinary, size_t reclimit); |
94 |
static int p_count(struct parse *p); |
94 |
static int p_count(struct parse *p); |
95 |
static void p_bracket(struct parse *p); |
95 |
static void p_bracket(struct parse *p); |
96 |
static void p_b_term(struct parse *p, cset *cs); |
96 |
static void p_b_term(struct parse *p, cset *cs); |
Lines 102-108
Link Here
|
102 |
static void bothcases(struct parse *p, wint_t ch); |
102 |
static void bothcases(struct parse *p, wint_t ch); |
103 |
static void ordinary(struct parse *p, wint_t ch); |
103 |
static void ordinary(struct parse *p, wint_t ch); |
104 |
static void nonnewline(struct parse *p); |
104 |
static void nonnewline(struct parse *p); |
105 |
static void repeat(struct parse *p, sopno start, int from, int to); |
105 |
static void repeat(struct parse *p, sopno start, int from, int to, size_t reclimit); |
106 |
static int seterr(struct parse *p, int e); |
106 |
static int seterr(struct parse *p, int e); |
107 |
static cset *allocset(struct parse *p); |
107 |
static cset *allocset(struct parse *p); |
108 |
static void freeset(struct parse *p, cset *cs); |
108 |
static void freeset(struct parse *p, cset *cs); |
Lines 167-172
Link Here
|
167 |
#define never 0 /* some <assert.h>s have bugs too */ |
167 |
#define never 0 /* some <assert.h>s have bugs too */ |
168 |
#endif |
168 |
#endif |
169 |
|
169 |
|
|
|
170 |
#define MEMLIMIT 0x8000000 |
171 |
#define MEMSIZE(p) \ |
172 |
((p)->ncsalloc / CHAR_BIT * NC + \ |
173 |
(p)->ncsalloc * sizeof(cset) + \ |
174 |
(p)->ssize * sizeof(sop)) |
175 |
#define RECLIMIT 256 |
176 |
|
170 |
/* Macro used by computejump()/computematchjump() */ |
177 |
/* Macro used by computejump()/computematchjump() */ |
171 |
#define MIN(a,b) ((a)<(b)?(a):(b)) |
178 |
#define MIN(a,b) ((a)<(b)?(a):(b)) |
172 |
|
179 |
|
Lines 249-259
Link Here
|
249 |
EMIT(OEND, 0); |
256 |
EMIT(OEND, 0); |
250 |
g->firststate = THERE(); |
257 |
g->firststate = THERE(); |
251 |
if (cflags®_EXTENDED) |
258 |
if (cflags®_EXTENDED) |
252 |
p_ere(p, OUT); |
259 |
p_ere(p, OUT, 0); |
253 |
else if (cflags®_NOSPEC) |
260 |
else if (cflags®_NOSPEC) |
254 |
p_str(p); |
261 |
p_str(p); |
255 |
else |
262 |
else |
256 |
p_bre(p, OUT, OUT); |
263 |
p_bre(p, OUT, OUT, 0); |
257 |
EMIT(OEND, 0); |
264 |
EMIT(OEND, 0); |
258 |
g->laststate = THERE(); |
265 |
g->laststate = THERE(); |
259 |
|
266 |
|
Lines 294-300
Link Here
|
294 |
*/ |
301 |
*/ |
295 |
static void |
302 |
static void |
296 |
p_ere(struct parse *p, |
303 |
p_ere(struct parse *p, |
297 |
int stop) /* character this ERE should end at */ |
304 |
int stop, /* character this ERE should end at */ |
|
|
305 |
size_t reclimit) |
298 |
{ |
306 |
{ |
299 |
char c; |
307 |
char c; |
300 |
sopno prevback; |
308 |
sopno prevback; |
Lines 302-312
Link Here
|
302 |
sopno conc; |
310 |
sopno conc; |
303 |
int first = 1; /* is this the first alternative? */ |
311 |
int first = 1; /* is this the first alternative? */ |
304 |
|
312 |
|
|
|
313 |
if (reclimit++ > RECLIMIT || p->error == REG_ESPACE) { |
314 |
p->error = REG_ESPACE; |
315 |
return; |
316 |
} |
317 |
|
305 |
for (;;) { |
318 |
for (;;) { |
306 |
/* do a bunch of concatenated expressions */ |
319 |
/* do a bunch of concatenated expressions */ |
307 |
conc = HERE(); |
320 |
conc = HERE(); |
308 |
while (MORE() && (c = PEEK()) != '|' && c != stop) |
321 |
while (MORE() && (c = PEEK()) != '|' && c != stop) |
309 |
p_ere_exp(p); |
322 |
p_ere_exp(p, reclimit); |
310 |
(void)REQUIRE(HERE() != conc, REG_EMPTY); /* require nonempty */ |
323 |
(void)REQUIRE(HERE() != conc, REG_EMPTY); /* require nonempty */ |
311 |
|
324 |
|
312 |
if (!EAT('|')) |
325 |
if (!EAT('|')) |
Lines 335-344
Link Here
|
335 |
|
348 |
|
336 |
/* |
349 |
/* |
337 |
- p_ere_exp - parse one subERE, an atom possibly followed by a repetition op |
350 |
- p_ere_exp - parse one subERE, an atom possibly followed by a repetition op |
338 |
== static void p_ere_exp(struct parse *p); |
351 |
== static void p_ere_exp(struct parse *p, size_t reclimit); |
339 |
*/ |
352 |
*/ |
340 |
static void |
353 |
static void |
341 |
p_ere_exp(struct parse *p) |
354 |
p_ere_exp(struct parse *p, size_t reclimit) |
342 |
{ |
355 |
{ |
343 |
char c; |
356 |
char c; |
344 |
wint_t wc; |
357 |
wint_t wc; |
Lines 361-367
Link Here
|
361 |
p->pbegin[subno] = HERE(); |
374 |
p->pbegin[subno] = HERE(); |
362 |
EMIT(OLPAREN, subno); |
375 |
EMIT(OLPAREN, subno); |
363 |
if (!SEE(')')) |
376 |
if (!SEE(')')) |
364 |
p_ere(p, ')'); |
377 |
p_ere(p, ')', reclimit); |
365 |
if (subno < NPAREN) { |
378 |
if (subno < NPAREN) { |
366 |
p->pend[subno] = HERE(); |
379 |
p->pend[subno] = HERE(); |
367 |
assert(p->pend[subno] != 0); |
380 |
assert(p->pend[subno] != 0); |
Lines 465-471
Link Here
|
465 |
count2 = INFINITY; |
478 |
count2 = INFINITY; |
466 |
} else /* just a single number */ |
479 |
} else /* just a single number */ |
467 |
count2 = count; |
480 |
count2 = count; |
468 |
repeat(p, pos, count, count2); |
481 |
repeat(p, pos, count, count2, 0); |
469 |
if (!EAT('}')) { /* error heuristics */ |
482 |
if (!EAT('}')) { /* error heuristics */ |
470 |
while (MORE() && PEEK() != '}') |
483 |
while (MORE() && PEEK() != '}') |
471 |
NEXT(); |
484 |
NEXT(); |
Lines 499-505
Link Here
|
499 |
/* |
512 |
/* |
500 |
- p_bre - BRE parser top level, anchoring and concatenation |
513 |
- p_bre - BRE parser top level, anchoring and concatenation |
501 |
== static void p_bre(struct parse *p, int end1, \ |
514 |
== static void p_bre(struct parse *p, int end1, \ |
502 |
== int end2); |
515 |
== int end2, size_t reclimit); |
503 |
* Giving end1 as OUT essentially eliminates the end1/end2 check. |
516 |
* Giving end1 as OUT essentially eliminates the end1/end2 check. |
504 |
* |
517 |
* |
505 |
* This implementation is a bit of a kludge, in that a trailing $ is first |
518 |
* This implementation is a bit of a kludge, in that a trailing $ is first |
Lines 509-516
Link Here
|
509 |
static void |
522 |
static void |
510 |
p_bre(struct parse *p, |
523 |
p_bre(struct parse *p, |
511 |
int end1, /* first terminating character */ |
524 |
int end1, /* first terminating character */ |
512 |
int end2) /* second terminating character */ |
525 |
int end2, /* second terminating character */ |
|
|
526 |
size_t reclimit) |
513 |
{ |
527 |
{ |
|
|
528 |
if (reclimit++ > RECLIMIT || p->error == REG_ESPACE) { |
529 |
p->error = REG_ESPACE; |
530 |
return; |
531 |
} |
532 |
|
514 |
sopno start = HERE(); |
533 |
sopno start = HERE(); |
515 |
int first = 1; /* first subexpression? */ |
534 |
int first = 1; /* first subexpression? */ |
516 |
int wasdollar = 0; |
535 |
int wasdollar = 0; |
Lines 521-527
Link Here
|
521 |
p->g->nbol++; |
540 |
p->g->nbol++; |
522 |
} |
541 |
} |
523 |
while (MORE() && !SEETWO(end1, end2)) { |
542 |
while (MORE() && !SEETWO(end1, end2)) { |
524 |
wasdollar = p_simp_re(p, first); |
543 |
wasdollar = p_simp_re(p, first, reclimit); |
525 |
first = 0; |
544 |
first = 0; |
526 |
} |
545 |
} |
527 |
if (wasdollar) { /* oops, that was a trailing anchor */ |
546 |
if (wasdollar) { /* oops, that was a trailing anchor */ |
Lines 536-546
Link Here
|
536 |
|
555 |
|
537 |
/* |
556 |
/* |
538 |
- p_simp_re - parse a simple RE, an atom possibly followed by a repetition |
557 |
- p_simp_re - parse a simple RE, an atom possibly followed by a repetition |
539 |
== static int p_simp_re(struct parse *p, int starordinary); |
558 |
== static int p_simp_re(struct parse *p, int starordinary, size_t reclimit); |
540 |
*/ |
559 |
*/ |
541 |
static int /* was the simple RE an unbackslashed $? */ |
560 |
static int /* was the simple RE an unbackslashed $? */ |
542 |
p_simp_re(struct parse *p, |
561 |
p_simp_re(struct parse *p, |
543 |
int starordinary) /* is a leading * an ordinary character? */ |
562 |
int starordinary, /* is a leading * an ordinary character? */ |
|
|
563 |
size_t reclimit) |
544 |
{ |
564 |
{ |
545 |
int c; |
565 |
int c; |
546 |
int count; |
566 |
int count; |
Lines 580-586
Link Here
|
580 |
EMIT(OLPAREN, subno); |
600 |
EMIT(OLPAREN, subno); |
581 |
/* the MORE here is an error heuristic */ |
601 |
/* the MORE here is an error heuristic */ |
582 |
if (MORE() && !SEETWO('\\', ')')) |
602 |
if (MORE() && !SEETWO('\\', ')')) |
583 |
p_bre(p, '\\', ')'); |
603 |
p_bre(p, '\\', ')', reclimit); |
584 |
if (subno < NPAREN) { |
604 |
if (subno < NPAREN) { |
585 |
p->pend[subno] = HERE(); |
605 |
p->pend[subno] = HERE(); |
586 |
assert(p->pend[subno] != 0); |
606 |
assert(p->pend[subno] != 0); |
Lines 641-647
Link Here
|
641 |
count2 = INFINITY; |
661 |
count2 = INFINITY; |
642 |
} else /* just a single number */ |
662 |
} else /* just a single number */ |
643 |
count2 = count; |
663 |
count2 = count; |
644 |
repeat(p, pos, count, count2); |
664 |
repeat(p, pos, count, count2, 0); |
645 |
if (!EATTWO('\\', '}')) { /* error heuristics */ |
665 |
if (!EATTWO('\\', '}')) { /* error heuristics */ |
646 |
while (MORE() && !SEETWO('\\', '}')) |
666 |
while (MORE() && !SEETWO('\\', '}')) |
647 |
NEXT(); |
667 |
NEXT(); |
Lines 996-1008
Link Here
|
996 |
|
1016 |
|
997 |
/* |
1017 |
/* |
998 |
- repeat - generate code for a bounded repetition, recursively if needed |
1018 |
- repeat - generate code for a bounded repetition, recursively if needed |
999 |
== static void repeat(struct parse *p, sopno start, int from, int to); |
1019 |
== static void repeat(struct parse *p, sopno start, int from, int to, |
|
|
1020 |
== size_t reclimit ); |
1000 |
*/ |
1021 |
*/ |
1001 |
static void |
1022 |
static void |
1002 |
repeat(struct parse *p, |
1023 |
repeat(struct parse *p, |
1003 |
sopno start, /* operand from here to end of strip */ |
1024 |
sopno start, /* operand from here to end of strip */ |
1004 |
int from, /* repeated from this number */ |
1025 |
int from, /* repeated from this number */ |
1005 |
int to) /* to this number of times (maybe INFINITY) */ |
1026 |
int to, /* to this number of times (maybe INFINITY) */ |
|
|
1027 |
size_t reclimit) |
1006 |
{ |
1028 |
{ |
1007 |
sopno finish = HERE(); |
1029 |
sopno finish = HERE(); |
1008 |
# define N 2 |
1030 |
# define N 2 |
Lines 1011-1017
Link Here
|
1011 |
# define MAP(n) (((n) <= 1) ? (n) : ((n) == INFINITY) ? INF : N) |
1033 |
# define MAP(n) (((n) <= 1) ? (n) : ((n) == INFINITY) ? INF : N) |
1012 |
sopno copy; |
1034 |
sopno copy; |
1013 |
|
1035 |
|
1014 |
if (p->error != 0) /* head off possible runaway recursion */ |
1036 |
if (reclimit++ > RECLIMIT) |
|
|
1037 |
p->error = REG_ESPACE; |
1038 |
if (p->error) |
1015 |
return; |
1039 |
return; |
1016 |
|
1040 |
|
1017 |
assert(from <= to); |
1041 |
assert(from <= to); |
Lines 1025-1031
Link Here
|
1025 |
case REP(0, INF): /* as x{1,}? */ |
1049 |
case REP(0, INF): /* as x{1,}? */ |
1026 |
/* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ |
1050 |
/* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ |
1027 |
INSERT(OCH_, start); /* offset is wrong... */ |
1051 |
INSERT(OCH_, start); /* offset is wrong... */ |
1028 |
repeat(p, start+1, 1, to); |
1052 |
repeat(p, start+1, 1, to, reclimit); |
1029 |
ASTERN(OOR1, start); |
1053 |
ASTERN(OOR1, start); |
1030 |
AHEAD(start); /* ... fix it */ |
1054 |
AHEAD(start); /* ... fix it */ |
1031 |
EMIT(OOR2, 0); |
1055 |
EMIT(OOR2, 0); |
Lines 1045-1051
Link Here
|
1045 |
ASTERN(O_CH, THERETHERE()); |
1069 |
ASTERN(O_CH, THERETHERE()); |
1046 |
copy = dupl(p, start+1, finish+1); |
1070 |
copy = dupl(p, start+1, finish+1); |
1047 |
assert(copy == finish+4); |
1071 |
assert(copy == finish+4); |
1048 |
repeat(p, copy, 1, to-1); |
1072 |
repeat(p, copy, 1, to-1, reclimit); |
1049 |
break; |
1073 |
break; |
1050 |
case REP(1, INF): /* as x+ */ |
1074 |
case REP(1, INF): /* as x+ */ |
1051 |
INSERT(OPLUS_, start); |
1075 |
INSERT(OPLUS_, start); |
Lines 1053-1063
Link Here
|
1053 |
break; |
1077 |
break; |
1054 |
case REP(N, N): /* as xx{m-1,n-1} */ |
1078 |
case REP(N, N): /* as xx{m-1,n-1} */ |
1055 |
copy = dupl(p, start, finish); |
1079 |
copy = dupl(p, start, finish); |
1056 |
repeat(p, copy, from-1, to-1); |
1080 |
repeat(p, copy, from-1, to-1, reclimit); |
1057 |
break; |
1081 |
break; |
1058 |
case REP(N, INF): /* as xx{n-1,INF} */ |
1082 |
case REP(N, INF): /* as xx{n-1,INF} */ |
1059 |
copy = dupl(p, start, finish); |
1083 |
copy = dupl(p, start, finish); |
1060 |
repeat(p, copy, from-1, to); |
1084 |
repeat(p, copy, from-1, to, reclimit); |
1061 |
break; |
1085 |
break; |
1062 |
default: /* "can't happen" */ |
1086 |
default: /* "can't happen" */ |
1063 |
SETERROR(REG_ASSERT); /* just in case */ |
1087 |
SETERROR(REG_ASSERT); /* just in case */ |
Lines 1112-1119
Link Here
|
1112 |
{ |
1136 |
{ |
1113 |
cset *cs, *ncs; |
1137 |
cset *cs, *ncs; |
1114 |
|
1138 |
|
|
|
1139 |
|
1140 |
if (MEMSIZE(p) > MEMLIMIT) |
1141 |
goto oomem; |
1142 |
|
1115 |
ncs = realloc(p->g->sets, (p->g->ncsets + 1) * sizeof(*ncs)); |
1143 |
ncs = realloc(p->g->sets, (p->g->ncsets + 1) * sizeof(*ncs)); |
1116 |
if (ncs == NULL) { |
1144 |
if (ncs == NULL) { |
|
|
1145 |
oomem: |
1117 |
SETERROR(REG_ESPACE); |
1146 |
SETERROR(REG_ESPACE); |
1118 |
return (NULL); |
1147 |
return (NULL); |
1119 |
} |
1148 |
} |
Lines 1347-1363
Link Here
|
1347 |
enlarge(struct parse *p, sopno size) |
1376 |
enlarge(struct parse *p, sopno size) |
1348 |
{ |
1377 |
{ |
1349 |
sop *sp; |
1378 |
sop *sp; |
|
|
1379 |
sopno osize; |
1350 |
|
1380 |
|
1351 |
if (p->ssize >= size) |
1381 |
if (p->ssize >= size) |
1352 |
return 1; |
1382 |
return 1; |
1353 |
|
1383 |
osize = p->ssize; |
|
|
1384 |
p->ssize = size; |
1385 |
if (MEMSIZE(p) > MEMLIMIT) |
1386 |
goto oomem; |
1354 |
sp = (sop *)realloc(p->strip, size*sizeof(sop)); |
1387 |
sp = (sop *)realloc(p->strip, size*sizeof(sop)); |
1355 |
if (sp == NULL) { |
1388 |
if (sp == NULL) { |
|
|
1389 |
oomem: |
1390 |
p->ssize = osize; |
1356 |
SETERROR(REG_ESPACE); |
1391 |
SETERROR(REG_ESPACE); |
1357 |
return 0; |
1392 |
return 0; |
1358 |
} |
1393 |
} |
1359 |
p->strip = sp; |
1394 |
p->strip = sp; |
1360 |
p->ssize = size; |
|
|
1361 |
return 1; |
1395 |
return 1; |
1362 |
} |
1396 |
} |
1363 |
|
1397 |
|