Skip to content

fix: normalize_path overflow shielding "//" path#995

Merged
alandefreitas merged 1 commit into
boostorg:developfrom
alandefreitas:develop
May 13, 2026
Merged

fix: normalize_path overflow shielding "//" path#995
alandefreitas merged 1 commit into
boostorg:developfrom
alandefreitas:develop

Conversation

@alandefreitas
Copy link
Copy Markdown
Member

@alandefreitas alandefreitas commented May 13, 2026

Closes #992.

Problem

auto u = boost::urls::parse_origin_form("//").value();
boost::urls::url{u}.normalize();

triggers BOOST_ASSERT(n + 2 <= pn) in url_base::normalize_path (include/boost/url/impl/url_base.hpp:2207). With assertions disabled the subsequent memmove writes past the end of the path region — a real heap buffer overflow.

Root cause

When the URL has no authority and the normalized path starts with //, normalize_path prepends a 2-byte /. shield so the round-tripped string isn't re-parsed as an authority. The pre-existing comment claimed this memmove always has room because .. cancellation consumes ≥ 5 bytes, and the shield only needs 2.

That's true for the cancellation case (/a/..//x/x/.//x, with slack from the canceled segments). It's not true for short inputs that hit the shield branch with no cancellation:

  • "//" (pn = 2, n = 2) — wants 4 bytes for /.//
  • "///" (pn = 3, n = 3) — wants 5 bytes for /.///
  • ...

parse_origin_form produces exactly such paths (origin-form has no authority).

Fix

include/boost/url/impl/url_base.hpp:2205-2222 — before the memmove, grow the path region with resize_impl(id_path, n + 2, op) when n + 2 > pn. Re-read p_dest from the resize return value (the underlying storage may have moved) and update pn so the later if (n != pn) shrink branch behaves correctly.

The surrounding comment was updated: the shield branch now requires either ≥ 2 bytes of cancellation slack or a buffer grow, instead of the previous overstated invariant.

Tests

test/unit/url.cpp — a new block in the existing normalize-path section asserts:

parse_origin_form("//").value().normalize().encoded_path()   == "/.//"
parse_origin_form("///").value().normalize().encoded_path()  == "/.///"
parse_origin_form("////").value().normalize().encoded_path() == "/.////"

The first case is the exact reproducer from the issue. The other two cover the same shieldless-// family with extra trailing slashes.

All 42324 unit-test assertions and 79 ctest entries pass locally under C++20 (./test_all.sh patterns).

@cppalliance-bot
Copy link
Copy Markdown

An automated preview of the documentation is available at https://995.url.prtest2.cppalliance.org/index.html

If more commits are pushed to the pull request, the docs will rebuild at the same URL.

2026-05-13 14:12:31 UTC

@cppalliance-bot
Copy link
Copy Markdown

GCOVR code coverage report https://995.url.prtest2.cppalliance.org/gcovr/index.html
LCOV code coverage report https://995.url.prtest2.cppalliance.org/genhtml/index.html
Coverage Diff Report https://995.url.prtest2.cppalliance.org/diff-report/index.html

Build time: 2026-05-13 14:24:07 UTC

@codecov
Copy link
Copy Markdown

codecov Bot commented May 13, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.12%. Comparing base (30b41fa) to head (6b3367f).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff            @@
##           develop     #995   +/-   ##
========================================
  Coverage    99.12%   99.12%           
========================================
  Files          154      154           
  Lines        10091    10093    +2     
========================================
+ Hits         10003    10005    +2     
  Misses          88       88           
Files with missing lines Coverage Δ
include/boost/url/impl/url_base.hpp 99.47% <100.00%> (+<0.01%) ⬆️

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 30b41fa...6b3367f. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@alandefreitas alandefreitas merged commit 9d65427 into boostorg:develop May 13, 2026
51 checks passed
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.

normalize_path triggers assertion in boost 1.91

2 participants