Mercurial > vim
changeset 2010:bec979a53f47 v7.2.307
updated for version 7.2-307
author | vimboss |
---|---|
date | Wed, 25 Nov 2009 17:21:32 +0000 |
parents | c5a806b29372 |
children | a3a4be6bdcdd |
files | src/regexp.c src/version.c |
diffstat | 2 files changed, 24 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- 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);