Skip to content
This repository was archived by the owner on Mar 22, 2024. It is now read-only.

Commit 39a648b

Browse files
committed
fix OpAssert positive lookbehind
1 parent 11532c5 commit 39a648b

File tree

4 files changed

+36
-4
lines changed

4 files changed

+36
-4
lines changed

src/engine.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -490,14 +490,24 @@ impl OpcodeDispatcher {
490490
SreOpcode::ASSERT => twice(
491491
|drive| {
492492
let back = drive.peek_code(2) as usize;
493-
let passed = drive.ctx().string_position - drive.state.start;
493+
let passed = drive.ctx().string_position;
494494
if passed < back {
495495
drive.ctx_mut().has_matched = Some(false);
496496
return None;
497497
}
498+
let back_offset = drive
499+
.state
500+
.string
501+
.back_offset(drive.ctx().string_offset, back);
502+
498503
drive.state.string_position = drive.ctx().string_position - back;
504+
499505
drive.push_new_context(3);
500-
drive.state.context_stack.last_mut().unwrap().toplevel = false;
506+
let child_ctx = drive.state.context_stack.last_mut().unwrap();
507+
child_ctx.toplevel = false;
508+
child_ctx.string_position -= back;
509+
child_ctx.string_offset = back_offset;
510+
501511
Some(())
502512
},
503513
|drive| {
@@ -512,14 +522,24 @@ impl OpcodeDispatcher {
512522
SreOpcode::ASSERT_NOT => twice(
513523
|drive| {
514524
let back = drive.peek_code(2) as usize;
515-
let passed = drive.ctx().string_position - drive.state.start;
525+
let passed = drive.ctx().string_position;
516526
if passed < back {
517527
drive.skip_code(drive.peek_code(1) as usize + 1);
518528
return None;
519529
}
530+
let back_offset = drive
531+
.state
532+
.string
533+
.back_offset(drive.ctx().string_offset, back);
534+
520535
drive.state.string_position = drive.ctx().string_position - back;
536+
521537
drive.push_new_context(3);
522-
drive.state.context_stack.last_mut().unwrap().toplevel = false;
538+
let child_ctx = drive.state.context_stack.last_mut().unwrap();
539+
child_ctx.toplevel = false;
540+
child_ctx.string_position -= back;
541+
child_ctx.string_offset = back_offset;
542+
523543
Some(())
524544
},
525545
|drive| {

tests/positive_lookbehind.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
re.compile(r'(?<=abc)def')

tests/positive_lookbehind.re

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// '(?<=abc)def', flags=re.UNICODE
2+
Pattern { code: &[15, 4, 0, 3, 3, 4, 9, 3, 17, 97, 17, 98, 17, 99, 1, 17, 100, 17, 101, 17, 102, 1], flags: SreFlag::from_bits_truncate(32) }

tests/tests.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,12 @@ fn test_2427() {
2424
state = state.pymatch();
2525
assert!(state.has_matched == Some(true));
2626
}
27+
28+
#[test]
29+
fn test_assert() {
30+
// '(?<=abc)def', flags=re.UNICODE
31+
let pattern = include!("positive_lookbehind.re");
32+
let mut state = pattern.state("abcdef", 0..usize::MAX);
33+
state = state.search();
34+
assert!(state.has_matched == Some(true));
35+
}

0 commit comments

Comments
 (0)