From e9bd38ad8ede7e63adfaa297415542e819c19eb3 Mon Sep 17 00:00:00 2001 From: Lexi Winter Date: Sat, 29 Mar 2025 01:23:43 +0000 Subject: make take_descriptor_array safer --- libnvxx/nv_list.cc | 42 +++++++++++++++++++++--------------------- 1 file 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{}; + /* + * 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{}; + ret.reserve(fds.size()); + + std::ranges::copy(fds | construct, std::back_inserter(ret)); + + ::nvlist_free_descriptor_array(__m_nv, skey.c_str()); + return ret; } /* -- cgit v1.2.3