@@ -683,6 +683,8 @@ delsub(struct nfa * nfa,
683683 rp -> tmp = rp ; /* mark end */
684684
685685 deltraverse (nfa , lp , lp );
686+ if (NISERR ())
687+ return ; /* asserts might not hold after failure */
686688 assert (lp -> nouts == 0 && rp -> nins == 0 ); /* did the job */
687689 assert (lp -> no != FREESTATE && rp -> no != FREESTATE ); /* no more */
688690
@@ -702,6 +704,13 @@ deltraverse(struct nfa * nfa,
702704 struct arc * a ;
703705 struct state * to ;
704706
707+ /* Since this is recursive, it could be driven to stack overflow */
708+ if (STACK_TOO_DEEP (nfa -> v -> re ))
709+ {
710+ NERR (REG_ETOOBIG );
711+ return ;
712+ }
713+
705714 if (s -> nouts == 0 )
706715 return ; /* nothing to do */
707716 if (s -> tmp != NULL )
@@ -713,6 +722,8 @@ deltraverse(struct nfa * nfa,
713722 {
714723 to = a -> to ;
715724 deltraverse (nfa , leftend , to );
725+ if (NISERR ())
726+ return ; /* asserts might not hold after failure */
716727 assert (to -> nouts == 0 || to -> tmp != NULL );
717728 freearc (nfa , a );
718729 if (to -> nins == 0 && to -> tmp == NULL )
@@ -767,6 +778,13 @@ duptraverse(struct nfa * nfa,
767778{
768779 struct arc * a ;
769780
781+ /* Since this is recursive, it could be driven to stack overflow */
782+ if (STACK_TOO_DEEP (nfa -> v -> re ))
783+ {
784+ NERR (REG_ETOOBIG );
785+ return ;
786+ }
787+
770788 if (s -> tmp != NULL )
771789 return ; /* already done */
772790
@@ -796,6 +814,13 @@ cleartraverse(struct nfa * nfa,
796814{
797815 struct arc * a ;
798816
817+ /* Since this is recursive, it could be driven to stack overflow */
818+ if (STACK_TOO_DEEP (nfa -> v -> re ))
819+ {
820+ NERR (REG_ETOOBIG );
821+ return ;
822+ }
823+
799824 if (s -> tmp == NULL )
800825 return ;
801826 s -> tmp = NULL ;
@@ -1284,7 +1309,7 @@ fixempties(struct nfa * nfa,
12841309 */
12851310 for (s = nfa -> states ; s != NULL && !NISERR (); s = s -> next )
12861311 {
1287- for (s2 = emptyreachable (s , s ); s2 != s && !NISERR (); s2 = nexts )
1312+ for (s2 = emptyreachable (nfa , s , s ); s2 != s && !NISERR (); s2 = nexts )
12881313 {
12891314 /*
12901315 * If s2 is doomed, we decide that (1) we will always push arcs
@@ -1342,19 +1367,28 @@ fixempties(struct nfa * nfa,
13421367 *
13431368 * The maximum recursion depth here is equal to the length of the longest
13441369 * loop-free chain of EMPTY arcs, which is surely no more than the size of
1345- * the NFA, and in practice will be a lot less than that .
1370+ * the NFA ... but that could still be enough to cause trouble .
13461371 */
13471372static struct state *
1348- emptyreachable (struct state * s , struct state * lastfound )
1373+ emptyreachable (struct nfa * nfa ,
1374+ struct state * s ,
1375+ struct state * lastfound )
13491376{
13501377 struct arc * a ;
13511378
1379+ /* Since this is recursive, it could be driven to stack overflow */
1380+ if (STACK_TOO_DEEP (nfa -> v -> re ))
1381+ {
1382+ NERR (REG_ETOOBIG );
1383+ return lastfound ;
1384+ }
1385+
13521386 s -> tmp = lastfound ;
13531387 lastfound = s ;
13541388 for (a = s -> outs ; a != NULL ; a = a -> outchain )
13551389 {
13561390 if (a -> type == EMPTY && a -> to -> tmp == NULL )
1357- lastfound = emptyreachable (a -> to , lastfound );
1391+ lastfound = emptyreachable (nfa , a -> to , lastfound );
13581392 }
13591393 return lastfound ;
13601394}
@@ -1433,19 +1467,22 @@ cleanup(struct nfa * nfa)
14331467 struct state * nexts ;
14341468 int n ;
14351469
1470+ if (NISERR ())
1471+ return ;
1472+
14361473 /* clear out unreachable or dead-end states */
14371474 /* use pre to mark reachable, then post to mark can-reach-post */
14381475 markreachable (nfa , nfa -> pre , (struct state * ) NULL , nfa -> pre );
14391476 markcanreach (nfa , nfa -> post , nfa -> pre , nfa -> post );
1440- for (s = nfa -> states ; s != NULL ; s = nexts )
1477+ for (s = nfa -> states ; s != NULL && ! NISERR () ; s = nexts )
14411478 {
14421479 nexts = s -> next ;
14431480 if (s -> tmp != nfa -> post && !s -> flag )
14441481 dropstate (nfa , s );
14451482 }
1446- assert (nfa -> post -> nins == 0 || nfa -> post -> tmp == nfa -> post );
1483+ assert (NISERR () || nfa -> post -> nins == 0 || nfa -> post -> tmp == nfa -> post );
14471484 cleartraverse (nfa , nfa -> pre );
1448- assert (nfa -> post -> nins == 0 || nfa -> post -> tmp == NULL );
1485+ assert (NISERR () || nfa -> post -> nins == 0 || nfa -> post -> tmp == NULL );
14491486 /* the nins==0 (final unreachable) case will be caught later */
14501487
14511488 /* renumber surviving states */
@@ -1466,6 +1503,13 @@ markreachable(struct nfa * nfa,
14661503{
14671504 struct arc * a ;
14681505
1506+ /* Since this is recursive, it could be driven to stack overflow */
1507+ if (STACK_TOO_DEEP (nfa -> v -> re ))
1508+ {
1509+ NERR (REG_ETOOBIG );
1510+ return ;
1511+ }
1512+
14691513 if (s -> tmp != okay )
14701514 return ;
14711515 s -> tmp = mark ;
@@ -1485,6 +1529,13 @@ markcanreach(struct nfa * nfa,
14851529{
14861530 struct arc * a ;
14871531
1532+ /* Since this is recursive, it could be driven to stack overflow */
1533+ if (STACK_TOO_DEEP (nfa -> v -> re ))
1534+ {
1535+ NERR (REG_ETOOBIG );
1536+ return ;
1537+ }
1538+
14881539 if (s -> tmp != okay )
14891540 return ;
14901541 s -> tmp = mark ;
@@ -1502,6 +1553,9 @@ analyze(struct nfa * nfa)
15021553 struct arc * a ;
15031554 struct arc * aa ;
15041555
1556+ if (NISERR ())
1557+ return 0 ;
1558+
15051559 if (nfa -> pre -> outs == NULL )
15061560 return REG_UIMPOSSIBLE ;
15071561 for (a = nfa -> pre -> outs ; a != NULL ; a = a -> outchain )
0 commit comments