aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2025-09-10 14:33:35 +0000
committerMark Johnston <markj@FreeBSD.org>2025-09-10 16:00:13 +0000
commit0b68e3ce6e0e437fa480b25a0ef706ee08562257 (patch)
tree0364e7cc9a86c649d5d8795785dba149b69e5ae0
parent187ee62c71f2be62870f26ae98de865e330121be (diff)
libnv: Fix handling of nvlist_dump() and nvlist_send() for child nvlists
Suppose an nvlist nvl belongs to a parent nvlist or nvlist array. In this case, nvl contains a pointer to its container. This trips up nvlist_send(nvl) and nvlist_dump(nvl), which intuitively should only operate on nvl and its nvpairs. In particular, both of these functions will traverse to nvl's parent and start sending/dumping the parent's nvpairs, which results in assertion failures or nonsensical output, respectively. Reviewed by: oshogbo MFC after: 2 weeks Sponsored by: Innovate UK Differential Revision: https://reviews.freebsd.org/D52360
-rw-r--r--sys/contrib/libnv/nvlist.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/sys/contrib/libnv/nvlist.c b/sys/contrib/libnv/nvlist.c
index 41edc72322c3..73226ee51a78 100644
--- a/sys/contrib/libnv/nvlist.c
+++ b/sys/contrib/libnv/nvlist.c
@@ -478,7 +478,7 @@ nvlist_dump_error_check(const nvlist_t *nvl, int fd, int level)
void
nvlist_dump(const nvlist_t *nvl, int fd)
{
- const nvlist_t *tmpnvl;
+ const nvlist_t *tmpnvl, *top;
nvpair_t *nvp, *tmpnvp;
void *cookie;
int level;
@@ -487,6 +487,7 @@ nvlist_dump(const nvlist_t *nvl, int fd)
if (nvlist_dump_error_check(nvl, fd, level))
return;
+ top = nvl;
nvp = nvlist_first_nvpair(nvl);
while (nvp != NULL) {
dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp),
@@ -645,6 +646,8 @@ nvlist_dump(const nvlist_t *nvl, int fd)
while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
do {
+ if (nvl == top)
+ return;
cookie = NULL;
if (nvlist_in_array(nvl))
dprintf(fd, "%*s,\n", level * 4, "");
@@ -847,7 +850,7 @@ nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep)
{
unsigned char *buf, *ptr;
size_t left, size;
- const nvlist_t *tmpnvl;
+ const nvlist_t *tmpnvl, *top;
nvpair_t *nvp, *tmpnvp;
void *cookie;
@@ -868,6 +871,7 @@ nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep)
ptr = nvlist_pack_header(nvl, ptr, &left);
+ top = nvl;
nvp = nvlist_first_nvpair(nvl);
while (nvp != NULL) {
NVPAIR_ASSERT(nvp);
@@ -958,6 +962,8 @@ nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep)
goto fail;
while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
do {
+ if (nvl == top)
+ goto out;
cookie = NULL;
if (nvlist_in_array(nvl)) {
ptr = nvpair_pack_nvlist_array_next(ptr,