Index | Thread | Search

From:
Stuart Henderson <stu@spacehopper.org>
Subject:
Re: devel/boost: backport a regression fix to 1.91.0
To:
Sergii Rudchenko <sergii@rudchenko.nl>, <ports@openbsd.org>
Cc:
<marc.espie.openbsd@gmail.com>, Brad Smith <brad@comstyle.com>
Date:
Mon, 14 Sep 2026 09:44:37 +0100

Download raw body.

Thread
please use "make update-patches" to generate the patch files; from what you 
have now, "make clean; make patch; rm 
patches/patch-libs_url_base_edit_params; make update-patches".

-- 
  Sent from a phone, apologies for poor formatting.

On 13 September 2026 20:34:36 Sergii Rudchenko <sergii@rudchenko.nl> wrote:

> The current version of the Boost C++ library in OpenBSD ports (1.91.0)
> has an
> annoying regression in Boost.URL: https://github.com/boostorg/url/issues/989
>
> The issue is fixed upstream and released in in 1.92.0:
> https://github.com/boostorg/url/commit/41b467a389a68321608138a432b15024b6c11918
>
> After talking to Marc Espie at EuroBSDCon I understood that that
> updating boost
> to 1.92.0 is at this point in the release cycle is risky and will most
> likely
> be postponed until 8.0 is out. He suggested to try backporting the fix
> for the
> time being.
>
> Below is the patch taken as-is from the upstream and it luckily applies
> cleanly
> on top of 1.91.0. I have verified the fix on the resulting build from
> the port.
>
> Can we please apply this stopgap measure until we move to 1.92.0?
>
> Index: devel/boost/Makefile
> ===================================================================
> RCS file: /cvs/ports/devel/boost/Makefile,v
> diff -u -p -u -r1.163 Makefile
> --- devel/boost/Makefile    18 May 2026 05:48:17 -0000    1.163
> +++ devel/boost/Makefile    13 Sep 2026 18:07:29 -0000
> @@ -6,6 +6,7 @@ COMMENT-main=    free peer-reviewed portabl
>  COMMENT-md=    machine-dependent libraries for boost
>
>  VERSION=    1.91.0
> +REVISION=    0
>  DISTNAME=    boost_${VERSION:S/./_/g}
>  PKGNAME=    boost-${VERSION}
>  EPOCH=        0
> Index: devel/boost/patches/patch-libs_url_base_edit_params
> ===================================================================
> RCS file: devel/boost/patches/patch-libs_url_base_edit_params
> diff -N devel/boost/patches/patch-libs_url_base_edit_params
> --- /dev/null    1 Jan 1970 00:00:00 -0000
> +++ devel/boost/patches/patch-libs_url_base_edit_params    13 Sep 2026
> 18:07:29 -0000
> @@ -0,0 +1,140 @@
> +Backport the fix for the URL corruption bug on url.params().append() in
> Boost 1.91.0
> +
> +Fixed upstream in 1.92.0: 41b467a389a68321608138a432b15024b6c11918
> +Index: boost/include/boost/url/impl/url_base.hpp
> +--- boost/url/impl/url_base.hpp.orig
> ++++ boost/url/impl/url_base.hpp
> +@@ -3159,7 +3159,12 @@ edit_params(
> +     BOOST_ASSERT(pos1 <= impl_.offset(id_frag));
> +
> +     // calc decoded size of old range,
> +-    // minus one if '?' or '&' prefixed
> ++    // minus one for the leading '?' which is
> ++    // not counted in decoded_[id_query].
> ++    // dn0 may be -1 here when the old range is
> ++    // empty and the query was non-empty; the
> ++    // matching subtraction on dn below cancels
> ++    // that out when the delta is taken.
> +     auto dn0 =
> +         static_cast<std::ptrdiff_t>(
> +             detail::decode_bytes_unsafe(
> +@@ -3168,8 +3173,6 @@ edit_params(
> +                     pos1 - pos0)));
> +     if(impl_.len(id_query) > 0)
> +         dn0 -= 1;
> +-    if(dn0 < 0)
> +-        dn0 = 0;
> +
> + //------------------------------------------------
> + //
> +@@ -3267,16 +3270,13 @@ edit_params(
> +         }
> +     }
> +
> +-    // calc decoded size of new range,
> +-    // minus one if '?' or '&' prefixed
> ++    // calc decoded size of new range; see dn0.
> +     auto dn =
> +         static_cast<std::ptrdiff_t>(
> +             detail::decode_bytes_unsafe(
> +                 core::string_view(dest0, dest - dest0)));
> +     if(impl_.len(id_query) > 0)
> +         dn -= 1;
> +-    if(dn < 0)
> +-        dn = 0;
> +
> +     if(dn >= dn0)
> +         impl_.decoded_[id_query] +=
> +Index: libs/url/test/unit/params_encoded_ref.cpp
> +--- libs/url/test/unit/params_encoded_ref.cpp.orig
> ++++ libs/url/test/unit/params_encoded_ref.cpp
> +@@ -121,6 +121,11 @@ struct params_encoded_ref_test
> +         params_encoded_ref ps(u.encoded_params());
> +         f(ps);
> +         BOOST_TEST_EQ(u.encoded_query(), s1);
> ++        BOOST_TEST_EQ(
> ++            u.encoded_query().decoded_size(),
> ++            pct_string_view(s1).decoded_size());
> ++        BOOST_TEST_NO_THROW(u.encoded_target());
> ++        BOOST_TEST_NO_THROW(u.encoded_resource());
> +         if(! BOOST_TEST_EQ(
> +                 ps.size(), init.size()))
> +             return;
> +Index: libs/url/test/unit/params_ref.cpp
> +--- libs/url/test/unit/params_ref.cpp.orig
> ++++ libs/url/test/unit/params_ref.cpp
> +@@ -142,6 +142,11 @@ struct params_ref_test
> +         params_ref ps(u.params());
> +         f(ps);
> +         BOOST_TEST_EQ(u.encoded_query(), s1);
> ++        BOOST_TEST_EQ(
> ++            u.encoded_query().decoded_size(),
> ++            pct_string_view(s1).decoded_size());
> ++        BOOST_TEST_NO_THROW(u.encoded_target());
> ++        BOOST_TEST_NO_THROW(u.encoded_resource());
> +         if(! BOOST_TEST_EQ(
> +                 ps.size(), init.size()))
> +             return;
> +@@ -814,6 +819,62 @@ struct params_ref_test
> +             check(f, "?k0&k1=&k2=key", "k0&k1=" BIGSTR "&k2=key",
> +                 { {"k0",no_value}, {"k1",BIGSTR}, {"k2","key"} });
> +         }
> ++
> ++        // issue #989: encoded_target() asserts after
> ++        // successive params().set() on a fresh url.
> ++        // Regression for broken decoded_[id_query]
> ++        // bookkeeping in url_base::edit_params.
> ++        {
> ++            url u;
> ++            u.params().set("a", "b");
> ++            BOOST_TEST_EQ(u.encoded_query(), "a=b");
> ++            BOOST_TEST_EQ(u.encoded_query().decoded_size(), 3u);
> ++            BOOST_TEST_EQ(u.encoded_target(), "?a=b");
> ++
> ++            u.params().set("c", "d");
> ++            BOOST_TEST_EQ(u.encoded_query(), "a=b&c=d");
> ++            BOOST_TEST_EQ(u.encoded_query().decoded_size(), 7u);
> ++            BOOST_TEST_EQ(u.encoded_target(), "?a=b&c=d");
> ++        }
> ++
> ++        // Related: erase first param must leave a
> ++        // consistent decoded_[id_query].
> ++        {
> ++            url u("?a=b&c=d");
> ++            BOOST_TEST_EQ(u.encoded_query().decoded_size(), 7u);
> ++            u.params().erase(u.params().begin());
> ++            BOOST_TEST_EQ(u.encoded_query(), "c=d");
> ++            BOOST_TEST_EQ(u.encoded_query().decoded_size(), 3u);
> ++            BOOST_TEST_EQ(u.encoded_target(), "?c=d");
> ++        }
> ++
> ++        // Related: erase last param must leave a
> ++        // consistent decoded_[id_query].
> ++        {
> ++            url u("?a=b&c=d");
> ++            u.params().erase(std::next(u.params().begin()));
> ++            BOOST_TEST_EQ(u.encoded_query(), "a=b");
> ++            BOOST_TEST_EQ(u.encoded_query().decoded_size(), 3u);
> ++            BOOST_TEST_EQ(u.encoded_target(), "?a=b");
> ++        }
> ++
> ++        // Related: insert at front of non-empty query.
> ++        {
> ++            url u("?x=y");
> ++            u.params().insert(u.params().begin(), {"a", "b"});
> ++            BOOST_TEST_EQ(u.encoded_query(), "a=b&x=y");
> ++            BOOST_TEST_EQ(u.encoded_query().decoded_size(), 7u);
> ++            BOOST_TEST_EQ(u.encoded_target(), "?a=b&x=y");
> ++        }
> ++
> ++        // Related: append to non-empty query.
> ++        {
> ++            url u("?x=y");
> ++            u.params().append({"a", "b"});
> ++            BOOST_TEST_EQ(u.encoded_query(), "x=y&a=b");
> ++            BOOST_TEST_EQ(u.encoded_query().decoded_size(), 7u);
> ++            BOOST_TEST_EQ(u.encoded_target(), "?x=y&a=b");
> ++        }
> +     }
> +
> +     static