[Support] Always wait for GraphViz before opening the viewer
[oota-llvm.git] / lib / Support / regcomp.c
index 4fd88b1249872b7904f2b49bb8ea86c74f60b0be..ebde64f9cf7512d2aa3168b66e1fa07c1b4d7823 100644 (file)
 #include "regcclass.h"
 #include "regcname.h"
 
+#include "llvm/Config/config.h"
+#if HAVE_STDINT_H
+#include <stdint.h>
+#else
+/* Pessimistically bound memory use */
+#define SIZE_MAX UINT_MAX
+#endif
+
 /*
  * parse structure, passed up and down to avoid global variables and
  * other clumsinesses
@@ -142,6 +150,7 @@ static char nuls[10];               /* place to point scanner in event of error */
 #else
 #define        DUPMAX  255
 #endif
+#define        INFINITY        (DUPMAX + 1)
 
 #ifndef NDEBUG
 static int never = 0;          /* for use in asserts; shuts lint up */
@@ -256,8 +265,8 @@ static void
 p_ere(struct parse *p, int stop)       /* character this ERE should end at */
 {
        char c;
-       sopno prevback = prevback;
-       sopno prevfwd = prevfwd;
+       sopno prevback = 0;
+       sopno prevfwd = 0;
        sopno conc;
        int first = 1;          /* is this the first alternative? */
 
@@ -302,6 +311,7 @@ p_ere_exp(struct parse *p)
        sopno pos;
        int count;
        int count2;
+       int backrefnum;
        sopno subno;
        int wascaret = 0;
 
@@ -369,7 +379,34 @@ p_ere_exp(struct parse *p)
        case '\\':
                REQUIRE(MORE(), REG_EESCAPE);
                c = GETNEXT();
-               ordinary(p, c);
+               if (c >= '1' && c <= '9') {
+                       /* \[0-9] is taken to be a back-reference to a previously specified
+                        * matching group. backrefnum will hold the number. The matching
+                        * group must exist (i.e. if \4 is found there must have been at
+                        * least 4 matching groups specified in the pattern previously).
+                        */
+                       backrefnum = c - '0';
+                       if (p->pend[backrefnum] == 0) {
+                               SETERROR(REG_ESUBREG);
+                               break;
+                       }
+
+                       /* Make sure everything checks out and emit the sequence
+                        * that marks a back-reference to the parse structure.
+                        */
+                       assert(backrefnum <= p->g->nsub);
+                       EMIT(OBACK_, backrefnum);
+                       assert(p->pbegin[backrefnum] != 0);
+                       assert(OP(p->strip[p->pbegin[backrefnum]]) != OLPAREN);
+                       assert(OP(p->strip[p->pend[backrefnum]]) != ORPAREN);
+                       (void) dupl(p, p->pbegin[backrefnum]+1, p->pend[backrefnum]);
+                       EMIT(O_BACK, backrefnum);
+                       p->g->backrefs = 1;
+               } else {
+                       /* Other chars are simply themselves when escaped with a backslash.
+                        */
+                       ordinary(p, c);
+               }
                break;
        case '{':               /* okay as ordinary except if digit follows */
                REQUIRE(!MORE() || !isdigit((uch)PEEK()), REG_BADRPT);
@@ -503,10 +540,10 @@ p_simp_re(struct parse *p,
        sopno subno;
 #      define  BACKSL  (1<<CHAR_BIT)
 
-       pos = HERE();           /* repetion op, if any, covers from here */
+        pos = HERE(); /* repetition op, if any, covers from here */
 
-       assert(MORE());         /* caller should have ensured this */
-       c = GETNEXT();
+        assert(MORE()); /* caller should have ensured this */
+        c = GETNEXT();
        if (c == '\\') {
                REQUIRE(MORE(), REG_EESCAPE);
                c = BACKSL | GETNEXT();
@@ -779,7 +816,7 @@ p_b_cclass(struct parse *p, cset *cs)
        const char *u;
        char c;
 
-       while (MORE() && isalpha(PEEK()))
+       while (MORE() && isalpha((uch)PEEK()))
                NEXT();
        len = p->next - sp;
        for (cp = cclasses; cp->name != NULL; cp++)
@@ -1040,6 +1077,8 @@ allocset(struct parse *p)
 
                p->ncsalloc += CHAR_BIT;
                nc = p->ncsalloc;
+               if (nc > SIZE_MAX / sizeof(cset))
+                       goto nomem;
                assert(nc % CHAR_BIT == 0);
                nbytes = nc / CHAR_BIT * css;
 
@@ -1383,6 +1422,11 @@ enlarge(struct parse *p, sopno size)
        if (p->ssize >= size)
                return;
 
+       if ((uintptr_t)size > SIZE_MAX / sizeof(sop)) {
+               SETERROR(REG_ESPACE);
+               return;
+       }
+
        sp = (sop *)realloc(p->strip, size*sizeof(sop));
        if (sp == NULL) {
                SETERROR(REG_ESPACE);
@@ -1399,6 +1443,12 @@ static void
 stripsnug(struct parse *p, struct re_guts *g)
 {
        g->nstates = p->slen;
+       if ((uintptr_t)p->slen > SIZE_MAX / sizeof(sop)) {
+               g->strip = p->strip;
+               SETERROR(REG_ESPACE);
+               return;
+       }
+
        g->strip = (sop *)realloc((char *)p->strip, p->slen * sizeof(sop));
        if (g->strip == NULL) {
                SETERROR(REG_ESPACE);
@@ -1419,8 +1469,8 @@ static void
 findmust(struct parse *p, struct re_guts *g)
 {
        sop *scan;
-       sop *start;    /* start initialized in the default case, after that */
-       sop *newstart; /* newstart was initialized in the OCHAR case */
+       sop *start = 0; /* start initialized in the default case, after that */
+       sop *newstart = 0; /* newstart was initialized in the OCHAR case */
        sopno newlen;
        sop s;
        char *cp;