Skip site navigation (1)Skip section navigation (2)


| raw e-mail | index | archive | help
The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=0b68e3ce6e0e437fa480b25a0ef706ee08562257

commit 0b68e3ce6e0e437fa480b25a0ef706ee08562257
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2025-09-10 14:33:35 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2025-09-10 16:00:13 +0000

    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
---
 sys/contrib/libnv/nvlist.c | 10 ++++++++--
 1 file 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,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?>