From 9ec69a2b57163f8cf70c6d0307b11d23fb2c923a Mon Sep 17 00:00:00 2001 From: Colin Finck Date: Wed, 18 Aug 2021 23:18:24 +0200 Subject: Don't revisit a last entry with subnode in `NtfsIndexEntries` Add a test that would have caught this. --- src/index.rs | 20 ++++++++++++++------ src/index_entry.rs | 3 ++- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/index.rs b/src/index.rs index 5c122fc..0814ecf 100644 --- a/src/index.rs +++ b/src/index.rs @@ -12,6 +12,7 @@ use binread::io::{Read, Seek}; use core::cmp::Ordering; use core::marker::PhantomData; +#[derive(Clone, Debug)] pub struct NtfsIndex<'n, 'f, E> where E: NtfsIndexEntryType, @@ -61,6 +62,7 @@ where /// returning an [`NtfsIndexEntry`] for each entry. /// /// See [`NtfsIndexEntriesAttached`] for an iterator that implements [`Iterator`] and [`FusedIterator`]. +#[derive(Clone, Debug)] pub struct NtfsIndexEntries<'n, 'f, 'i, E> where E: NtfsIndexEntryType, @@ -115,6 +117,7 @@ where if let Some(entry_range) = iter.next() { // Convert that `IndexEntryRange` to a (lifetime-bound) `NtfsIndexEntry`. let entry = entry_range.to_entry(iter.data()); + let is_last_entry = entry.flags().contains(NtfsIndexEntryFlags::LAST_ENTRY); // Does this entry have a subnode that needs to be iterated first? if let Some(subnode_vcn) = entry.subnode_vcn() { @@ -132,13 +135,16 @@ where )); let subnode_iter = subnode.into_entry_ranges(); - // Save this subnode's iterator and the entry range. - // We'll pick up the iterator through `self.inner_iterators.last_mut()` in the - // next loop iteration, and we will return that entry as soon as the subnode iterator - // has been fully iterated. + // Save this subnode's iterator. + // We'll pick it up through `self.inner_iterators.last_mut()` in the next loop iteration. self.inner_iterators.push(subnode_iter); - self.following_entries.push(entry_range); - } else if !entry.flags().contains(NtfsIndexEntryFlags::LAST_ENTRY) { + + if !is_last_entry { + // This is not the empty "last entry", so save it as well. + // We'll pick it up again after the subnode iterator has been fully iterated. + self.following_entries.push(entry_range); + } + } else if !is_last_entry { // There is no subnode, and this is not the empty "last entry", // so our `entry` comes next lexicographically. break entry_range; @@ -321,5 +327,7 @@ mod tests { let entry_name = entry.key().unwrap().unwrap(); assert_eq!(entry_name.name(), dir_name.as_str()); } + + assert!(subdir_iter.next(&mut testfs1).is_none()); } } diff --git a/src/index_entry.rs b/src/index_entry.rs index c84b67f..b6fcb55 100644 --- a/src/index_entry.rs +++ b/src/index_entry.rs @@ -203,6 +203,7 @@ where } } +#[derive(Clone, Debug)] pub(crate) struct IndexNodeEntryRanges where E: NtfsIndexEntryType, @@ -248,7 +249,7 @@ where // Get the current entry. let start = self.range.start; let position = self.position; - let entry = NtfsIndexEntry::<'_, E>::new(&self.data[start..], position); + let entry = NtfsIndexEntry::::new(&self.data[start..], position); let end = start + entry.index_entry_length() as usize; if entry.flags().contains(NtfsIndexEntryFlags::LAST_ENTRY) { -- cgit v1.2.3