treebitmap
treebitmap copied to clipboard
Panic on remove()
I'm getting an occasional panic using this library on calling IpLookupTable.remove(). Panic location is below:
thread '<unnamed>' panicked at 'index out of bounds: the len is 0 but the index is 0', /cargo/registry/src/github.com-1ecc6299db9ec823/treebitmap-0.4.0/src/tree_bitmap/mod.rs:297:22
The Rust binary in question is processing a couple hundred full BGP feeds but the list of prefixes which trigger the panic is suspiciously small... 49.255.11.17/32 is by far the most frequent culprit. It doesn't seem to happen every time and I have yet to be able to reliably reproduce it in a simple example. All the prefixes that trigger the crashes are /32 IPv4 prefixes.
I added some debug logging and something looks odd. I started logging whenever I insert that prefix so I know it's been seen. Immediately before the panic I dump the table to a file and the prefix exists, however if I try to lookup the prefix using either exact_match() or longest_match() I get a None back..
I realise this is probably tricky to troubleshoot without a reliable reproduction, but any tips on where I can start looking? I tried a build with this line changed to an assert!() but it still gets past that, so something seems to be happening in remove_child()
Actually - I can reproduce it with a pretty small example. This is using 0.4 from crates.io
use treebitmap::IpLookupTable;
use std::error::Error;
use std::net::Ipv4Addr;
const ADDR: Ipv4Addr = Ipv4Addr::new(49, 255, 11, 17);
fn main() -> Result<(), Box<dyn Error>> {
let mut table = IpLookupTable::new();
table.insert( Ipv4Addr::new(49, 255, 11, 16), 28, ());
table.insert( ADDR, 32, ());
println!("exact_match: {:?}", table.exact_match(ADDR, 32));
println!("longest_match: {:?}", table.longest_match(ADDR));
let v = table.remove(ADDR, 32);
println!("removed: {:?}", v);
Ok(())
}
Looks like a bug with overlapping subnets.