sikol/patricia

Negative test cases for patricia_set<>::prefix_match()?

Opened this issue · 3 comments

If in tests/ip_prefix.cxx I add db.lookup("ff01:db8:1000::43")
it returns ::1/128
what not seem to be correct.

E.g. db.lookup() always returns "something", even though it shouldn't.

Would it be possible to provide example of how to check, if some IP address is NOT in IP prefix database?
May be something like contains() method in class prefix_set?

I can reproduce this issue as well.

Here's minimal example to to reproduce:

namespace {

struct sliced_byte {
  std::byte byte{0xFF};
  size_t bits{8};
};

auto slice = [](auto byte, size_t bits) {
  return sliced_byte{static_cast<std::byte>(byte), bits};
};

struct sliced_byte_keymaker {
  template <class U>
  struct rebind {
    using other = sliced_byte_keymaker;
  };

  auto operator()(sliced_byte x) -> sk::patricia_key {
    return {std::span<const std::byte>{&x.byte, 1}, x.bits};
  }
};

} // namespace

TEST(ensure no false positives during prefix match) {
  auto xs = sk::patricia_map<sliced_byte, int8_t, sliced_byte_keymaker>{};
  xs[slice(0xff, 4)] = 42;
  CHECK_EQUAL(xs.prefix_match(slice(0xff, 1)), xs.end());
  CHECK_EQUAL(xs.prefix_match(slice(0xff, 2)), xs.end());
  CHECK_EQUAL(xs.prefix_match(slice(0xff, 3)), xs.end());
  CHECK_NOT_EQUAL(xs.prefix_match(slice(0xff, 4)), xs.end()); // fails: exact match
  CHECK_NOT_EQUAL(xs.prefix_match(slice(0xff, 5)), xs.end()); // fails: prefix match
  CHECK_NOT_EQUAL(xs.prefix_match(slice(0xff, 6)), xs.end()); // fails: prefix match
  CHECK_NOT_EQUAL(xs.prefix_match(slice(0xff, 7)), xs.end()); // fails: prefix match
  CHECK_NOT_EQUAL(xs.prefix_match(slice(0xff, 8)), xs.end()); // fails: prefix match
}

I'm seeing some non-deterministic behavior. When I instrument the library with extra logging, all of a sudden these tests pass.

I have a hunch: the node has a patricia_key as member function, which is effectively a span plus bit length. If the original object the span points to no longer exists, wouldn't the accessed memory be invalid? Or is there some copying taking place?