diff options
| author | Lexi Winter <lexi@hemlock.eden.le-fay.org> | 2025-03-29 01:23:43 +0000 |
|---|---|---|
| committer | Lexi Winter <lexi@hemlock.eden.le-fay.org> | 2025-03-29 01:23:43 +0000 |
| commit | e9bd38ad8ede7e63adfaa297415542e819c19eb3 (patch) | |
| tree | 3606a341c6e9d921eb2f64b71bd4de74b2ca8366 | |
| parent | 54b85919051bb6508b53ce98116608196573cfe7 (diff) | |
| download | libnvxx-e9bd38ad8ede7e63adfaa297415542e819c19eb3.tar.gz libnvxx-e9bd38ad8ede7e63adfaa297415542e819c19eb3.tar.bz2 | |
make take_descriptor_array safer
| -rw-r--r-- | libnvxx/nv_list.cc | 42 |
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; } /* |
