From b80d320eacb63e23cc636da3134e3b265e00036f Mon Sep 17 00:00:00 2001 From: Cole Helbling Date: Thu, 12 Feb 2026 08:38:54 -0800 Subject: [PATCH 1/3] filetransfer: mark enqueueFileTransfer() as noexcept --- src/libstore/filetransfer.cc | 5 +++-- src/libstore/include/nix/store/filetransfer.hh | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc index f7a5d672103..136de4276ac 100644 --- a/src/libstore/filetransfer.cc +++ b/src/libstore/filetransfer.cc @@ -965,7 +965,8 @@ struct curlFileTransfer : public FileTransfer return ItemHandle(static_cast(*item)); } - ItemHandle enqueueFileTransfer(const FileTransferRequest & request, Callback callback) override + ItemHandle + enqueueFileTransfer(const FileTransferRequest & request, Callback callback) noexcept override { /* Handle s3:// URIs by converting to HTTPS and optionally adding auth */ if (request.uri.scheme() == "s3") { @@ -1047,7 +1048,7 @@ void FileTransferRequest::setupForS3() #endif } -std::future FileTransfer::enqueueFileTransfer(const FileTransferRequest & request) +std::future FileTransfer::enqueueFileTransfer(const FileTransferRequest & request) noexcept { auto promise = std::make_shared>(); enqueueFileTransfer(request, {[promise](std::future fut) { diff --git a/src/libstore/include/nix/store/filetransfer.hh b/src/libstore/include/nix/store/filetransfer.hh index fa8a649e2b3..ca5d2a9f1cd 100644 --- a/src/libstore/include/nix/store/filetransfer.hh +++ b/src/libstore/include/nix/store/filetransfer.hh @@ -279,14 +279,14 @@ public: * exception. */ virtual ItemHandle - enqueueFileTransfer(const FileTransferRequest & request, Callback callback) = 0; + enqueueFileTransfer(const FileTransferRequest & request, Callback callback) noexcept = 0; /** * Unpause a transfer that has been previously paused by a dataCallback. */ virtual void unpauseTransfer(ItemHandle handle) = 0; - std::future enqueueFileTransfer(const FileTransferRequest & request); + std::future enqueueFileTransfer(const FileTransferRequest & request) noexcept; /** * Synchronously download a file. From 2208cf992634a84960cd7c69fad1c6184c05252d Mon Sep 17 00:00:00 2001 From: Cole Helbling Date: Thu, 12 Feb 2026 08:53:04 -0800 Subject: [PATCH 2/3] filetransfer: handle exceptions thrown from enqueueItem --- src/libstore/filetransfer.cc | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc index 136de4276ac..34c050d4cee 100644 --- a/src/libstore/filetransfer.cc +++ b/src/libstore/filetransfer.cc @@ -972,10 +972,22 @@ struct curlFileTransfer : public FileTransfer if (request.uri.scheme() == "s3") { auto modifiedRequest = request; modifiedRequest.setupForS3(); - return enqueueItem(make_ref(*this, std::move(modifiedRequest), std::move(callback))); + auto item = make_ref(*this, std::move(modifiedRequest), std::move(callback)); + try { + return enqueueItem(item); + } catch (const nix::Error & e) { + item->fail(e); + return ItemHandle(static_cast(*item)); + } } - return enqueueItem(make_ref(*this, request, std::move(callback))); + auto item = make_ref(*this, request, std::move(callback)); + try { + return enqueueItem(item); + } catch (const nix::Error & e) { + item->fail(e); + return ItemHandle(static_cast(*item)); + } } void unpauseTransfer(ref item) From 3619618e8d079f70bc45309eb59f29d27d0b7bf7 Mon Sep 17 00:00:00 2001 From: Cole Helbling Date: Thu, 19 Feb 2026 11:52:18 -0800 Subject: [PATCH 3/3] fixup: make ItemHandle own a ref to prevent UAF on failed transfers --- src/libstore/filetransfer.cc | 8 ++++---- src/libstore/include/nix/store/filetransfer.hh | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc index 34c050d4cee..240d5aa9370 100644 --- a/src/libstore/filetransfer.cc +++ b/src/libstore/filetransfer.cc @@ -962,7 +962,7 @@ struct curlFileTransfer : public FileTransfer writeFull(wakeupPipe.writeSide.get(), " "); #endif - return ItemHandle(static_cast(*item)); + return ItemHandle(ref(std::move(item))); } ItemHandle @@ -977,7 +977,7 @@ struct curlFileTransfer : public FileTransfer return enqueueItem(item); } catch (const nix::Error & e) { item->fail(e); - return ItemHandle(static_cast(*item)); + return ItemHandle(ref(std::move(item))); } } @@ -986,7 +986,7 @@ struct curlFileTransfer : public FileTransfer return enqueueItem(item); } catch (const nix::Error & e) { item->fail(e); - return ItemHandle(static_cast(*item)); + return ItemHandle(ref(std::move(item))); } } @@ -1001,7 +1001,7 @@ struct curlFileTransfer : public FileTransfer void unpauseTransfer(ItemHandle handle) override { - unpauseTransfer(ref{static_cast(handle.item.get()).shared_from_this()}); + unpauseTransfer(ref{static_cast(*handle.item).shared_from_this()}); } }; diff --git a/src/libstore/include/nix/store/filetransfer.hh b/src/libstore/include/nix/store/filetransfer.hh index ca5d2a9f1cd..9220c26cb0d 100644 --- a/src/libstore/include/nix/store/filetransfer.hh +++ b/src/libstore/include/nix/store/filetransfer.hh @@ -262,11 +262,11 @@ public: */ struct ItemHandle { - std::reference_wrapper item; + ref item; friend struct FileTransfer; - ItemHandle(Item & item) - : item(item) + explicit ItemHandle(ref item) + : item(std::move(item)) { } };