Skip to content

fix out-of-bounds read on blueprint index in Router::get_found_bp - #1276

Open
nishat-06 wants to merge 1 commit into
CrowCpp:masterfrom
nishat-06:router-blueprint-index-bounds-check
Open

nishat-06 wants to merge 1 commit into
CrowCpp:masterfrom
nishat-06:router-blueprint-index-bounds-check

Conversation

@nishat-06

Copy link
Copy Markdown
Contributor

get_found_bp rebuilds the matched blueprint chain from found.blueprint_indices, where each value is a blueprint's index within its parent's child list. The verify_prefix() lambda checks bp_i[index] against the list size only on the matched (if) path; the else path indexes blueprints_[bp_i[index]] and last_element->blueprints_[bp_i[index]] with no bounds check.

When a parent blueprint has no route of its own, no trie node carries its index. That is the normal case under CROW_DISABLE_STATIC_DIR, where run() skips add_blueprint()/add_static_dir() so a static-dir blueprint never gets a route of its own. A 404 under one of its child blueprints then leaves the child's parent-relative index as the first entry of blueprint_indices, and get_found_bp indexes the router's top-level blueprint vector with it, reading past the end when it is larger than the number of top-level blueprints. The out-of-bounds Blueprint* is pushed into found_bps and later dereferenced by get_catch_all()/get_error(), so it is reachable from any unauthenticated request URL that 404s under such a blueprint.

The fix applies the same bounds check the if-path already uses before both indexing sites, falling back to the global catchall when the index is out of range.

Added blueprint_catchall_oob to tests/unittest.cpp: it registers a parent blueprint with two child blueprints, validates without the static-dir routes (the CROW_DISABLE_STATIC_DIR path), and sends a 404 under the second child. It fails on master under -fsanitize=address (heap-buffer-overflow in get_found_bp at routing.h:1566) and passes with this change. The full test suite stays green under the ci-sanitize build.

get_found_bp rebuilds the matched blueprint chain from
found.blueprint_indices, each entry being a blueprint's position in its
parent's child list. verify_prefix() checks bp_i[index] against the list
size only on the matched path; the else branch indexes blueprints_ and
last_element->blueprints_ with no check. A parent blueprint that
registers no route of its own (e.g. under CROW_DISABLE_STATIC_DIR) leaves
a child's parent-relative index as the first collected index, so a 404
under that child reads past the top-level blueprint vector and the
garbage Blueprint* is later dereferenced. Reuse the existing bounds check
before both indexing sites.

This branch has not been deployed

No deployments
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