diff options
author | Andrew Gallant <jamslam@gmail.com> | 2018-02-02 01:01:08 +0300 |
---|---|---|
committer | Andrew Gallant <jamslam@gmail.com> | 2018-02-02 01:01:08 +0300 |
commit | e2b898329f64f71db06a5a0049fed5e22888aa42 (patch) | |
tree | d7785d906b164b6fb927cab78428bbbd1daa93ac | |
parent | 34857644e6ef90c60e000cba22809b923b79bb9e (diff) |
traversal: more robust error handling
This fixes a bug in walkdir that happened on Windows when following
symlinks. It was triggered when opening a handle to the symlink failed.
In particular, this resulted in the two stacks in the walkdir iterator
getting out of sync. At some point, this tripped a panic when popping
from one stack would be fine but popping from the other failed because
it was empty.
We fix this by only pushing to both stacks if and only if both pushes
would succeed.
This bug was found via ripgrep. See:
https://github.com/BurntSushi/ripgrep/issues/633#issuecomment-339076246
-rw-r--r-- | src/lib.rs | 4 |
1 files changed, 3 insertions, 1 deletions
@@ -851,13 +851,15 @@ impl IntoIter { }); list = DirList::Closed(entries.into_iter()); } - self.stack_list.push(list); if self.opts.follow_links { let ancestor = Ancestor::new(&dent).map_err(|err| { Error::from_io(self.depth, err) })?; self.stack_path.push(ancestor); } + // We push this after stack_path since creating the Ancestor can fail. + // If it fails, then we return the error and won't descend. + self.stack_list.push(list); Ok(()) } |