]> granicus.if.org Git - postgresql/blobdiff - src/include/regex/regguts.h
Add recursion depth protections to regular expression matching.
[postgresql] / src / include / regex / regguts.h
index 0cced701dbdc84578ff3d8df2dcbd91a65107064..327775235514e96de2352a1665e81db2a95a5a4a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Internal interface definitions, etc., for the reg package
  *
- * Copyright (c) 1998, 1999 Henry Spencer.     All rights reserved.
+ * Copyright (c) 1998, 1999 Henry Spencer.  All rights reserved.
  *
  * Development of this software was funded, in part, by Cray Research Inc.,
  * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
@@ -78,9 +78,6 @@
 #endif
 
 /* want size of a char in bits, and max value in bounded quantifiers */
-#ifndef CHAR_BIT
-#include <limits.h>
-#endif
 #ifndef _POSIX2_RE_DUP_MAX
 #define _POSIX2_RE_DUP_MAX     255 /* normally from <limits.h> */
 #endif
@@ -95,7 +92,7 @@
 #define xxx            1
 
 #define DUPMAX _POSIX2_RE_DUP_MAX
-#define INFINITY       (DUPMAX+1)
+#define DUPINF (DUPMAX+1)
 
 #define REMAGIC 0xfed7                 /* magic number for main struct */
 
 
 
 /*
- * We dissect a chr into byts for colormap table indexing.     Here we define
- * a byt, which will be the same as a byte on most machines... The exact
+ * We dissect a chr into byts for colormap table indexing.  Here we define
+ * a byt, which will be the same as a byte on most machines...  The exact
  * size of a byt is not critical, but about 8 bits is good, and extraction
  * of 8-bit chunks is sometimes especially fast.
  */
 typedef short color;                   /* colors of characters */
 typedef int pcolor;                            /* what color promotes to */
 
+#define MAX_COLOR      32767           /* max color (must fit in 'color' datatype) */
 #define COLORLESS      (-1)            /* impossible color */
 #define WHITE          0                       /* default color, parent of all others */
 
@@ -155,12 +153,16 @@ typedef int pcolor;                               /* what color promotes to */
 
 /*
  * A colormap is a tree -- more precisely, a DAG -- indexed at each level
- * by a byt of the chr, to map the chr to a color efficiently. Because
+ * by a byt of the chr, to map the chr to a color efficiently.  Because
  * lower sections of the tree can be shared, it can exploit the usual
- * sparseness of such a mapping table. The tree is always NBYTS levels
+ * sparseness of such a mapping table.  The tree is always NBYTS levels
  * deep (in the past it was shallower during construction but was "filled"
  * to full depth at the end of that); areas that are unaltered as yet point
  * to "fill blocks" which are entirely WHITE in color.
+ *
+ * Leaf-level tree blocks are of type "struct colors", while upper-level
+ * blocks are of type "struct ptrs".  Pointers into the tree are generally
+ * declared as "union tree *" to be agnostic about what level they point to.
  */
 
 /* the tree itself */
@@ -178,37 +180,58 @@ union tree
        struct ptrs ptrs;
 };
 
+/* use these pseudo-field names when dereferencing a "union tree" pointer */
 #define tcolor colors.ccolor
 #define tptr   ptrs.pptr
 
-/* internal per-color descriptor structure for the color machinery */
+/*
+ * Per-color data structure for the compile-time color machinery
+ *
+ * If "sub" is not NOSUB then it is the number of the color's current
+ * subcolor, i.e. we are in process of dividing this color (character
+ * equivalence class) into two colors.  See src/backend/regex/README for
+ * discussion of subcolors.
+ *
+ * Currently-unused colors have the FREECOL bit set and are linked into a
+ * freelist using their "sub" fields, but only if their color numbers are
+ * less than colormap.max.  Any array entries beyond "max" are just garbage.
+ */
 struct colordesc
 {
        uchr            nchrs;                  /* number of chars of this color */
-       color           sub;                    /* open subcolor (if any); free chain ptr */
-#define  NOSUB  COLORLESS
-       struct arc *arcs;                       /* color chain */
-       int                     flags;
+       color           sub;                    /* open subcolor, if any; or free-chain ptr */
+#define  NOSUB  COLORLESS              /* value of "sub" when no open subcolor */
+       struct arc *arcs;                       /* chain of all arcs of this color */
+       chr                     firstchr;               /* char first assigned to this color */
+       int                     flags;                  /* bit values defined next */
 #define  FREECOL 01                            /* currently free */
 #define  PSEUDO  02                            /* pseudocolor, no real chars */
-#define  UNUSEDCOLOR(cd) ((cd)->flags&FREECOL)
+#define  UNUSEDCOLOR(cd) ((cd)->flags & FREECOL)
        union tree *block;                      /* block of solid color, if any */
 };
 
