Skip to content

Bug fixes and test improvements#113

Merged
oschwald merged 6 commits intomainfrom
greg/fixes
Apr 26, 2026
Merged

Bug fixes and test improvements#113
oschwald merged 6 commits intomainfrom
greg/fixes

Conversation

@oschwald
Copy link
Copy Markdown
Owner

@oschwald oschwald commented Apr 26, 2026

  • Update MaxMind-DB fixtures
  • Validate search tree layout in reader
  • Improve test coverage of bad-database handling
  • Reject IPv6 CIDRs in within() with IPv4 trees
  • Tighten decoder verification bounds
  • Use actual IPv4 subtree depth for network

Summary by CodeRabbit

Bug Fixes

  • Database validation now rejects invalid search tree sizes to prevent runaway allocation
  • IPv6 CIDR iteration properly rejected for IPv4-only databases
  • Truncated scalar/string payloads now treated as invalid during verification
  • IPv4 network computation in IPv6 databases fixed to use accurate measured depth

Tests

  • Enhanced verification and boundary condition test coverage

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 26, 2026

Warning

Rate limit exceeded

@oschwald has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 4 minutes and 8 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 4 minutes and 8 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 256d2f69-ad3e-4f0f-afc5-8a1f69b0a351

📥 Commits

Reviewing files that changed from the base of the PR and between c5c9df0 and 3ce5264.

📒 Files selected for processing (8)
  • CHANGELOG.md
  • src/decoder.rs
  • src/lib.rs
  • src/reader.rs
  • src/reader_test.rs
  • src/result.rs
  • src/within.rs
  • test-data

Walkthrough

This pull request fixes several validation and correctness issues across the database reader, decoder, and result computation. Changes include rejecting invalid search tree sizes, preventing IPv6 CIDR iteration in IPv4-only databases, treating truncated payloads as invalid during verification, and computing network prefixes using the reader's measured IPv4 subtree depth instead of hardcoded offsets.

Changes

Cohort / File(s) Summary
Changelog
CHANGELOG.md
Documents five fixed-behavior notes: invalid search tree size rejection, IPv6 CIDR filtering for IPv4-only databases, truncated payload handling, and network prefix computation via reader metadata.
Decoder Bounds Validation
src/decoder.rs
Adds overflow-safe offset computation via checked_offset() for primitive payload skipping when pointer-following is disabled, preserving the unchecked fast path when enabled.
Reader Validation & Search Tree
src/reader.rs
Introduces fallible, overflow-safe search tree size computation with bounds validation, stricter input validation in within() for IPv6 CIDRs in IPv4-only databases, and new helper methods has_ipv4_subtree() and validate_search_tree_layout().
Network Prefix Computation
src/result.rs
Replaces hardcoded IPv4-in-IPv6 prefix thresholds with reader-driven metadata; now uses ipv4_start_bit_depth and has_ipv4_subtree() to determine correct IPv4 prefix handling.
Testing & Verification
src/lib.rs, src/reader_test.rs
Adds unit test validating network() uses cached IPv4 subtree depth; expands test coverage with invalid node count assertions, IPv6 CIDR rejection for IPv4 databases, exact error matching for broken pointers/trees, corrupted payload detection, and updated iteration expectations.
Test Data
test-data
Git submodule pinned commit update.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

  • PR #112: Overlapping modifications to reader/lookup/result/decoder logic with IPv4-subtree handling and network adjustment patterns.
  • PR #108: Concurrent changes to decoder and reader code paths introducing and using checked_offset() and IPv4-subtree start handling.
  • PR #107: Parallel bounds-validation and pointer-traversal improvements in decoder/reader with pointer-base and offset computation refinements.

Poem

🐰 A Rabbit's Celebration

