NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: kern/60340: npf(4): quadratic-time state/config export
The following reply was made to PR kern/60340; it has been noted by GNATS.
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
To: gnats-bugs%NetBSD.org@localhost, netbsd-bugs%NetBSD.org@localhost
Cc:
Subject: Re: kern/60340: npf(4): quadratic-time state/config export
Date: Thu, 18 Jun 2026 20:44:05 +0000
This is a multi-part message in MIME format.
--=_jTTFFMu/al3E0ztP4Shf9axJ0hgFpHTk
Candidate fix attached, untested -- need to construct a reproducer
with a gigantic state table to verify that it doesn't provoke
quadratic-time export.
--=_jTTFFMu/al3E0ztP4Shf9axJ0hgFpHTk
Content-Type: text/plain; charset="ISO-8859-1"; name="pr60340-nvlistquadtime"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment; filename="pr60340-nvlistquadtime.patch"
# HG changeset patch
# User Taylor R Campbell <riastradh%NetBSD.org@localhost>
# Date 1781815285 0
# Thu Jun 18 20:41:25 2026 +0000
# Branch trunk
# Node ID 7b5e16fb12943b9c83a6e1cec19c5dd3002dfc57
# Parent babdf5c7e2cbe4d552248d2f38ead15e92b0b64f
# EXP-Topic riastradh-pr60340-nvlistquadtime
WIP: nvlist(9): Avoid quadratic-time array construction.
We could do this doubling in realloc(9) itself but that might have
nontrivial downstream consequences for other kernel users.
PR kern/60340: npf(4): quadratic-time state/config export
diff -r babdf5c7e2cb -r 7b5e16fb1294 sys/external/bsd/libnv/dist/nvpair.c
--- a/sys/external/bsd/libnv/dist/nvpair.c Tue Jun 16 23:37:48 2026 +0000
+++ b/sys/external/bsd/libnv/dist/nvpair.c Thu Jun 18 20:41:25 2026 +0000
@@ -113,6 +113,7 @@ struct nvpair {
uint64_t nvp_data;
size_t nvp_datasize;
size_t nvp_nitems; /* Used only for array types. */
+ size_t nvp_nalloc; /* Used only for array types. */
nvlist_t *nvp_list;
TAILQ_ENTRY(nvpair) nvp_next;
};
@@ -161,6 +162,7 @@ nvpair_allocv(const char *name, int type
nvp->nvp_data =3D data;
nvp->nvp_datasize =3D datasize;
nvp->nvp_nitems =3D nitems;
+ nvp->nvp_nalloc =3D nitems;
nvp->nvp_magic =3D NVPAIR_MAGIC;
}
=20
@@ -170,20 +172,44 @@ nvpair_allocv(const char *name, int type
static int
nvpair_append(nvpair_t *nvp, const void *value, size_t valsize, size_t dat=
asize)
{
- void *olddata, *data, *valp;
+ void *data, *valp;
size_t oldlen;
=20
oldlen =3D nvp->nvp_nitems * valsize;
- olddata =3D (void *)(uintptr_t)nvp->nvp_data;
- data =3D nv_realloc(olddata, oldlen + valsize);
- if (data =3D=3D NULL) {
- ERRNO_SET(ENOMEM);
- return (-1);
+ if (nvp->nvp_nitems < nvp->nvp_nalloc) {
+ data =3D (void *)(uintptr_t)nvp->nvp_data;
+ } else {
+ void *const olddata =3D (void *)(uintptr_t)nvp->nvp_data;
+ size_t newlen, newnalloc;
+
+ if (valsize > SIZE_MAX - oldlen) {
+ ERRNO_SET(ENOMEM);
+ return (-1);
+ }
+ if (oldlen > SIZE_MAX/2 - 1) {
+ /*
+ * Degrade to quadratic-time appending once
+ * we're nearing SIZE_MAX -- only relevant on a
+ * 32-bit platform, where we're likely to
+ * exhaust memory before this point anyway.
+ */
+ newlen =3D oldlen + valsize;
+ newnalloc =3D nvp->nvp_nalloc + 1;
+ } else {
+ newlen =3D 2*oldlen + valsize;
+ newnalloc =3D 2*nvp->nvp_nalloc + 1;
+ }
+ data =3D nv_realloc(olddata, newlen);
+ if (data =3D=3D NULL) {
+ ERRNO_SET(ENOMEM);
+ return (-1);
+ }
+ nvp->nvp_nalloc =3D newnalloc;
+ nvp->nvp_data =3D (uint64_t)(uintptr_t)data;
}
valp =3D (unsigned char *)data + oldlen;
memcpy(valp, value, valsize);
=20
- nvp->nvp_data =3D (uint64_t)(uintptr_t)data;
nvp->nvp_datasize +=3D datasize;
nvp->nvp_nitems++;
return (0);
--=_jTTFFMu/al3E0ztP4Shf9axJ0hgFpHTk--
Home |
Main Index |
Thread Index |
Old Index