diff options
author | pjd <pjd@FreeBSD.org> | 2015-01-30 09:44:29 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2015-01-30 09:44:29 +0000 |
commit | d08c53259eac79d61d0f15af9d8a2c5e09e4f89d (patch) | |
tree | 4499682cef8975f23d00e1fba77542ee63bee8bd | |
parent | 30e216f85893cebc73455d1d87e357e9867988c2 (diff) | |
download | FreeBSD-src-d08c53259eac79d61d0f15af9d8a2c5e09e4f89d.zip FreeBSD-src-d08c53259eac79d61d0f15af9d8a2c5e09e4f89d.tar.gz |
If moving descriptor or binary data to an nvlist fails, we need to close the
descriptor or free the memory before returning.
Submitted by: Mariusz Zaborski <oshogbo@FreeBSD.org>
While here, protect errno, so it won't be overwritted by close(2) or free(3).
-rw-r--r-- | lib/libnv/nvpair.c | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/lib/libnv/nvpair.c b/lib/libnv/nvpair.c index 4f0bd72..a2da8cc 100644 --- a/lib/libnv/nvpair.c +++ b/lib/libnv/nvpair.c @@ -1100,6 +1100,7 @@ nvpair_t * nvpair_movev_string(char *value, const char *namefmt, va_list nameap) { nvpair_t *nvp; + int serrno; if (value == NULL) { errno = EINVAL; @@ -1108,8 +1109,11 @@ nvpair_movev_string(char *value, const char *namefmt, va_list nameap) nvp = nvpair_allocv(NV_TYPE_STRING, (uint64_t)(uintptr_t)value, strlen(value) + 1, namefmt, nameap); - if (nvp == NULL) + if (nvp == NULL) { + serrno = errno; free(value); + errno = serrno; + } return (nvp); } @@ -1137,28 +1141,46 @@ nvpair_movev_nvlist(nvlist_t *value, const char *namefmt, va_list nameap) nvpair_t * nvpair_movev_descriptor(int value, const char *namefmt, va_list nameap) { + nvpair_t *nvp; + int serrno; if (value < 0 || !fd_is_valid(value)) { errno = EBADF; return (NULL); } - return (nvpair_allocv(NV_TYPE_DESCRIPTOR, (uint64_t)value, - sizeof(int64_t), namefmt, nameap)); + nvp = nvpair_allocv(NV_TYPE_DESCRIPTOR, (uint64_t)value, + sizeof(int64_t), namefmt, nameap); + if (nvp == NULL) { + serrno = errno; + close(value); + errno = serrno; + } + + return (nvp); } nvpair_t * nvpair_movev_binary(void *value, size_t size, const char *namefmt, va_list nameap) { + nvpair_t *nvp; + int serrno; if (value == NULL || size == 0) { errno = EINVAL; return (NULL); } - return (nvpair_allocv(NV_TYPE_BINARY, (uint64_t)(uintptr_t)value, size, - namefmt, nameap)); + nvp = nvpair_allocv(NV_TYPE_BINARY, (uint64_t)(uintptr_t)value, size, + namefmt, nameap); + if (nvp == NULL) { + serrno = errno; + free(value); + errno = serrno; + } + + return (nvp); } bool |