Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions include/boost/url/detail/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,9 @@

// Limit tests
#ifndef BOOST_URL_MAX_SIZE
// we leave room for a null,
// and still fit in size_t
#define BOOST_URL_MAX_SIZE ((std::size_t(-1))-1)
// leave room for a null terminator and
// fit within url_impl's 32-bit offsets
#define BOOST_URL_MAX_SIZE ((std::size_t)UINT32_MAX - 1)
#endif

// noinline attribute
Expand Down
34 changes: 30 additions & 4 deletions include/boost/url/detail/url_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <boost/core/detail/string_view.hpp>
#include <boost/url/detail/parts_base.hpp>
#include <boost/assert.hpp>
#include <cstddef>
#include <cstdint>

namespace boost {
Expand All @@ -36,17 +37,23 @@ constexpr char const* const empty_c_str_ = "";
// to by cs_.
struct BOOST_URL_DECL url_impl : parts_base
{
using size_type = std::uint32_t;

static_assert(
BOOST_URL_MAX_SIZE <= UINT32_MAX,
"BOOST_URL_MAX_SIZE exceeds 32-bit url_impl capacity");

static
constexpr
std::size_t const zero_ = 0;

// never nullptr
char const* cs_ = empty_c_str_;

std::size_t offset_[id_end + 1] = {};
std::size_t decoded_[id_end] = {};
std::size_t nseg_ = 0;
std::size_t nparam_ = 0;
size_type offset_[id_end + 1] = {};
size_type decoded_[id_end] = {};
size_type nseg_ = 0;
size_type nparam_ = 0;
unsigned char ip_addr_[16] = {};
// VFALCO don't we need a bool?
std::uint16_t port_number_ = 0;
Expand Down Expand Up @@ -95,6 +102,25 @@ struct BOOST_URL_DECL url_impl : parts_base
void apply_frag(pct_string_view) noexcept;
};

// url_impl stores 32-bit sizes; centralize narrowing with checks.
inline
url_impl::size_type
to_size_type(std::size_t n) noexcept
{
BOOST_ASSERT(n <= BOOST_URL_MAX_SIZE);
BOOST_ASSERT(n <= UINT32_MAX);
return static_cast<url_impl::size_type>(n);
}

inline
url_impl::size_type
to_size_type(std::ptrdiff_t n) noexcept
{
BOOST_ASSERT(n >= 0);
return to_size_type(
static_cast<std::size_t>(n));
}

//------------------------------------------------

// this allows a path to come from a
Expand Down
53 changes: 31 additions & 22 deletions src/detail/pattern.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,9 @@ apply(
char const* dest1 = pct_vformat(
user_chars, pctx, fctx);
u.impl_.decoded_[parts::id_user] =
pct_string_view(dest, dest1 - dest)
->decoded_size();
detail::to_size_type(
pct_string_view(dest, dest1 - dest)
->decoded_size());
if (has_pass)
{
char* destp = u.set_password_impl(
Expand All @@ -177,8 +178,9 @@ apply(
dest1 = pct_vformat(
password_chars, pctx, fctx);
u.impl_.decoded_[parts::id_pass] =
pct_string_view({destp, dest1})
->decoded_size() + 1;
detail::to_size_type(
pct_string_view({destp, dest1})
->decoded_size() + 1);
}
}
auto dest = u.set_host_impl(
Expand All @@ -193,8 +195,9 @@ apply(
pct_vformat(lhost_chars, pctx, fctx);
*dest1++ = ']';
u.impl_.decoded_[parts::id_host] =
pct_string_view(dest - 1, dest1 - dest)
->decoded_size();
detail::to_size_type(
pct_string_view(dest - 1, dest1 - dest)
->decoded_size());
}
else
{
Expand All @@ -203,8 +206,9 @@ apply(
char const* dest1 =
pct_vformat(host_chars, pctx, fctx);
u.impl_.decoded_[parts::id_host] =
pct_string_view(dest, dest1 - dest)
->decoded_size();
detail::to_size_type(
pct_string_view(dest, dest1 - dest)
->decoded_size());
}
auto uh = u.encoded_host();
auto h = grammar::parse(uh, host_rule).value();
Expand All @@ -221,8 +225,9 @@ apply(
char const* dest1 = pct_vformat(
grammar::digit_chars, pctx, fctx);
u.impl_.decoded_[parts::id_port] =
pct_string_view(dest, dest1 - dest)
->decoded_size() + 1;
detail::to_size_type(
pct_string_view(dest, dest1 - dest)
->decoded_size() + 1);
core::string_view up = {dest - 1, dest1};
auto p = grammar::parse(up, detail::port_part_rule).value();
if (p.has_port)
Expand All @@ -240,12 +245,14 @@ apply(
path_chars, pctx, fctx);
pct_string_view npath(dest, dest1 - dest);
u.impl_.decoded_[parts::id_path] +=
npath.decoded_size();
detail::to_size_type(
npath.decoded_size());
if (!npath.empty())
{
u.impl_.nseg_ = std::count(
npath.begin() + 1,
npath.end(), '/') + 1;
u.impl_.nseg_ = detail::to_size_type(
std::count(
npath.begin() + 1,
npath.end(), '/') + 1);
}
// handle edge cases
// 1) path is first component and the
Expand Down Expand Up @@ -309,12 +316,14 @@ apply(
query_chars, pctx, fctx);
pct_string_view nquery(dest, dest1 - dest);
u.impl_.decoded_[parts::id_query] +=
nquery.decoded_size() + 1;
detail::to_size_type(
nquery.decoded_size() + 1);
if (!nquery.empty())
{
u.impl_.nparam_ = std::count(
nquery.begin(),
nquery.end(), '&') + 1;
u.impl_.nparam_ = detail::to_size_type(
std::count(
nquery.begin(),
nquery.end(), '&') + 1);
}
}
if (has_frag)
Expand All @@ -328,9 +337,10 @@ apply(
auto dest1 = pct_vformat(
fragment_chars, pctx, fctx);
u.impl_.decoded_[parts::id_frag] +=
make_pct_string_view(
core::string_view(dest, dest1 - dest))
->decoded_size() + 1;
detail::to_size_type(
make_pct_string_view(
core::string_view(dest, dest1 - dest))
->decoded_size() + 1);
}
}

Expand Down Expand Up @@ -944,4 +954,3 @@ parse_pattern(
} // detail
} // urls
} // boost

48 changes: 34 additions & 14 deletions src/detail/url_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,15 @@ apply_userinfo(
// userinfo
set_size(id_user, user.size());
decoded_[id_user] =
user.decoded_size();
detail::to_size_type(
user.decoded_size());
if(pass)
{
set_size(id_pass,
pass->size() + 2);
decoded_[id_pass] =
pass->decoded_size();
detail::to_size_type(
pass->decoded_size());
}
else
{
Expand All @@ -82,7 +84,8 @@ apply_host(
host_type_ = ht;
set_size(id_host, s.size());
decoded_[id_host] =
s.decoded_size();
detail::to_size_type(
s.decoded_size());
std::memcpy(
ip_addr_,
addr,
Expand Down Expand Up @@ -137,8 +140,11 @@ apply_path(
std::size_t nseg) noexcept
{
set_size(id_path, s.size());
decoded_[id_path] = s.decoded_size();
nseg_ = detail::path_segments(s, nseg);
decoded_[id_path] =
detail::to_size_type(
s.decoded_size());
nseg_ = detail::to_size_type(
detail::path_segments(s, nseg));
}

void
Expand All @@ -147,9 +153,11 @@ apply_query(
pct_string_view s,
std::size_t n) noexcept
{
nparam_ = n;
nparam_ = detail::to_size_type(n);
set_size(id_query, 1 + s.size());
decoded_[id_query] = s.decoded_size();
decoded_[id_query] =
detail::to_size_type(
s.decoded_size());
}

void
Expand All @@ -158,7 +166,9 @@ apply_frag(
pct_string_view s) noexcept
{
set_size(id_frag, s.size() + 1);
decoded_[id_frag] = s.decoded_size();
decoded_[id_frag] =
detail::to_size_type(
s.decoded_size());
}

// return length of [first, last)
Expand Down Expand Up @@ -255,10 +265,19 @@ set_size(
int id,
std::size_t n) noexcept
{
auto d = n - len(id);
auto const cur = len(id);
if(n >= cur)
{
auto const d = n - cur;
for(auto i = id + 1;
i <= id_end; ++i)
offset_[i] += detail::to_size_type(d);
return;
}
auto const d = cur - n;
for(auto i = id + 1;
i <= id_end; ++i)
offset_[i] += d;
offset_[i] -= detail::to_size_type(d);
}

// trim id to size n,
Expand All @@ -271,7 +290,8 @@ split(
{
BOOST_ASSERT(id < id_end - 1);
//BOOST_ASSERT(n <= len(id));
offset_[id + 1] = offset(id) + n;
offset_[id + 1] = detail::to_size_type(
offset(id) + n);
}

// add n to [first, last]
Expand All @@ -284,7 +304,7 @@ adjust_right(
{
for(int i = first;
i <= last; ++i)
offset_[i] += n;
offset_[i] += detail::to_size_type(n);
}

// remove n from [first, last]
Expand All @@ -297,7 +317,7 @@ adjust_left(
{
for(int i = first;
i <= last; ++i)
offset_[i] -= n;
offset_[i] -= detail::to_size_type(n);
}

// set [first, last) offset
Expand All @@ -310,7 +330,7 @@ collapse(
{
for(int i = first + 1;
i < last; ++i)
offset_[i] = n;
offset_[i] = detail::to_size_type(n);
}


Expand Down
Loading
Loading