summaryrefslogtreecommitdiff
path: root/src/regexp.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2009-11-25 17:21:32 +0000
committerBram Moolenaar <Bram@vim.org>2009-11-25 17:21:32 +0000
commitd3005803d5642c3aa45a52e57f4b34fb6b2a9239 (patch)
tree155b77b0dfd076d3c8bf3f7e2c702bc6e4ebeba8 /src/regexp.c
parent099d01d4a7187eb14af30d6182e552e64a302df1 (diff)
downloadvim-git-d3005803d5642c3aa45a52e57f4b34fb6b2a9239.tar.gz
updated for version 7.2-307v7.2.307
Diffstat (limited to 'src/regexp.c')
-rw-r--r--src/regexp.c28
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);