-/* the color map itself */
+/*
+ * The color map itself
+ *
+ * Much of the data in the colormap struct is only used at compile time.
+ * However, the bulk of the space usage is in the "tree" structure, so it's
+ * not clear that there's much point in converting the rest to a more compact
+ * form when compilation is finished.
+ */
 struct colormap
 {
        int                     magic;
 #define  CMMAGIC 0x876
        struct vars *v;                         /* for compile error reporting */
-       size_t          ncds;                   /* number of colordescs */
-       size_t          max;                    /* highest in use */
+       size_t          ncds;                   /* allocated length of colordescs array */
+       size_t          max;                    /* highest color number currently in use */
        color           free;                   /* beginning of free chain (if non-0) */
-       struct colordesc *cd;
+       struct colordesc *cd;           /* pointer to array of colordescs */
 #define  CDEND(cm)      (&(cm)->cd[(cm)->max + 1])
+       /* If we need up to NINLINECDS, we store them here to save a malloc */
 #define  NINLINECDS  ((size_t)10)
        struct colordesc cdspace[NINLINECDS];
-       union tree      tree[NBYTS];    /* tree top, plus fill blocks */
+       union tree      tree[NBYTS];    /* tree top, plus lower-level fill blocks */
 };
 
 /* optimization magic to do fast chr->color mapping */
@@ -229,19 +252,25 @@ struct colormap
 
 
 /*
- * Interface definitions for locale-interface functions in locale.c.
+ * Interface definitions for locale-interface functions in regc_locale.c.
  */
 
-/* Representation of a set of characters. */
+/*
+ * Representation of a set of characters.  chrs[] represents individual
+ * code points, ranges[] represents ranges in the form min..max inclusive.
+ *
+ * Note that in cvecs gotten from newcvec() and intended to be freed by
+ * freecvec(), both arrays of chrs are after the end of the struct, not
+ * separately malloc'd; so chrspace and rangespace are effectively immutable.
+ */
 struct cvec
 {
        int                     nchrs;                  /* number of chrs */
-       int                     chrspace;               /* number of chrs possible */
+       int                     chrspace;               /* number of chrs allocated in chrs[] */
        chr                *chrs;                       /* pointer to vector of chrs */
        int                     nranges;                /* number of ranges (chr pairs) */
-       int                     rangespace;             /* number of chrs possible */
+       int                     rangespace;             /* number of ranges allocated in ranges[] */
        chr                *ranges;                     /* pointer to vector of chr pairs */
-       /* both batches of chrs are on the end */
 };
 
 
@@ -255,15 +284,14 @@ struct state;
 
 struct arc
 {
-       int                     type;
-#define  ARCFREE '\0'
+       int                     type;                   /* 0 if free, else an NFA arc type code */
        color           co;
        struct state *from;                     /* where it's from (and contained within) */
        struct state *to;                       /* where it's to */
-       struct arc *outchain;           /* *from's outs chain or free chain */
+       struct arc *outchain;           /* link in *from's outs chain or free chain */
 #define  freechain      outchain
-       struct arc *inchain;            /* *to's ins chain */
-       struct arc *colorchain;         /* color's arc chain */
+       struct arc *inchain;            /* link in *to's ins chain */
+       struct arc *colorchain;         /* link in color's arc chain */
        struct arc *colorchainRev;      /* back-link in color's arc chain */
 };
 
@@ -305,8 +333,8 @@ struct nfa
        color           bos[2];                 /* colors, if any, assigned to BOS and BOL */
        color           eos[2];                 /* colors, if any, assigned to EOS and EOL */
        size_t          size;                   /* Current NFA size; differs from nstates as
-                                                                * it also counts the number of states created
-                                                                * by children of this state. */
+                                                                * it also counts the number of states in
+                                                                * children of this NFA. */
        struct vars *v;                         /* simplifies compile error reporting */
        struct nfa *parent;                     /* parent NFA, if any */
 };
@@ -315,24 +343,38 @@ struct nfa
 
 /*
  * definitions for compacted NFA
+ *
+ * The main space savings in a compacted NFA is from making the arcs as small
+ * as possible.  We store only the transition color and next-state number for
+ * each arc.  The list of out arcs for each state is an array beginning at
+ * cnfa.states[statenumber], and terminated by a dummy carc struct with
+ * co == COLORLESS.
+ *
+ * The non-dummy carc structs are of two types: plain arcs and LACON arcs.
+ * Plain arcs just store the transition color number as "co".  LACON arcs
+ * store the lookahead constraint number plus cnfa.ncolors as "co".  LACON
+ * arcs can be distinguished from plain by testing for co >= cnfa.ncolors.
  */
 struct carc
 {
        color           co;                             /* COLORLESS is list terminator */
-       int                     to;                             /* state number */
+       int                     to;                             /* next-state number */
 };
 
 struct cnfa
 {
        int                     nstates;                /* number of states */
-       int                     ncolors;                /* number of colors */
+       int                     ncolors;                /* number of colors (max color in use + 1) */
        int                     flags;
-#define  HASLACONS      01                     /* uses lookahead constraints */
+#define  HASLACONS     01                      /* uses lookahead constraints */
        int                     pre;                    /* setup state number */
        int                     post;                   /* teardown state number */
        color           bos[2];                 /* colors, if any, assigned to BOS and BOL */
        color           eos[2];                 /* colors, if any, assigned to EOS and EOL */
+       char       *stflags;            /* vector of per-state flags bytes */
+#define  CNFA_NOPROGRESS       01      /* flag bit for a no-progress state */
        struct carc **states;           /* vector of pointers to outarc lists */
+       /* states[n] are pointers into a single malloc'd array of arcs */
        struct carc *arcs;                      /* the area for the lists */
 };
 
