Conversation
Replace the manually maintained SOURCES list with glob-tree-ex to auto-discover test .cpp files, matching the CMakeLists.txt approach. Files needing special flags (doc_grammar.cpp, doc_3_urls.cpp, example/) are excluded from the glob and handled by explicit run statements.
|
An automated preview of the documentation is available at https://982.url.prtest2.cppalliance.org/index.html If more commits are pushed to the pull request, the docs will rebuild at the same URL. 2026-03-02 22:20:22 UTC |
|
GCOVR code coverage report https://982.url.prtest2.cppalliance.org/gcovr/index.html Build time: 2026-03-02 22:32:53 UTC |
The coveralls section fails on Ubuntu 24.04 because pip3 install requires a virtual environment (PEP 668), and the resulting cpp-coveralls command-not-found exit code was failing the build.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #982 +/- ##
===========================================
- Coverage 99.15% 99.11% -0.04%
===========================================
Files 155 155
Lines 10045 10085 +40
===========================================
+ Hits 9960 9996 +36
- Misses 85 89 +4
... and 15 files with indirect coverage changes Continue to review full report in Codecov by Sentry.
🚀 New features to boost your workflow:
|
BOOST_ASSERTpreconditions on internal APIs, non-owning view types, and raw pointer parsing routines).Summary
v1 (Feb 2, 2026)
v2 (Feb 17, 2026)
All Fixes (18 commits)
f0a80adaf227d461c8962bcd76d8fc51e83f4f723e217c954f1d59ab1c6e27dce4755d1f179140c22bcd7bcecccd304da80148a7a70b0e49c935b72422153cFinding Details
Per-finding triage with a verdict and a rationale for each individual finding.
CRITICAL (4 findings)
C1. Buffer overflow in format_args.cpp string formatting
src/detail/format_args.cpp:196char*fromctx.out()assuming sufficient capacity.C2. Buffer overflow in format_args.cpp integer formatting
src/detail/format_args.cpp:510C3. Buffer overflow in format_args.cpp unsigned integer formatting
src/detail/format_args.cpp:613C4. Out-of-bounds read in url_base.cpp loop condition
include/boost/url/impl/url_base.hpp:248,2092,2616*itbefore checkingit != end. Three instances.af227d4, "fix: url_base loop condition order"): Reordered conditions towhile (it != end && *it != '/').HIGH (185 v1 + 9 v2 = 194 findings)
Confirmed bugs fixed (12 fixes)
Format center-alignment padding heap overflow
src/detail/format_args.cpp:190lpad = w / 2used total width instead of padding amount, solpad + rpad > pad, causing writes past the pre-measured buffer.217c954, "fix: format center-alignment padding"): Changed tolpad = pad / 2.decode_view::ends_with infinite loop on empty string
src/decode_view.cpp:106-124sis empty,s.size()is 0, decrementing iterators andn - 1wraps around causing infinite loop/UB.f1d59ab, "fix: decode_view::ends_with with empty string"): Addedif(s.empty()) return true;early return.Stale n.path after colon-encoding in pattern.cpp
src/detail/pattern.cpp:268-291diff),n.pathwas not updated. The subsequent//prefix check used the stale value formemmove.1c6e27d, "fix: stale pattern n.path after colon-encoding"): Addedn.path += diff;after the colon-encoding block.ci_is_less OOB read on mismatched-length strings
src/grammar/ci_string.cpp:58-74s0.size()as bound but read from both strings. Whens0.size() > s1.size(), OOB read on s1. Also returned false (equal) when s0 is a proper prefix of s1. Unlikeci_is_equal, the publicci_is_less()does NOT check sizes before calling detail.ce4755d, "fix: ci_is_less OOB read"): Usemin(s0.size(), s1.size())as loop bound, fall through to size comparison.recycled_ptr copy assignment self-assignment UAF
include/boost/url/grammar/impl/recycled.hpp:1851f17914, "fix: recycled_ptr copy self-assignment"): Addedif(this == &other) return *this;guard.Signed integer overflow: LLONG_MIN negation (3 findings)
src/detail/format_args.cpp:367,src/detail/format_args.cpp:453,src/detail/format_args.cpp:51961c8962, "fix: LLONG_MIN negation UB in format"): Replaced with unsigned arithmetic throughout.ci_less::operator() incorrect return type
include/boost/url/grammar/ci_string.hpp:333std::size_tinstead ofbool.bcd76d8, "fix: ci_less::operator() return type"): Changed return type tobool.segments_base front()/back() incorrect noexcept
include/boost/url/segments_base.hpp:250front()andback()markednoexceptbut can throw.fc51e83, "fix: incorrect noexcept in segments_base::front() and back()"): Removed incorrectnoexcept.recycled_ptr::get() null dereference
include/boost/url/grammar/recycled.hpp:452get()dereferencedp_without null check.f4f723e, "fix: recycled_ptr::get() nullptr when empty"): Added null check to return nullptr when empty.Pointer arithmetic UB in encode() for small buffers
include/boost/url/impl/encode.hppf0a80ad, "fix: encode() UB pointer arithmetic for small buffers"): Avoid UB pointer arithmetic.False positives (v2)
Data race on recycled_ptr refcount
include/boost/url/grammar/recycled.hpp:97-102refsISstd::atomic<std::size_t>when threads enabled (BOOST_URL_DISABLE_THREADSguard). Same issue as v1 Theme 5.decode() output buffer insufficient
include/boost/url/detail/decode.hppdecode_unsafechecksdest == endat line 90 and returns early. Truncation is documented behavior.Theme: BOOST_ASSERT as sole bounds check (29 findings, v1)
TRIAGE: BY DESIGN. Internal
_unsafefunctions and detail routines. The public API validates all inputs before calling them. The_unsafesuffix explicitly signals the precondition contract. Adding redundant runtime checks would duplicate validation already performed at the public API boundary. Standard Boost/STL design pattern (cf.std::vector::operator[]vsat()).detail/encode.hpp:58%+ two hex digitsdetail/encode.hpp:77detail/encode.hpp:90detail/encode.hpp:121detail/segments_range.hpp:82detail/url_impl.hpp:110detail/normalize.cpp:318detail/normalize.cpp:362detail/over_allocator.hpp:95detail/params_iter_impl.cpp:89detail/pattern.cpp:75[/]pairingdetail/pattern.cpp:78host.substr(1, host.size()-2)detail/pattern.cpp:188detail/pattern.cpp:191detail/pct_format.cpp:54detail/pct_format.cpp:107detail/pct_format.cpp:152detail/pct_format.cpp:205detail/segments_iter_impl.cpp:113detail/segments_iter_impl.cpp:156detail/url_impl.cpp:205impl/decode_view.hpp:73impl/decode_view.hpp:84impl/encode.hpp:95impl/encode.hpp:194detail/format_args.cpp:134detail/format_args.cpp:346rfc/detail/query_part_rule.hpp:54detail/vformat.cpp:25Theme: Non-owning view/pointer lifetime safety (27 findings, v1)
TRIAGE: BY DESIGN. Non-owning views are fundamental to C++ (cf.
std::string_view,std::span). Callers responsible for ensuring referenced data outlives the view. Documented and inherent to the view-based design.authority_view.hpp:242param.hpp:427params_encoded_base.hpp:71params_encoded_view.hpp:166params_ref.hpp:91params_view.hpp:186params_view.hpp:253segments_encoded_base.hpp:39segments_encoded_ref.hpp:84segments_encoded_view.hpp:161segments_encoded_view.hpp:162segments_ref.hpp:80segments_view.hpp:160url_view.hpp:197url_view.cpp:48grammar/charset.hpp:207grammar/range_rule.hpp:235grammar/string_view_base.hpp:60detail/optional_string.hpp:38detail/optional_string.hpp:73detail/format_args.hpp:103detail/impl/format_args.hpp:70detail/impl/format_args.hpp:80params_encoded_ref.cpp:34segments_ref.cpp:32segments_encoded_view.cpp:29params_encoded_ref.hpp:82Theme: Raw pointer buffer APIs (45 findings, v1)
TRIAGE: BY DESIGN. Internal
_unsafefunctions accept raw pointers with documented preconditions. The public API handles buffer management.detail/any_params_iter.hpp:79detail/any_params_iter.hpp:80detail/any_segments_iter.hpp:70detail/decode.hpp:26detail/decode.hpp:34detail/decode.hpp:42detail/format_args.hpp:239detail/normalize.hpp:158detail/normalize.hpp:159detail/any_params_iter.cpp:115detail/any_params_iter.cpp:117detail/any_params_iter.cpp:210detail/any_params_iter.cpp:265detail/any_params_iter.cpp:329detail/any_params_iter.cpp:374detail/any_segments_iter.cpp:66detail/any_segments_iter.cpp:153detail/decode.cpp:25detail/move_chars.hpp:78detail/move_chars.hpp:81detail/normalize.cpp:33detail/normalize.cpp:40detail/url_impl.cpp:89url_view_base.cpp:76url_base.hpp:65url_base.hpp:82impl/decode.hpp:35impl/decode.hpp:43static_url.cpp:23static_url.cpp:28url_base.cpp:115url_base.cpp:138url_base.cpp:239af227d4)url.cpp:76params_view.cpp:41params_view.cpp:52ipv6_address.hpp:248ipv6_address.hpp:372ipv4_address.cpp:32ipv4_address.cpp:33ipv6_address.cpp:26authority_view.cpp:263rfc/detail/host_rule.cpp:55rfc/detail/host_rule.cpp:98url_view_base.cpp:91Theme: Unchecked percent-encoding assumptions (13 findings, v1)
TRIAGE: BY DESIGN. Internal decode/encode routines operate on data already validated by the public parsing API (RFC 3986 grammar).
pct_string_viewvalidates on construction.decode_view.cpp:27decode_view.cpp:32decode_view.cpp:53decode_view.cpp:69decode_view.hpp:473decode_view.hpp:496impl/decode_view.hpp:84pct_string_view.cpp:27pct_string_view.hpp:435pct_string_view.hpp:436rfc/impl/pct_encoded_rule.hpp:37detail/params_iter_impl.cpp:220detail/normalize.cpp:266Theme: Race conditions in recycled<T> (6 findings, v1)
TRIAGE: FALSE POSITIVE. The report missed
#if !defined(BOOST_URL_DISABLE_THREADS)guards. When threads are enabled,refsisstd::atomic<std::size_t>(recycled.hpp:98-99), and the freelist is protected bystd::mutex m_(recycled.hpp:119).grammar/impl/recycled.hpp:33grammar/impl/recycled.hpp:66grammar/impl/recycled.hpp:78grammar/impl/recycled.hpp:149grammar/impl/recycled.hpp:191grammar/recycled.hpp:78Theme: Incorrect noexcept specifications (5 findings, v1)
TRIAGE: FALSE POSITIVE. These functions take
pct_string_view, which validates percent-encoding on construction. By the time these functions are called, data is already validated.params_encoded_base.hpp:322params_encoded_base.hpp:414params_encoded_base.hpp:467params_encoded_base.hpp:514params_encoded_base.hpp:562Miscellaneous (42 findings, v1)
grammar/ci_string.hpp:333bcd76d8, "fix: ci_less::operator() return type")grammar/detail/charset.hpp:135_mm_loadu_si128is unaligned loadgrammar/detail/charset.hpp:163grammar/impl/not_empty_rule.hpp:29if(!rv)grammar/impl/range_rule.hpp:163grammar/recycled.hpp:440bin_set in ALL constructorsgrammar/recycled.hpp:452f4f723e, "fix: recycled_ptr::get() nullptr when empty")grammar/recycled.hpp:482not this->empty()grammar/string_token.hpp:254s_.resize(n)before&s_[0], n==0 unusedgrammar/string_token.hpp:306grammar/string_token.hpp:369grammar/string_token.hpp:436grammar/literal_rule.hpp:46grammar/lut_chars.hpp:90grammar/lut_chars.hpp:94grammar/ci_string.cpp:35ci_is_equalchecks sizes before detail callgrammar/ci_string.cpp:65FPFIXED (ce4755d, "fix: ci_is_less OOB read")ci_is_lessdoes NOT check sizes (corrected by v2-HIGH-8/9)grammar/literal_rule.cpp:32grammar/impl/tuple_rule.hpp:74grammar/token_rule.hpp:36empty_valueretrievalgrammar/tuple_rule.hpp:61if(!rv)impl/params_base.hpp:50impl/params_encoded_ref.hpp:31impl/segments_encoded_ref.hpp:143!this->empty()impl/segments_ref.hpp:144params_encoded_ref.cpp:86params_ref.cpp:70segments_base.hpp:250fc51e83, "fix: incorrect noexcept in segments_base::front() and back()")detail/format_args.hpp:103detail/impl/format_args.hpp:111detail/over_allocator.hpp:119authority_view.cpp:58rfc/absolute_uri_rule.cpp:77rfc/detail/hier_part_rule.cpp:55rfc/detail/ip_literal_rule.hpp:48it == endfirstrfc/detail/port_rule.cpp:47rfc/detail/port_rule.cpp:53it != endchecked firstrfc/origin_form_rule.cpp:26if(it == end || ...)rfc/query_rule.cpp:52scheme.cpp:29detail/format_args.cpp:39params_encoded_ref.hpp:230u_always valid (private ctor, friend of url_base)Signed integer overflow (3 findings, v1)
TRIAGE: FIXED (
61c8962). Negation of LLONG_MIN is undefined behavior. Three instances, all fixed.detail/format_args.cpp:367detail/format_args.cpp:453detail/format_args.cpp:519Scanner duplicates (15 findings, v1)
The v1 report merged two scanner runs (gpt-5.2 and claude-sonnet-4-5). These 15 findings are exact duplicates (same file and line) reported by both scanners. Each inherits the verdict of the original.
detail/encode.hpp:58grammar/impl/range_rule.hpp:163grammar/impl/recycled.hpp:78detail/decode.cpp:25detail/pct_format.cpp:54detail/pct_format.cpp:107detail/pct_format.cpp:152detail/pct_format.cpp:205detail/url_impl.cpp:89grammar/ci_string.cpp:35grammar/ci_string.cpp:65ipv6_address.cpp:26rfc/detail/host_rule.cpp:55segments_ref.hpp:80url_view.cpp:48MEDIUM (491 v1 + 10 v2 = 501 findings)
v2 MEDIUM (10 findings in report, 9 unique after deduplication)
MED-1. Signed char right-shift in encode_one
include/boost/url/detail/impl/format_args.hpp:2157bceccc, "fix: encode_one signed char right-shift"): Castctounsigned charbefore shift.MED-2. recycled_ptr::get() null dereference
include/boost/url/grammar/recycled.hpp:452f4f723e, "fix: recycled_ptr::get() nullptr when empty").MED-3. encode() noexcept but calls throwing prepare()
include/boost/url/impl/encode.hpp:281token.prepare(n)can throwstd::bad_alloc, butencode()was markednoexcept, causingstd::terminate.d304da8, "fix: encode() noexcept on throwing template"): Removednoexceptfrom both declaration and definition.MED-4. Unbounded remove_suffix on decode_view
src/decode_view.cpp:72BOOST_ASSERT(n <= dn_). Same precondition pattern asstd::string_view::remove_suffix.MED-5. LLONG_MIN negation UB in format
src/detail/format_args.cpp61c8962, "fix: LLONG_MIN negation UB in format").MED-6. OOB read in url_base loop condition
include/boost/url/impl/url_base.hppaf227d4, "fix: url_base loop condition order").MED-7. url::operator=(url&&) self-move-assignment UAF
include/boost/url/impl/url.hpp:63s_then assigned the dangling pointer back.0c22bcd, "fix: url move self-assignment"): Addedif(this == &u) return *this;guard.MED-8. recycled_ptr copy assignment self-assignment UAF
include/boost/url/grammar/impl/recycled.hpp:1871f17914, "fix: recycled_ptr copy self-assignment").MED-9. Unbounded remove_prefix on decode_view
src/decode_view.cpp:55BOOST_ASSERT(n <= dn_). Same as MED-4.MED-10. params_iter_impl decrement multi-equals
src/detail/params_iter_impl.cppa87998a, "fix(params): correct decoded_size in params_iter_impl::decrement() for values containing '='").v1 MEDIUM (491 findings)
No confirmed bugs among the 491 v1 MEDIUM items. All findings fall into the same patterns as the HIGH findings: by-design precondition-based APIs, non-owning view types, internal raw pointer operations, and false positives about thread safety, noexcept, and integer overflow.
LOW (358 v1 + 6 v2 = 364 findings)
v2 LOW (6 findings)
LOW-1. ci_less::operator() return type
include/boost/url/grammar/ci_string.hpp:333bcd76d8, "fix: ci_less::operator() return type").LOW-2. Pointer arithmetic UB in encode()
include/boost/url/impl/encode.hppf0a80ad, "fix: encode() UB pointer arithmetic for small buffers").LOW-3/4. front()/back() noexcept on segments
include/boost/url/segments_base.hpp:250fc51e83, "fix: incorrect noexcept in segments_base::front() and back()").LOW-5. port_rule has_number wrong for port zero at end of input
include/boost/url/rfc/detail/impl/port_rule.hpp:71it == end),has_numberwas incorrectly false because it checkedit != endinstead ofit != start.0148a7a, "fix: port_rule has_number for port zero at end of input"): Changed tot.has_number = it != start;.LOW-6. Static destruction order fiasco in recycled bin
include/boost/url/grammar/impl/recycled.hpp:66v1 LOW (358 findings)
Verdict totals: FIXED 2, FALSE POSITIVE 186, BY DESIGN 170
Two confirmed bugs, both the same underlying issue:
decode()withStringTokenis markednoexceptbuttoken.prepare(n)allocates and can throwstd::bad_alloc, causingstd::terminate. Fixed by removingnoexceptfromdecode()(commitc935b72, "fix: decode() noexcept on throwing template").INFORMATIONAL (169 v1 + 2 v2 = 171 findings)
v2 INFORMATIONAL (2 findings)
INFO-1. ci_equal pass-by-value
include/boost/url/grammar/ci_string.hpp:298-299operator()tookString0andString1by value, causing unnecessary copies for non-trivial string types.70b0e49, "fix: ci_equal arguments by const reference"): Changed toString0 const&andString1 const&.INFO-2. param self-move-assignment
v1 INFORMATIONAL (169 findings)
Confirmed bugs: 3 copy-paste doc bugs in error_types.hpp (FIXED
422153c), 1 missing BOOST_URL_DECL on format_spec_rule_t::parse, 1 duplicate header include. No critical security issues among the INFORMATIONAL findings.