Skip to content

Commit 9d65427

Browse files
committed
fix: normalize_path overflow shielding "//" path
fix #992
1 parent 30b41fa commit 9d65427

2 files changed

Lines changed: 28 additions & 5 deletions

File tree

include/boost/url/impl/url_base.hpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2149,10 +2149,11 @@ normalize_path()
21492149
// remove_dot_segments can produce output that
21502150
// needs a 2-byte shield prefix, as explained
21512151
// in step 2. The memmove below writes within
2152-
// the original path region (before shrink_impl)
2153-
// and always has room because ".." cancellation
2154-
// consumes >= 5 bytes but we only need 2 for the
2155-
// shield.
2152+
// the path region; when ".." cancellation has
2153+
// consumed >= 2 bytes there is already slack,
2154+
// but for short inputs that take the shield
2155+
// branch without any cancellation (e.g. "//"),
2156+
// the region has to grow to fit the prefix.
21562157
//
21572158
bool needs_shield = [&]()
21582159
{
@@ -2204,7 +2205,14 @@ normalize_path()
22042205
}();
22052206
if (needs_shield)
22062207
{
2207-
BOOST_ASSERT(n + 2 <= pn);
2208+
if (n + 2 > pn)
2209+
{
2210+
// No ".. cancellation slack — grow the path
2211+
// region to fit the 2-byte shield. p_dest may
2212+
// be invalidated by the underlying reallocation.
2213+
p_dest = resize_impl(id_path, n + 2, op);
2214+
pn = n + 2;
2215+
}
22082216
std::memmove(p_dest + 2, p_dest, n);
22092217
if (was_absolute)
22102218
{

test/unit/url.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,6 +1333,21 @@ struct url_test
13331333
check("", "");
13341334
}
13351335

1336+
// normalize path without authority: a "//" path must
1337+
// grow the buffer before prepending the "/." shield.
1338+
// https://github.com/boostorg/url/issues/992
1339+
{
1340+
auto check = [](core::string_view p,
1341+
core::string_view e) {
1342+
url u = parse_origin_form(p).value();
1343+
u.normalize();
1344+
BOOST_TEST_EQ(u.encoded_path(), e);
1345+
};
1346+
check("//", "/.//");
1347+
check("///", "/.///");
1348+
check("////", "/.////");
1349+
}
1350+
13361351
// inequality
13371352
{
13381353
auto check = [](core::string_view e1,

0 commit comments

Comments
 (0)