# HG changeset patch # User vimboss # Date 1259169692 0 # Node ID bec979a53f47ff6866d390eff6c4ddd4d5ce8a8b # Parent c5a806b29372c033c3b616083c86159a8719635c updated for version 7.2-307 diff --git a/src/regexp.c b/src/regexp.c --- 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); diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -682,6 +682,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 307, +/**/ 306, /**/ 305,