In searching trees both large and small,
We bounds-check now, we verify all,
No truncated strings shall slip on by,
IPv4 math no longer shy,
Safe offsets dance, the rabbits cheer! 🥕✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Bug fixes and test improvements' is vague and overly generic, using non-descriptive terms that obscure the specific nature of the changes. Consider a more specific title reflecting the main fixes, such as 'Fix IPv4 subtree depth computation and search tree validation' or similar.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch greg/fixes

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/reader_test.rs`:
- Around line 1135-1144: The test in reader_test.rs currently asserts exact
equality on the error message inside the matches! pattern
(Err(MaxMindDbError::InvalidDatabase { ref message, .. }) and message == "search
tree appears to have a cycle or invalid structure (exceeded 492 iterations)"),
which couples the test to the fixture node_count; update the pattern to match
more robustly by checking the message starts with or contains the invariant
substring (e.g., message.starts_with("search tree appears to have a cycle") or
message.contains("search tree appears to have a cycle")) so the test no longer
depends on the exact iteration count.

In `@src/reader.rs`:
- Around line 730-751: The error message in search_tree_size_bytes is misleading
because the only failure is a checked_mul overflow; change the MaxMindDbError
text in search_tree_size_bytes to indicate an overflow or impossibly-large
search tree size (e.g., "search tree size calculation overflowed or is
impossibly large") so it is clearly distinct from the overlap/extent error
produced by validate_search_tree_layout; update the message used in
search_tree_size_bytes (and keep validate_search_tree_layout's existing message)
to make the two failure modes unambiguous.
- Around line 623-633: The code currently calls
find_metadata_start(self.buf.as_ref()) twice via verify_metadata() and
verify_database(); change verify() to compute metadata_start once (e.g., let
metadata_start = find_metadata_start(self.buf.as_ref())?) and pass that value
into verify_metadata(), verify_search_tree(), and verify_data_section() (or
store it on Reader if preferred), updating the signatures of
verify_metadata(&self, metadata_start: usize) and verify_database(&self,
metadata_start: usize) (and any helper like validate_search_tree_layout and
verify_data_section to accept the precomputed metadata_start) so the buffer scan
happens only once; keep pointer_base usage as-is since it is already cached at
construction.

In `@src/result.rs`:
- Around line 115-133: The branch selection that infers whether a prefix came
from iteration vs lookup by testing prefix_len ≤ 32 is ambiguous when
ipv4_start_bit_depth ≤ 32; instead add an explicit source flag on the
LookupResult (e.g., lookup_source: enum {Iter, Lookup}) and use that flag when
deciding how to adjust IPv4 prefix lengths in the code paths around
ipv4_start_bit_depth, prefix_len, and reader.has_ipv4_subtree(); update the
producer sites (iteration and lookup functions that construct LookupResult) to
set the flag and replace the numeric-based conditionals in the block handling
IpAddr::V6 with explicit checks against LookupResult::Iter vs
LookupResult::Lookup so the prefix subtraction logic is deterministic regardless
of ipv4_start_bit_depth.

In `@test-data`:
- Line 1: The test-data submodule pointer references a non-existent commit
(6e99232bb6a70d5169ecc96ed0614a52017ff654) which causes "not our ref" errors;
verify the correct commit SHA in the actual test-data repository and update the
superproject to point to a valid commit. To fix, check out the test-data repo,
identify the intended commit or branch (or create/push the missing commit), then
in the superproject update the submodule pointer to that valid SHA (or to the
correct branch head) and commit the change so the pointer in the submodule
reference for the test-data submodule matches an existing commit. Ensure you
push both the test-data repo (if you had to add the missing commit) and the
updated superproject commit so CI and other users can initialize submodules
successfully.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: a117a835-3d40-4f19-86e9-968b6c5b301c

📥 Commits

Reviewing files that changed from the base of the PR and between 429baa5 and c5c9df0.

📒 Files selected for processing (7)
  • CHANGELOG.md
  • src/decoder.rs
  • src/lib.rs
  • src/reader.rs
  • src/reader_test.rs
  • src/result.rs
  • test-data

Comment thread src/reader_test.rs
Comment on lines +1135 to +1144
matches!(
result,
Err(MaxMindDbError::InvalidDatabase { ref message, .. })
if message
== "search tree appears to have a cycle or invalid structure (exceeded 492 iterations)"
),
"Expected specific InvalidDatabase error for broken-search-tree, got {:?}",
result
);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Pinning the exact iteration count couples the test to the fixture's node_count.

exceeded 492 iterations is node_count * 3, so if MaxMind-DB-test-broken-search-tree-24.mmdb is ever regenerated with a different node count this test fails for an unrelated reason. Consider matching on a substring (message.starts_with("search tree appears to have a cycle")) to reduce coupling.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/reader_test.rs` around lines 1135 - 1144, The test in reader_test.rs
currently asserts exact equality on the error message inside the matches!
pattern (Err(MaxMindDbError::InvalidDatabase { ref message, .. }) and message ==
"search tree appears to have a cycle or invalid structure (exceeded 492
iterations)"), which couples the test to the fixture node_count; update the
pattern to match more robustly by checking the message starts with or contains
the invariant substring (e.g., message.starts_with("search tree appears to have
a cycle") or message.contains("search tree appears to have a cycle")) so the
test no longer depends on the exact iteration count.

Comment thread src/reader.rs Outdated
Comment thread src/reader.rs
Comment thread src/result.rs Outdated
Comment thread test-data Outdated
@oschwald oschwald merged commit b730a7c into main Apr 26, 2026
42 checks passed
@oschwald oschwald deleted the greg/fixes branch April 26, 2026 19:57
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 this pull request may close these issues.

1 participant