Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package nix for openSUSE:Factory checked in at 2026-08-14 22:07:04 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/nix (Old) and /work/SRC/openSUSE:Factory/.nix.new.1258 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "nix" Fri Aug 14 22:07:04 2026 rev:22 rq:1371043 version:2.35.2 Changes: -------- --- /work/SRC/openSUSE:Factory/nix/nix.changes 2026-07-18 22:26:09.404443084 +0200 +++ /work/SRC/openSUSE:Factory/.nix.new.1258/nix.changes 2026-08-14 22:07:27.519048271 +0200 @@ -1,0 +2,19 @@ +Wed Aug 12 22:36:49 UTC 2026 - Marcus Rueckert <[email protected]> + +- Update to version 2.35.2: + - ae5195225 Revert "Drop old hacks for unachhored vtables and + exception handling" + - 40c627396 libstore: Actually check that hash part is followed + by a dash in StorePath + - b15a3d003 libutil-tests: Disable + sourceToSink.forcedUnwindUcaughtExceptions under ASan + - f8d28f3b8 Add boost.context patch for + std::uncaught_exceptions() misreporting 0 while abandoning the + coroutine + - 95cfc5da5 libutil-tests: Add test for sourceToSink + boost.context bug + - fba3f6e49 libstore: Fix lost waiting for slot goal wakeups + - fbd4c3f7e daemon: unlink worker's temproots file on exit + - 822e07028 libutil: Use O_PATH when opening parent dirFds + +------------------------------------------------------------------- Old: ---- nix-2.35.1.tar.gz New: ---- nix-2.35.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ nix.spec ++++++ --- /var/tmp/diff_new_pack.4kEKTE/_old 2026-08-14 22:07:28.553085919 +0200 +++ /var/tmp/diff_new_pack.4kEKTE/_new 2026-08-14 22:07:28.554085955 +0200 @@ -26,7 +26,7 @@ %bcond_with docs Name: nix -Version: 2.35.1 +Version: 2.35.2 Release: 0 Summary: The purely functional package manager License: LGPL-2.1-only ++++++ nix-2.35.1.tar.gz -> nix-2.35.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nix-2.35.1/.version new/nix-2.35.2/.version --- old/nix-2.35.1/.version 2026-07-14 01:07:05.000000000 +0200 +++ new/nix-2.35.2/.version 2026-08-12 23:09:18.000000000 +0200 @@ -1 +1 @@ -2.35.1 +2.35.2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nix-2.35.1/packaging/components.nix new/nix-2.35.2/packaging/components.nix --- old/nix-2.35.1/packaging/components.nix 2026-07-14 01:07:05.000000000 +0200 +++ new/nix-2.35.2/packaging/components.nix 2026-08-12 23:09:18.000000000 +0200 @@ -139,6 +139,8 @@ !(stdenv.hostPlatform.isWindows || stdenv.hostPlatform.isCygwin) # build failure && !stdenv.hostPlatform.isStatic + # LTO breaks exception handling on x86-64-darwin. + && stdenv.system != "x86_64-darwin" ) '' case "$mesonBuildType" in diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nix-2.35.1/packaging/dependencies.nix new/nix-2.35.2/packaging/dependencies.nix --- old/nix-2.35.1/packaging/dependencies.nix 2026-07-14 01:07:05.000000000 +0200 +++ new/nix-2.35.2/packaging/dependencies.nix 2026-08-12 23:09:18.000000000 +0200 @@ -98,6 +98,9 @@ "--with-iostreams" "--with-url" ]; + patches = [ + ./patches/0001-Fix-uncaught_exceptions-not-accounting-for-forced_un.patch + ]; enableIcu = false; }).overrideAttrs (old: { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nix-2.35.1/packaging/patches/0001-Fix-uncaught_exceptions-not-accounting-for-forced_un.patch new/nix-2.35.2/packaging/patches/0001-Fix-uncaught_exceptions-not-accounting-for-forced_un.patch --- old/nix-2.35.1/packaging/patches/0001-Fix-uncaught_exceptions-not-accounting-for-forced_un.patch 1970-01-01 01:00:00.000000000 +0100 +++ new/nix-2.35.2/packaging/patches/0001-Fix-uncaught_exceptions-not-accounting-for-forced_un.patch 2026-08-12 23:09:18.000000000 +0200 @@ -0,0 +1,102 @@ +From 5883212311535a0046031d74d1568ae173c1e35b Mon Sep 17 00:00:00 2001 +From: Sergei Zimmerman <[email protected]> +Date: Tue, 21 Jul 2026 21:15:51 +0000 +Subject: [PATCH] Fix uncaught_exceptions() not accounting for forced_unwind + +Unwound fibers would see std::uncaught_exceptions() == 0, while a +forced_unwind exception is in "flight". This goes against the contract +of std::uncaught_exceptions() that scope guards rely upon. Failing +to report the correct number of uncaught exceptions (especially +misreporting zero) will lead to scope guards to misbehave badly and skip +running cleanup code which branches on whether the destructor is called +during stack unwinding or not. + +This is because the "throw" would happen before the destructor is run on +the fiber stack being switched to, but the increment would be clobbered +by the destructor of manage_exception_state. + +I'm not sure what the contract of run ontop_fcontext is wrt to whether +the the caller provided function can throw or not, but in my best +understanding the forced_unwind mechanism is mostly internal and so is +throwing from ontop_fcontext in the switched-to fiber. Thus, I've kept +the catch block scoped to detail::forced_unwind. +--- + include/boost/context/fiber_fcontext.hpp | 37 +++++++++++++++++------- + test/test_fiber.cpp | 24 +++++++++++++++ + 2 files changed, 51 insertions(+), 10 deletions(-) + +diff --git a/include/boost/context/fiber_fcontext.hpp b/include/boost/context/fiber_fcontext.hpp +index 543ba6c..38476c9 100644 +--- a/boost/context/fiber_fcontext.hpp ++++ b/boost/context/fiber_fcontext.hpp +@@ -70,7 +70,9 @@ namespace context { + namespace detail { + + // manage_exception_state is a dummy struct unless we have specific support +-struct manage_exception_state {}; ++struct manage_exception_state { ++ void from_forced_unwind() noexcept {} ++}; + + } // namespace detail + } // namespace context +@@ -90,6 +92,11 @@ public: + manage_exception_state() { + exception_state_ = *__cxa_get_globals(); + } ++ // Hack to account for the forced_unwind exception thrown in fiber_unwind ++ // that's run ontop before the destructor. ++ void from_forced_unwind() noexcept { ++ exception_state_.uncaughtExceptions += 1; ++ } + ~manage_exception_state() { + *__cxa_get_globals() = exception_state_; + } +@@ -376,13 +383,18 @@ public: + BOOST_ASSERT( nullptr != fctx_); + detail::manage_exception_state exstate; + boost::ignore_unused(exstate); +- return { detail::jump_fcontext( ++ try { ++ return { detail::jump_fcontext( + #if defined(BOOST_NO_CXX14_STD_EXCHANGE) +- detail::exchange( fctx_, nullptr), ++ detail::exchange( fctx_, nullptr), + #else +- std::exchange( fctx_, nullptr), ++ std::exchange( fctx_, nullptr), + #endif +- nullptr).fctx }; ++ nullptr).fctx }; ++ } catch ( detail::forced_unwind const& ) { ++ exstate.from_forced_unwind(); ++ throw; ++ } + } + + template< typename Fn > +@@ -391,14 +403,19 @@ public: + detail::manage_exception_state exstate; + boost::ignore_unused(exstate); + auto p = std::forward< Fn >( fn); +- return { detail::ontop_fcontext( ++ try { ++ return { detail::ontop_fcontext( + #if defined(BOOST_NO_CXX14_STD_EXCHANGE) +- detail::exchange( fctx_, nullptr), ++ detail::exchange( fctx_, nullptr), + #else +- std::exchange( fctx_, nullptr), ++ std::exchange( fctx_, nullptr), + #endif +- & p, +- detail::fiber_ontop< fiber, decltype(p) >).fctx }; ++ & p, ++ detail::fiber_ontop< fiber, decltype(p) >).fctx }; ++ } catch ( detail::forced_unwind const& ) { ++ exstate.from_forced_unwind(); ++ throw; ++ } + } + + explicit operator bool() const noexcept { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nix-2.35.1/src/libstore/build/worker.cc new/nix-2.35.2/src/libstore/build/worker.cc --- old/nix-2.35.1/src/libstore/build/worker.cc 2026-07-14 01:07:05.000000000 +0200 +++ new/nix-2.35.2/src/libstore/build/worker.cc 2026-08-12 23:09:18.000000000 +0200 @@ -249,19 +249,6 @@ } children.erase(i); - auto & waiting = jobCategory == JobCategory::Substitution ? wantingToSubstitute : wantingToBuild; - - /* Wake up goals waiting for a build slot. Wake at most one waiter to avoid - starting unnecessary work (that is accompanied by coroutine frame allocation). */ - auto it = waiting.begin(); - while (it != waiting.end()) { - if (auto goal = it->lock()) { - waiting.erase(it); - wakeUp(goal); - break; - } - it = waiting.erase(it); - } } void Worker::waitForBuildSlot(GoalPtr goal) @@ -337,6 +324,22 @@ if (topGoals.empty()) break; // stuff may have been cancelled } + + auto wakeSlotWaiters = [this](WeakGoals & waiting, size_t running, size_t limit) { + auto it = waiting.begin(); + while (it != waiting.end() && running < limit) { + auto goal = it->lock(); + it = waiting.erase(it); + if (!goal) + continue; + wakeUp(goal); + ++running; + } + }; + + wakeSlotWaiters( + wantingToSubstitute, getNrSubstitutions(), std::max<std::size_t>(1, settings.maxSubstitutionJobs)); + wakeSlotWaiters(wantingToBuild, getNrLocalBuilds(), settings.maxBuildJobs); } if (topGoals.empty()) @@ -365,6 +368,7 @@ --keep-going *is* set, then they must all be finished now. */ assert(!settings.keepGoing || awake.empty()); assert(!settings.keepGoing || wantingToBuild.empty()); + assert(!settings.keepGoing || wantingToSubstitute.empty()); assert(!settings.keepGoing || children.empty()); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nix-2.35.1/src/libstore/include/nix/store/build/worker.hh new/nix-2.35.2/src/libstore/include/nix/store/build/worker.hh --- old/nix-2.35.1/src/libstore/include/nix/store/build/worker.hh 2026-07-14 01:07:05.000000000 +0200 +++ new/nix-2.35.2/src/libstore/include/nix/store/build/worker.hh 2026-08-12 23:09:18.000000000 +0200 @@ -326,8 +326,7 @@ bool respectTimeouts); /** - * Unregisters a running child process. Wakes at most a single goal that is - * awaiting on the corresponding build slot type (building or substitution). + * Unregisters a running child process. * * This overload requires `goal` to point to a fully constructed, * valid goal object, as it calls `goal->jobCategory()`. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nix-2.35.1/src/libstore/path.cc new/nix-2.35.2/src/libstore/path.cc --- old/nix-2.35.1/src/libstore/path.cc 2026-07-14 01:07:05.000000000 +0200 +++ new/nix-2.35.2/src/libstore/path.cc 2026-08-12 23:09:18.000000000 +0200 @@ -51,6 +51,8 @@ { if (baseName.size() < HashLen + 1) throw BadStorePath("'%s' is too short to be a valid store path", baseName); + if (baseName[HashLen] != '-') + throw BadStorePath("'%s' can't name a store path because the hash part is not followed by a '-'", baseName); for (auto c : hashPart()) if (c == 'e' || c == 'o' || c == 'u' || c == 't' || !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z'))) throw BadStorePath("store path '%s' contains illegal base-32 character '%s'", baseName, c); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nix-2.35.1/src/libstore-tests/path.cc new/nix-2.35.2/src/libstore-tests/path.cc --- old/nix-2.35.1/src/libstore-tests/path.cc 2026-07-14 01:07:05.000000000 +0200 +++ new/nix-2.35.2/src/libstore-tests/path.cc 2026-08-12 23:09:18.000000000 +0200 @@ -139,6 +139,15 @@ RC_ASSERT(parsed == std::regex_match(std::string{name}, nameRegex)); } +TEST_F(StorePathTest, mustBeDashAfterHashPart) +{ + std::string hashPart = "575s52sh487i0ylmbs9pvi606ljdszr0"; + for (char c : {'_', '\0'}) { + EXPECT_THROW(StorePath(hashPart + c + "name"), BadStorePath); + } + EXPECT_NO_THROW(StorePath(hashPart + "-" + "name")); +} + /* ---------------------------------------------------------------------------- * JSON * --------------------------------------------------------------------------*/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nix-2.35.1/src/libutil/meson.build new/nix-2.35.2/src/libutil/meson.build --- old/nix-2.35.1/src/libutil/meson.build 2026-07-14 01:07:05.000000000 +0200 +++ new/nix-2.35.2/src/libutil/meson.build 2026-08-12 23:09:18.000000000 +0200 @@ -44,6 +44,12 @@ description : 'Whether nix has been built with UBSan enabled', ) +configdata_pub.set( + 'NIX_ASAN_ENABLED', + ('address' in get_option('b_sanitize')).to_int(), + description : 'Whether nix has been built with ASan enabled', +) + subdir('nix-meson-build-support/libatomic') if host_machine.system() == 'windows' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nix-2.35.1/src/libutil/posix-source-accessor.cc new/nix-2.35.2/src/libutil/posix-source-accessor.cc --- old/nix-2.35.1/src/libutil/posix-source-accessor.cc 2026-07-14 01:07:05.000000000 +0200 +++ new/nix-2.35.2/src/libutil/posix-source-accessor.cc 2026-08-12 23:09:18.000000000 +0200 @@ -383,8 +383,20 @@ } try { - AutoCloseFD parentFdOwning = - openFileEnsureBeneathNoSymlinks(startFd, relPath, O_DIRECTORY | O_RDONLY | O_CLOEXEC, 0, std::move(cb)); + AutoCloseFD parentFdOwning = openFileEnsureBeneathNoSymlinks( + startFd, + relPath, +# ifdef O_PATH + /* As to not require read permissions on the directory. */ + O_PATH | +# else + /* Sadly this will require read permissison for path resolution, + but without O_PATH that's unavoidable. */ + O_RDONLY | +# endif + O_DIRECTORY | O_CLOEXEC, + 0, + std::move(cb)); return {parentFdOwning.get(), make_ref<AutoCloseFD>(std::move(parentFdOwning))}; } catch (SymlinkNotAllowed & e) { /* Need to fixup the error message to include the actual path relative to the (possibly) cached fd. */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nix-2.35.1/src/libutil-tests/serialise.cc new/nix-2.35.2/src/libutil-tests/serialise.cc --- old/nix-2.35.1/src/libutil-tests/serialise.cc 2026-07-14 01:07:05.000000000 +0200 +++ new/nix-2.35.2/src/libutil-tests/serialise.cc 2026-08-12 23:09:18.000000000 +0200 @@ -1,5 +1,7 @@ #include "nix/util/serialise.hh" +#include "nix/util/config.hh" +#include <boost/context/detail/exception.hpp> #include <gtest/gtest.h> namespace nix { @@ -37,4 +39,43 @@ } } +// The following test catches the bug only under fcontext backend, +// but Boost.Coroutine2 stack switching when abandoning confuses the +// hell out of ASan. The workaround to getting ASan working isn't +// immediately useful because it works only with ucontext implementation. +// https://www.boost.org/doc/libs/1_89_0/libs/coroutine2/doc/html/coroutine2/stack/sanitizers.html +#if !NIX_ASAN_ENABLED + +TEST(sourceToSink, forcedUnwindUcaughtExceptions) +{ + int uncaughtExceptions = 42; + bool caught = false; + + auto sink = sourceToSink([&](Source & source) { + auto recordUncaughtExceptions = Finally([&]() { uncaughtExceptions = std::uncaught_exceptions(); }); + try { + StringSink s; + source.drainInto(s, 8); + source.drainInto(s, 8); + } catch (const boost::context::detail::forced_unwind &) { + caught = true; + throw; + } + }); + + *sink << 42; + + // Abandon the coroutine. This will trigger it to unwind with boost::context::detail::forced_unwind. + sink.reset(); + + ASSERT_TRUE(caught); + // This is a test for boost.context regression fixed by https://github.com/boostorg/context/pull/337. + // Without the fix std::uncaught_exceptions() *misreports* 0 while there's stack unwinding in progress. + // The issue only surfaces with libstdc++ and fcontext when boost.context + // uses fiber-specific exception states and messes with __cxa_get_globals(). + ASSERT_EQ(uncaughtExceptions, 1); +} + +#endif + } // namespace nix diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nix-2.35.1/src/nix/unix/daemon.cc new/nix-2.35.2/src/nix/unix/daemon.cc --- old/nix-2.35.1/src/nix/unix/daemon.cc 2026-07-14 01:07:05.000000000 +0200 +++ new/nix-2.35.2/src/nix/unix/daemon.cc 2026-08-12 23:09:18.000000000 +0200 @@ -375,7 +375,12 @@ // Handle the connection. auto store = storeConfig->openStore(); store->init(); - processConnection(store, FdSource(remote.get()), FdSink(remote.get()), trusted, NotRecursive); + processConnection( + std::move(store), + FdSource(remote.get()), + FdSink(remote.get()), + trusted, + RecursiveFlag::NotRecursive); exit(0); }, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nix-2.35.1/tests/nixos/functional/symlinked-home.nix new/nix-2.35.2/tests/nixos/functional/symlinked-home.nix --- old/nix-2.35.1/tests/nixos/functional/symlinked-home.nix 2026-07-14 01:07:05.000000000 +0200 +++ new/nix-2.35.2/tests/nixos/functional/symlinked-home.nix 2026-08-12 23:09:18.000000000 +0200 @@ -1,9 +1,11 @@ /** This test runs the functional tests on a NixOS system where the home directory - is symlinked to another location. + is symlinked to another location that also happens to reside in parent directory + that we don't have read permissions for (only execute). The purpose of this test is to find cases where Nix uses low-level operations - that don't support symlinks on paths that include them. + that don't support symlinks on paths that include them or requires excessive + permissions for path resolution. It is not a substitute for more intricate, use case-specific tests, but helps catch common issues. @@ -27,8 +29,12 @@ machine.succeed(""" ( set -x - mv /home/alice /home/alice.real - ln -s alice.real /home/alice + mkdir -p /home/alice.parent + chown alice:users /home/alice.parent + # Make the parent unreadable for good measure + chmod 0110 /home/alice.parent + mv /home/alice /home/alice.parent/alice.real + ln -s alice.parent/alice.real /home/alice ) 1>&2 """) machine.succeed("""