@@ -348,29 +390,47 @@ struct cnfa
 
 /*
  * subexpression tree
+ *
+ * "op" is one of:
+ *             '='  plain regex without interesting substructure (implemented as DFA)
+ *             'b'  back-reference (has no substructure either)
+ *             '('  capture node: captures the match of its single child
+ *             '.'  concatenation: matches a match for left, then a match for right
+ *             '|'  alternation: matches a match for left or a match for right
+ *             '*'  iteration: matches some number of matches of its single child
+ *
+ * Note: the right child of an alternation must be another alternation or
+ * NULL; hence, an N-way branch requires N alternation nodes, not N-1 as you
+ * might expect.  This could stand to be changed.  Actually I'd rather see
+ * a single alternation node with N children, but that will take revising
+ * the representation of struct subre.
+ *
+ * Note: when a backref is directly quantified, we stick the min/max counts
+ * into the backref rather than plastering an iteration node on top.  This is
+ * for efficiency: there is no need to search for possible division points.
  */
 struct subre
 {
-       char            op;                             /* '|', '.' (concat), 'b' (backref), '(', '=' */
+       char            op;                             /* see type codes above */
        char            flags;
 #define  LONGER  01                            /* prefers longer match */
 #define  SHORTER 02                            /* prefers shorter match */
 #define  MIXED  04                             /* mixed preference below */
-#define  CAP 010                               /* capturing parens below */
+#define  CAP    010                    /* capturing parens below */
 #define  BACKR  020                    /* back reference below */
 #define  INUSE  0100                   /* in use in final tree */
-#define  LOCAL  03                             /* bits which may not propagate up */
+#define  NOPROP  03                            /* bits which may not propagate up */
 #define  LMIX(f) ((f)<<2)              /* LONGER -> MIXED */
 #define  SMIX(f) ((f)<<1)              /* SHORTER -> MIXED */
-#define  UP(f)  (((f)&~LOCAL) | (LMIX(f) & SMIX(f) & MIXED))
+#define  UP(f)  (((f)&~NOPROP) | (LMIX(f) & SMIX(f) & MIXED))
 #define  MESSY(f)       ((f)&(MIXED|CAP|BACKR))
-#define  PREF(f) ((f)&LOCAL)
+#define  PREF(f) ((f)&NOPROP)
 #define  PREF2(f1, f2)  ((PREF(f1) != 0) ? PREF(f1) : PREF(f2))
 #define  COMBINE(f1, f2) (UP((f1)|(f2)) | PREF2(f1, f2))
-       short           retry;                  /* index into retry memory */
+       short           id;                             /* ID of subre (1..ntree-1) */
        int                     subno;                  /* subexpression number (for 'b' and '(') */
-       short           min;                    /* min repetitions, for backref only */
-       short           max;                    /* max repetitions, for backref only */
+       short           min;                    /* min repetitions for iteration or backref */
+       short           max;                    /* max repetitions for iteration or backref */
        struct subre *left;                     /* left child, if any (also freelist chain) */
        struct subre *right;            /* right child, if any */
        struct state *begin;            /* outarcs from here... */
@@ -388,8 +448,15 @@ struct subre
 struct fns
 {
        void            FUNCPTR(free, (regex_t *));
+       int                     FUNCPTR(cancel_requested, (void));
+       int                     FUNCPTR(stack_too_deep, (void));
 };
 
+#define CANCEL_REQUESTED(re)  \
+       ((*((struct fns *) (re)->re_fns)->cancel_requested) ())
+
+#define STACK_TOO_DEEP(re)     \
+       ((*((struct fns *) (re)->re_fns)->stack_too_deep) ())
 
 
 /*
@@ -404,7 +471,7 @@ struct guts
        size_t          nsub;                   /* copy of re_nsub */
        struct subre *tree;
        struct cnfa search;                     /* for fast preliminary search */
-       int                     ntree;
+       int                     ntree;                  /* number of subre's, plus one */
        struct colormap cmap;
        int                     FUNCPTR(compare, (const chr *, const chr *, size_t));
        struct subre *lacons;           /* lookahead-constraint vector */