Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kad: potentially wrong returned value when calling Addresses::remove with a non present address #4815

Closed
stormshield-frb opened this issue Nov 7, 2023 · 0 comments · Fixed by #4816

Comments

@stormshield-frb
Copy link
Contributor

Summary

There is an incoherence between the documentation of protocols::kad::src::addresses.rs::Addresses::remove() and its implementation.

Indeed, the documentation states that it returns Err(()) if the address is the last remaining address, which cannot be removed. However, when calling remove and there is only one address left, Err(()) is returned no matter what, event if the provided address was not in the self.addrs field.

pub fn remove(&mut self, addr: &Multiaddr) -> Result<(), ()> {
if self.addrs.len() == 1 {
return Err(());
}
if let Some(pos) = self.addrs.iter().position(|a| a == addr) {
self.addrs.remove(pos);
if self.addrs.len() <= self.addrs.inline_size() {
self.addrs.shrink_to_fit();
}
}
Ok(())
}

As we can see at line 70, there is no check to determine if the last address is indeed the one provided.

Expected behavior

let addr1 = "/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().unwrap();
let addr2 = "/ip4/127.0.0.1/tcp/4321".parse::<Multiaddr>().unwrap();

let mut addresses = Addresses::new(addr1.clone());

// addr2 is not present so calling remove should return Ok(()) and be a no-op as mentioned in the doc:
// "Returns `Ok(())` if the address is either not in the list or was found and removed"
assert_eq!(Ok(()), addresses.remove(&addr2));

// addr1 is present but is the last one so it should return Err(()) and be a no-op as mentioned in the doc:
// "Returns `Err(())` if the address is the last remaining address, which cannot be removed."
assert_eq!(Err(()), addresses.remove(&addr1));

Actual behavior

let addr1 = "/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().unwrap();
let addr2 = "/ip4/127.0.0.1/tcp/4321".parse::<Multiaddr>().unwrap();

let mut addresses = Addresses::new(addr1.clone());

// addr2 is not present so calling remove should return Ok(()) and be a no-op as mentioned in the doc:
// "Returns `Ok(())` if the address is either not in the list or was found and removed"
// However, it currently returns Err(()) because there is no check to assert the last remaining address
// does match the provided one
assert_eq!(Err(()), addresses.remove(&addr2));

Relevant log output

No response

Possible Solution

No response

Version

libp2p-kad: 0.45.0 & master

Would you like to work on fixing this bug ?

Yes

@mergify mergify bot closed this as completed in #4816 Nov 10, 2023
mergify bot pushed a commit that referenced this issue Nov 10, 2023
Adding a check when there is only one address left in the list of `Addresses` to verify that the remaining one does match the provided one when calling `remove`.

Fixes: #4815.

Pull-Request: #4816.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant