aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLexi Winter <lexi@hemlock.eden.le-fay.org>2025-03-29 01:23:43 +0000
committerLexi Winter <lexi@hemlock.eden.le-fay.org>2025-03-29 01:23:43 +0000
commite9bd38ad8ede7e63adfaa297415542e819c19eb3 (patch)
tree3606a341c6e9d921eb2f64b71bd4de74b2ca8366
parent54b85919051bb6508b53ce98116608196573cfe7 (diff)
downloadlibnvxx-e9bd38ad8ede7e63adfaa297415542e819c19eb3.tar.gz
libnvxx-e9bd38ad8ede7e63adfaa297415542e819c19eb3.tar.bz2
make take_descriptor_array safer
-rw-r--r--libnvxx/nv_list.cc42
1 files changed, 21 insertions, 21 deletions
diff --git a/libnvxx/nv_list.cc b/libnvxx/nv_list.cc
index 72fc937..6bcfd7e 100644
--- a/libnvxx/nv_list.cc
+++ b/libnvxx/nv_list.cc
@@ -806,29 +806,29 @@ __nv_list::take_descriptor_array(std::string_view key)
{
__throw_if_error();
- // define this here to avoid throwing after we call
- // nvlist_take_descriptor_array().
- auto ret = std::vector<nv_fd>{};
+ /*
+ * don't use nvlist_take_descriptor_array() here, because we don't
+ * want to remove the array from the nvlist if vector allocation fails.
+ */
+
+ auto skey = std::string(key);
auto nitems = std::size_t{};
- auto ptr = __ptr_guard(
- ::nvlist_take_descriptor_array(__m_nv,
- std::string(key).c_str(),
- &nitems));
- auto fds = std::span(ptr.__ptr, ptr.__ptr + nitems);
-
- try {
- ret.reserve(fds.size());
- for (auto fd : fds)
- ret.push_back(nv_fd(fd));
-
- return ret;
- } catch (...) {
- // close all the fds we didn't manage to add to the vector
- for (auto fd : fds.subspan(ret.size()))
- (void)::close(fd);
- throw;
- }
+ auto ptr = ::nvlist_get_descriptor_array(__m_nv, skey.c_str(), &nitems);
+ auto fds = std::span(ptr, ptr + nitems);
+
+ /*
+ * reserve space before copying since creating an nv_fd will take
+ * ownership of the fd, and we don't want to partially close the fds
+ * if allocation fails.
+ */
+ auto ret = std::vector<nv_fd>{};
+ ret.reserve(fds.size());
+
+ std::ranges::copy(fds | construct<nv_fd>, std::back_inserter(ret));
+
+ ::nvlist_free_descriptor_array(__m_nv, skey.c_str());
+ return ret;
}
/*