diff options
author | Bram Moolenaar <Bram@vim.org> | 2009-11-25 17:21:32 +0000 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2009-11-25 17:21:32 +0000 |
commit | d3005803d5642c3aa45a52e57f4b34fb6b2a9239 (patch) | |
tree | 155b77b0dfd076d3c8bf3f7e2c702bc6e4ebeba8 /src/regexp.c | |
parent | 099d01d4a7187eb14af30d6182e552e64a302df1 (diff) | |
download | vim-git-d3005803d5642c3aa45a52e57f4b34fb6b2a9239.tar.gz |
updated for version 7.2-307v7.2.307
Diffstat (limited to 'src/regexp.c')
-rw-r--r-- | src/regexp.c | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/src/regexp.c b/src/regexp.c index dc0433dbf..9ce4cd8f8 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -583,6 +583,7 @@ static int re_has_z; /* \z item detected */ #endif static char_u *regcode; /* Code-emit pointer, or JUST_CALC_SIZE */ static long regsize; /* Code size. */ +static int reg_toolong; /* TRUE when offset out of range */ static char_u had_endbrace[NSUBEXP]; /* flags, TRUE if end of () found */ static unsigned regflags; /* RF_ flags for prog */ static long brace_min[10]; /* Minimums for complex brace repeats */ @@ -1028,9 +1029,11 @@ vim_regcomp(expr, re_flags) regcomp_start(expr, re_flags); regcode = r->program; regc(REGMAGIC); - if (reg(REG_NOPAREN, &flags) == NULL) + if (reg(REG_NOPAREN, &flags) == NULL || reg_toolong) { vim_free(r); + if (reg_toolong) + EMSG_RET_NULL(_("E339: Pattern too long")); return NULL; } @@ -1141,6 +1144,7 @@ regcomp_start(expr, re_flags) re_has_z = 0; #endif regsize = 0L; + reg_toolong = FALSE; regflags = 0; #if defined(FEAT_SYN_HL) || defined(PROTO) had_eol = FALSE; @@ -1228,7 +1232,7 @@ reg(paren, flagp) { skipchr(); br = regbranch(&flags); - if (br == NULL) + if (br == NULL || reg_toolong) return NULL; regtail(ret, br); /* BRANCH -> BRANCH. */ if (!(flags & HASWIDTH)) @@ -1313,6 +1317,8 @@ regbranch(flagp) break; skipchr(); regtail(latest, regnode(END)); /* operand ends */ + if (reg_toolong) + break; reginsert(MATCH, latest); chain = latest; } @@ -1382,7 +1388,7 @@ regconcat(flagp) break; default: latest = regpiece(&flags); - if (latest == NULL) + if (latest == NULL || reg_toolong) return NULL; *flagp |= flags & (HASWIDTH | HASNL | HASLOOKBH); if (chain == NULL) /* First piece. */ @@ -2540,8 +2546,16 @@ regtail(p, val) offset = (int)(scan - val); else offset = (int)(val - scan); - *(scan + 1) = (char_u) (((unsigned)offset >> 8) & 0377); - *(scan + 2) = (char_u) (offset & 0377); + /* When the offset uses more than 16 bits it can no longer fit in the two + * bytes avaliable. Use a global flag to avoid having to check return + * values in too many places. */ + if (offset > 0xffff) + reg_toolong = TRUE; + else + { + *(scan + 1) = (char_u) (((unsigned)offset >> 8) & 0377); + *(scan + 2) = (char_u) (offset & 0377); + } } /* @@ -5764,6 +5778,8 @@ do_class: /* * regnext - dig the "next" pointer out of a node + * Returns NULL when calculating size, when there is no next item and when + * there is an error. */ static char_u * regnext(p) @@ -5771,7 +5787,7 @@ regnext(p) { int offset; - if (p == JUST_CALC_SIZE) + if (p == JUST_CALC_SIZE || reg_toolong) return NULL; offset = NEXT(p); |