Skip to content

Commit

Permalink
VIM-856 Fix regex lookbehind bugs
Browse files Browse the repository at this point in the history
The regex code has the following bugs, mostly related to lookbehind:
    - Comparison of CharPointers with == is wrong, .equals should be
      used instead.

    - In the original C code, the behind_pos variable is declared as
      'static regsave_T behind_pos;', i.e. not a pointer, and the same
      for other variables of type regsave_T. So assignments to these
      types of variables need to make deep copies.
  • Loading branch information
dezgeg committed Jan 20, 2015
1 parent dcd0353 commit 5090c81
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 6 deletions.
20 changes: 14 additions & 6 deletions src/com/maddyhome/idea/vim/regexp/RegExp.java
Expand Up @@ -3051,7 +3051,7 @@ else if (next.OP() >= BRACE_COMPLEX
if (--count < minval) {
break;
}
if (reginput == regline) {
if (reginput.equals(regline)) {
/* backup to last char of previous line */
--reglnum;
regline = reg_getline(reglnum);
Expand Down Expand Up @@ -3132,7 +3132,7 @@ else if (next.OP() >= BRACE_COMPLEX
case BEHIND:
case NOBEHIND: {
regsave_T save_after = new regsave_T(), save_start = new regsave_T();
regsave_T save_behind_pos = new regsave_T();
regsave_T save_behind_pos;
boolean needmatch = (op == BEHIND);

/*
Expand All @@ -3153,8 +3153,8 @@ else if (next.OP() >= BRACE_COMPLEX
* line (for multi-line matching).
* Set behind_pos to where the match should end, BHPOS
* will match it. */
save_behind_pos = behind_pos;
behind_pos = save_start;
save_behind_pos = behind_pos == null ? null : new regsave_T(behind_pos);
behind_pos = new regsave_T(save_start);
while (true) {
reg_restore(save_start);
if (regmatch(scan.OPERAND()) && reg_save_equal(behind_pos)) {
Expand Down Expand Up @@ -3676,9 +3676,9 @@ private void reg_restore(@NotNull regsave_T save) {
*/
private boolean reg_save_equal(@NotNull regsave_T save) {
if (reg_match == null) {
return reglnum == save.pos.lnum && reginput == regline.ref(save.pos.col);
return reglnum == save.pos.lnum && reginput.equals(regline.ref(save.pos.col));
}
return reginput == save.ptr;
return reginput.equals(save.ptr);
}

/*
Expand Down Expand Up @@ -4694,6 +4694,14 @@ public lpos_T() {
private static class regsave_T {
CharPointer ptr; /* reginput pointer, for single-line regexp */
@NotNull lpos_T pos = new lpos_T(); /* reginput pos, for multi-line regexp */

public regsave_T() {
}

public regsave_T(regsave_T rhs) {
ptr = rhs.ptr == null ? null : new CharPointer("").assign(rhs.ptr);
pos = new lpos_T(rhs.pos);
}
}

/* struct to save start/end pointer/position in for \(\) */
Expand Down
7 changes: 7 additions & 0 deletions test/org/jetbrains/plugins/ideavim/group/SearchGroupTest.java
Expand Up @@ -88,6 +88,13 @@ public void testCharacterClassRegressionCaseInsensitive() {
assertEquals(-1, pos);
}

// VIM-856 |/|
public void testNegativeLookbehindRegression() {
final int pos = search("a\\@<!b",
"<caret>ab\n");
assertEquals(-1, pos);
}

// |/|
public void testSearchMotion() {
typeTextInFile(parseKeys("/", "two", "<Enter>"),
Expand Down

0 comments on commit 5090c81

Please sign in to comment.