📄 100-netfilter_layer7_2.17.patch
字号:
+ if (*g->regparse == ')') {+ FAIL("unmatched ()");+ } else+ FAIL("junk on end"); /* "Can't happen". */+ /* NOTREACHED */+ }++ return(ret);+}++/*+ - regbranch - one alternative of an | operator+ *+ * Implements the concatenation operator.+ */+static char *+regbranch(struct match_globals *g, int *flagp)+{+ register char *ret;+ register char *chain;+ register char *latest;+ int flags;++ *flagp = WORST; /* Tentatively. */++ ret = regnode(g, BRANCH);+ chain = NULL;+ while (*g->regparse != '\0' && *g->regparse != '|' && *g->regparse != ')') {+ latest = regpiece(g, &flags);+ if (latest == NULL)+ return(NULL);+ *flagp |= flags&HASWIDTH;+ if (chain == NULL) /* First piece. */+ *flagp |= flags&SPSTART;+ else+ regtail(g, chain, latest);+ chain = latest;+ }+ if (chain == NULL) /* Loop ran zero times. */+ (void) regnode(g, NOTHING);++ return(ret);+}++/*+ - regpiece - something followed by possible [*+?]+ *+ * Note that the branching code sequences used for ? and the general cases+ * of * and + are somewhat optimized: they use the same NOTHING node as+ * both the endmarker for their branch list and the body of the last branch.+ * It might seem that this node could be dispensed with entirely, but the+ * endmarker role is not redundant.+ */+static char *+regpiece(struct match_globals *g, int *flagp)+{+ register char *ret;+ register char op;+ register char *next;+ int flags;++ ret = regatom(g, &flags);+ if (ret == NULL)+ return(NULL);++ op = *g->regparse;+ if (!ISMULT(op)) {+ *flagp = flags;+ return(ret);+ }++ if (!(flags&HASWIDTH) && op != '?')+ FAIL("*+ operand could be empty");+ *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);++ if (op == '*' && (flags&SIMPLE))+ reginsert(g, STAR, ret);+ else if (op == '*') {+ /* Emit x* as (x&|), where & means "self". */+ reginsert(g, BRANCH, ret); /* Either x */+ regoptail(g, ret, regnode(g, BACK)); /* and loop */+ regoptail(g, ret, ret); /* back */+ regtail(g, ret, regnode(g, BRANCH)); /* or */+ regtail(g, ret, regnode(g, NOTHING)); /* null. */+ } else if (op == '+' && (flags&SIMPLE))+ reginsert(g, PLUS, ret);+ else if (op == '+') {+ /* Emit x+ as x(&|), where & means "self". */+ next = regnode(g, BRANCH); /* Either */+ regtail(g, ret, next);+ regtail(g, regnode(g, BACK), ret); /* loop back */+ regtail(g, next, regnode(g, BRANCH)); /* or */+ regtail(g, ret, regnode(g, NOTHING)); /* null. */+ } else if (op == '?') {+ /* Emit x? as (x|) */+ reginsert(g, BRANCH, ret); /* Either x */+ regtail(g, ret, regnode(g, BRANCH)); /* or */+ next = regnode(g, NOTHING); /* null. */+ regtail(g, ret, next);+ regoptail(g, ret, next);+ }+ g->regparse++;+ if (ISMULT(*g->regparse))+ FAIL("nested *?+");++ return(ret);+}++/*+ - regatom - the lowest level+ *+ * Optimization: gobbles an entire sequence of ordinary characters so that+ * it can turn them into a single node, which is smaller to store and+ * faster to run. Backslashed characters are exceptions, each becoming a+ * separate node; the code is simpler that way and it's not worth fixing.+ */+static char *+regatom(struct match_globals *g, int *flagp)+{+ register char *ret;+ int flags;++ *flagp = WORST; /* Tentatively. */++ switch (*g->regparse++) {+ case '^':+ ret = regnode(g, BOL);+ break;+ case '$':+ ret = regnode(g, EOL);+ break;+ case '.':+ ret = regnode(g, ANY);+ *flagp |= HASWIDTH|SIMPLE;+ break;+ case '[': {+ register int class;+ register int classend;++ if (*g->regparse == '^') { /* Complement of range. */+ ret = regnode(g, ANYBUT);+ g->regparse++;+ } else+ ret = regnode(g, ANYOF);+ if (*g->regparse == ']' || *g->regparse == '-')+ regc(g, *g->regparse++);+ while (*g->regparse != '\0' && *g->regparse != ']') {+ if (*g->regparse == '-') {+ g->regparse++;+ if (*g->regparse == ']' || *g->regparse == '\0')+ regc(g, '-');+ else {+ class = UCHARAT(g->regparse-2)+1;+ classend = UCHARAT(g->regparse);+ if (class > classend+1)+ FAIL("invalid [] range");+ for (; class <= classend; class++)+ regc(g, class);+ g->regparse++;+ }+ } else+ regc(g, *g->regparse++);+ }+ regc(g, '\0');+ if (*g->regparse != ']')+ FAIL("unmatched []");+ g->regparse++;+ *flagp |= HASWIDTH|SIMPLE;+ }+ break;+ case '(':+ ret = reg(g, 1, &flags);+ if (ret == NULL)+ return(NULL);+ *flagp |= flags&(HASWIDTH|SPSTART);+ break;+ case '\0':+ case '|':+ case ')':+ FAIL("internal urp"); /* Supposed to be caught earlier. */+ break;+ case '?':+ case '+':+ case '*':+ FAIL("?+* follows nothing");+ break;+ case '\\':+ if (*g->regparse == '\0')+ FAIL("trailing \\");+ ret = regnode(g, EXACTLY);+ regc(g, *g->regparse++);+ regc(g, '\0');+ *flagp |= HASWIDTH|SIMPLE;+ break;+ default: {+ register int len;+ register char ender;++ g->regparse--;+ len = my_strcspn((const char *)g->regparse, (const char *)META);+ if (len <= 0)+ FAIL("internal disaster");+ ender = *(g->regparse+len);+ if (len > 1 && ISMULT(ender))+ len--; /* Back off clear of ?+* operand. */+ *flagp |= HASWIDTH;+ if (len == 1)+ *flagp |= SIMPLE;+ ret = regnode(g, EXACTLY);+ while (len > 0) {+ regc(g, *g->regparse++);+ len--;+ }+ regc(g, '\0');+ }+ break;+ }++ return(ret);+}++/*+ - regnode - emit a node+ */+static char * /* Location. */+regnode(struct match_globals *g, char op)+{+ register char *ret;+ register char *ptr;++ ret = g->regcode;+ if (ret == &g->regdummy) {+ g->regsize += 3;+ return(ret);+ }++ ptr = ret;+ *ptr++ = op;+ *ptr++ = '\0'; /* Null "next" pointer. */+ *ptr++ = '\0';+ g->regcode = ptr;++ return(ret);+}++/*+ - regc - emit (if appropriate) a byte of code+ */+static void+regc(struct match_globals *g, char b)+{+ if (g->regcode != &g->regdummy)+ *g->regcode++ = b;+ else+ g->regsize++;+}++/*+ - reginsert - insert an operator in front of already-emitted operand+ *+ * Means relocating the operand.+ */+static void+reginsert(struct match_globals *g, char op, char* opnd)+{+ register char *src;+ register char *dst;+ register char *place;++ if (g->regcode == &g->regdummy) {+ g->regsize += 3;+ return;+ }++ src = g->regcode;+ g->regcode += 3;+ dst = g->regcode;+ while (src > opnd)+ *--dst = *--src;++ place = opnd; /* Op node, where operand used to be. */+ *place++ = op;+ *place++ = '\0';+ *place++ = '\0';+}++/*+ - regtail - set the next-pointer at the end of a node chain+ */+static void+regtail(struct match_globals *g, char *p, char *val)+{+ register char *scan;+ register char *temp;+ register int offset;++ if (p == &g->regdummy)+ return;++ /* Find last node. */+ scan = p;+ for (;;) {+ temp = regnext(g, scan);+ if (temp == NULL)+ break;+ scan = temp;+ }++ if (OP(scan) == BACK)+ offset = scan - val;+ else+ offset = val - scan;+ *(scan+1) = (offset>>8)&0377;+ *(scan+2) = offset&0377;+}++/*+ - regoptail - regtail on operand of first argument; nop if operandless+ */+static void+regoptail(struct match_globals *g, char *p, char *val)+{+ /* "Operandless" and "op != BRANCH" are synonymous in practice. */+ if (p == NULL || p == &g->regdummy || OP(p) != BRANCH)+ return;+ regtail(g, OPERAND(p), val);+}++/*+ * regexec and friends+ */+++/*+ * Forwards.+ */+STATIC int regtry(struct match_globals *g, regexp *prog, char *string);+STATIC int regmatch(struct match_globals *g, char *prog);+STATIC int regrepeat(struct match_globals *g, char *p);++#ifdef DEBUG+int regnarrate = 0;+void regdump();+STATIC char *regprop(char *op);+#endif++/*+ - regexec - match a regexp against a string+ */+int+regexec(regexp *prog, char *string)+{+ register char *s;+ struct match_globals g;++ /* Be paranoid... */+ if (prog == NULL || string == NULL) {+ printk("<3>Regexp: NULL parameter\n");+ return(0);+ }++ /* Check validity of program. */+ if (UCHARAT(prog->program) != MAGIC) {+ printk("<3>Regexp: corrupted program\n");+ return(0);+ }++ /* If there is a "must appear" string, look for it. */+ if (prog->regmust != NULL) {+ s = string;+ while ((s = strchr(s, prog->regmust[0])) != NULL) {+ if (strncmp(s, prog->regmust, prog->regmlen) == 0)+ break; /* Found it. */+ s++;+ }+ if (s == NULL) /* Not present. */+ return(0);+ }++ /* Mark beginning of line for ^ . */+ g.regbol = string;++ /* Simplest case: anchored match need be tried only once. */+ if (prog->reganch)+ return(regtry(&g, prog, string));++ /* Messy cases: unanchored match. */+ s = string;+ if (prog->regstart != '\0')+ /* We know what char it must start with. */+ while ((s = strchr(s, prog->regstart)) != NULL) {+ if (regtry(&g, prog, s))+ return(1);+ s++;+ }+ else+ /* We don't -- general case. */+ do {+ if (regtry(&g, prog, s))+ return(1);+ } while (*s++ != '\0');++ /* Failure. */+ return(0);+}++/*+ - regtry - try match at specific point+ */+static int /* 0 failure, 1 success */+regtry(struct match_globals *g, regexp *prog, char *string)+{+ register int i;+ register char **sp;+ register char **ep;++ g->reginput = string;+ g->regstartp = prog->startp;+ g->regendp = prog->endp;++ sp = prog->startp;+ ep = prog->endp;+ for (i = NSUBEXP; i > 0; i--) {+ *sp++ = NULL;+ *ep++ = NULL;+ }+ if (regmatch(g, prog->program + 1)) {+ prog->startp[0] = string;+ prog->endp[0] = g->reginput;+ return(1);+ } else+ return(0);+}++/*+ - regmatch - main matching routine+ *+ * Conceptually the strategy is simple: check to see whether the current+ * node matches, call self recursively to see whether the rest matches,+ * and then act accordingly. In practice we make some effort to avoid+ * recursion, in particular by going through "ordinary" nodes (that don't+ * need to know whether the rest of the match failed) by a loop instead of+ * by recursion.+ */+static int /* 0 failure, 1 success */+regmatch(struct match_globals *g, char *prog)+{+ register char *scan = prog; /* Current node. */+ char *next; /* Next node. */++#ifdef DEBUG+ if (scan != NULL && regnarrate)+ fprintf(stderr, "%s(\n", regprop(scan));+#endif+ while (scan != NULL) {+#ifdef DEBUG+ if (regnarrate)+ fprintf(stderr, "%s...\n", regprop(scan));+#endif+ next = regnext(g, scan);++ switch (OP(scan)) {+ case BOL:+ if (g->reginput != g->regbol)+ return(0);+ break;+ case EOL:+ if (*g->reginput != '\0')+ return(0);+ break;+ case ANY:+ if (*g->reginput == '\0')+ return(0);+ g->reginput++;+ break;+ case EXACTLY: {+ register int len;+ register char *opnd;++ opnd = OPERAND(scan);+ /* Inline the first character, for speed. */+ if (*opnd != *g->reginput)+ return(0);+ len = strlen(opnd);+ if (len > 1 && strncmp(opnd, g->reginput, len) != 0)+ return(0);+ g->reginput += len;+ }+ break;+ case ANYOF:+ if (*g->reginput == '\0' || strchr(OPERAND(scan), *g->reginput) == NULL)+ return(0);+ g->reginput++;+ break;+ case ANYBUT:+ if (*g->reginput == '\0' || strchr(OPERAND(scan), *g->reginput) != NULL)+ return(0);+ g->reginput++;+ break;+ case NOTHING:+ case BACK:+ break;+ case OPEN+1:+ case OPEN+2:+ case OPEN+3:+ case OPEN+4:+ case OPEN+5:+ case OPEN+6:+ case OPEN+7:+ case OPEN+8:+ case OPEN+9: {+ register int no;+ register char *save;++ no = OP(scan) - OPEN;+ save = g->reginput;++ if (regmatch(g, next)) {+ /*+ * Don't set startp if some later+ * invocation of the same parentheses+ * already has.+ */+ if (g->regstartp[no] == NULL)+ g->regstartp[no] = save;+ return(1);+ } else+ return(0);+ }+ break;+ case CLOSE+1:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -