From e9a05ed6fa1668e76699e360b300f828d52747dd Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Fri, 29 Dec 2023 22:18:04 +0100 Subject: [PATCH] Fix overlap bug in LCS (#59) * Fix overlap bug in LCS * Mention pull request --- CHANGELOG.md | 2 ++ src/algorithms/lcs.rs | 30 +++++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0d9aff..b69881a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ All notable changes to similar are documented here. ## 2.4.0 * Fixed a bug where the LCS diff algorithm didn't always call `D::finish`. (#58) +* Fixed a bug in LCS that caused a panic if the common prefix and the + common suffix overlapped. (#59) ## 2.3.0 diff --git a/src/algorithms/lcs.rs b/src/algorithms/lcs.rs index ffead40..70c13d8 100644 --- a/src/algorithms/lcs.rs +++ b/src/algorithms/lcs.rs @@ -64,7 +64,12 @@ where } let common_prefix_len = common_prefix_len(old, old_range.clone(), new, new_range.clone()); - let common_suffix_len = common_suffix_len(old, old_range.clone(), new, new_range.clone()); + let common_suffix_len = common_suffix_len( + old, + old_range.start + common_prefix_len..old_range.end, + new, + new_range.start + common_prefix_len..new_range.end, + ); // If the sequences are not different then we're done if common_prefix_len == old_range.len() && (old_range.len() == new_range.len()) { @@ -266,3 +271,26 @@ fn test_finish_called() { diff(&mut d, slice, 0..slice.len(), slice, 0..slice.len()).unwrap(); assert!(d.0); } + +#[test] +fn test_bad_range_regression() { + use crate::algorithms::Capture; + use crate::DiffOp; + let mut d = Capture::new(); + diff(&mut d, &[0], 0..1, &[0, 0], 0..2).unwrap(); + assert_eq!( + d.into_ops(), + vec![ + DiffOp::Equal { + old_index: 0, + new_index: 0, + len: 1 + }, + DiffOp::Insert { + old_index: 1, + new_index: 1, + new_len: 1 + } + ] + ); +}