From nobody Sat Jun 20 14:29:02 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4gjGzz1JMfz6jf8n for ; Sat, 20 Jun 2026 14:29:03 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4gjGzz0bsMz43Gg for ; Sat, 20 Jun 2026 14:29:03 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1781965743; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=GmuouH9J6aoTPFGG1WnHZKSvW+0qtlwn1+dXs1wV9Zk=; b=eM7DuBJdoNBCYH+IbMk7TEJEJcIj6pVSwbefnqEjPHUdVToSVJwroMye/ey/nC1m9lr1/M B7S11T2zyDkHHoD6GT1QkCYBBBWV211wsbvb1G11exI8QHL/lZehoo5Ht0fpPm11a+KrUo uIS4+0kBGNuuSapGIY1y4NVVn0w5ICt5l9rkwhl/LKk/EFKo0JdDxcVCUAMF2kJwA4Qt3M 1MpEjj4uJGr2jWDwl8zADSXgBvv3NnoP9lHQLOFHGYEMh3ok6snEHM0SOJETFOK8iJYyqV NaT1VHGiVnU4rA66Un2DGLdOA0un+ZfsM6dVkZHPw01Om8GjaWh/jP4Yg69Rhw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1781965743; a=rsa-sha256; cv=none; b=OO/pQUsSuH5tY+/GUA0nvYRMCKK1XRELiQDWyBgo+A6mYasbdB6q6UiWlZid7QOkufmwqJ sWiRzJhaUvAYBSSSmaVo75pTbzoc2huGCz9xUnGUiaHnEjaqUw2eg96gNv2tcsJ2OX6627 xBK8brJUfVx3piEk8ZFVa1ALgnK45TGmVOAj8FDnLz0UHqbYRmQ5QvIKSmeurX/W+pg6my QQqiScUw1I+AbmJEG7skLi0EoofMAnoq950kRQ3+4298eg6fA4WZ8HjZpBH89nrKR7C5al zgviI2wa0qKXkO2xsOfu0KIPmhibKgBUa1O1BrxuBMSHyQ1t8b+40m/anTl4fg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1781965743; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=GmuouH9J6aoTPFGG1WnHZKSvW+0qtlwn1+dXs1wV9Zk=; b=mMqj4hQZptf8y60NObZgDCCmEgs6N+a3agGF1Lxsm/GOVrQta4ryN+iA4OeJBIGfkuDGOz 2D7akOByAlKgAdEOxWkRnUve903fF/B4LZ2MZqKgkEBWe2lPdnEM0+WrQ5i+RSXdg5szq0 dOgwj/jn8yQR9qQxGtN9MyKyn95DYsPzsc+alx3EMQnqe857AJj2qKgDQiVd/ZSO+cs4mv QT1MJ2rPKxp6cpBCY7tMXWNCA3Mu9hbduJhuqd/xdgj1CVkHn/S4m/+U/NKfDQIJmshsj6 jkebuhKpI7Q0sTVlWZ267IUv4UvFrWPXEBXcFc56aOpsYLVtLTpC3WuqqkHY+w== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gjGzy6cvQzZxl for ; Sat, 20 Jun 2026 14:29:02 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3e4a6 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Sat, 20 Jun 2026 14:29:02 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Bojan Novk=?utf-8?Q?ovi=C4=87?= Subject: git: f879eb3febb6 - main - libc/dbm: Differentiate between uninitialized and end-of-db cursors List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: bnovkov X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: f879eb3febb6c294d684e8e7fecd5cc396ec5a28 Auto-Submitted: auto-generated Date: Sat, 20 Jun 2026 14:29:02 +0000 Message-Id: <6a36a3ae.3e4a6.b87c159@gitrepo.freebsd.org> The branch main has been updated by bnovkov: URL: https://cgit.FreeBSD.org/src/commit/?id=f879eb3febb6c294d684e8e7fecd5cc396ec5a28 commit f879eb3febb6c294d684e8e7fecd5cc396ec5a28 Author: Bojan Novković AuthorDate: 2026-06-19 15:24:05 +0000 Commit: Bojan Novković CommitDate: 2026-06-20 14:27:44 +0000 libc/dbm: Differentiate between uninitialized and end-of-db cursors Commit `3a686b851f8f` fixed a `dbm_nextkey` edge case when using the function after reaching the end of the database, but it inadvertently broke the following `R_NEXT` behaviour: "If the cursor is not yet set, this is the same as the R_FIRST flag." Fix this by adding a new cursor constant that allows us to differentiate between an unset cursor and a cursor that overflowed. Reported by: ae Fixes: 3a686b851f8f Sponsored by: Klara, Inc. Differential Revision: https://reviews.freebsd.org/D57670 Reviewed by: markj --- lib/libc/db/hash/hash.c | 12 ++++++++---- lib/libc/tests/db/dbm_nextkey_test.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/lib/libc/db/hash/hash.c b/lib/libc/db/hash/hash.c index 88a3ffeab828..b025a2310e8f 100644 --- a/lib/libc/db/hash/hash.c +++ b/lib/libc/db/hash/hash.c @@ -81,6 +81,10 @@ static void swap_header_copy(HASHHDR *, HASHHDR *); #define ERROR (-1) #define ABNORMAL (1) +/* Cursor status */ +#define CURSOR_NOT_SET -1 +#define CURSOR_OVERFLOW -2 + #ifdef HASH_STATISTICS int hash_accesses, hash_collisions, hash_expansions, hash_overflows; #endif @@ -180,7 +184,7 @@ __hash_open(const char *file, int flags, int mode, hashp->new_file = new_table; hashp->save_file = file && (flags & O_RDWR); - hashp->cbucket = -1; + hashp->cbucket = CURSOR_NOT_SET; if (!(dbp = (DB *)malloc(sizeof(DB)))) { save_errno = errno; hdestroy(hashp); @@ -711,11 +715,11 @@ hash_seq(const DB *dbp, DBT *key, DBT *data, u_int32_t flag) #ifdef HASH_STATISTICS hash_accesses++; #endif - if (flag == R_FIRST) { + if (flag == R_FIRST || hashp->cbucket == CURSOR_NOT_SET) { hashp->cbucket = 0; hashp->cndx = 1; hashp->cpage = NULL; - } else if (hashp->cbucket < 0) { /* R_NEXT */ + } else if (hashp->cbucket <= CURSOR_OVERFLOW) { return (ABNORMAL); } next_bucket: @@ -734,7 +738,7 @@ next_bucket: } hashp->cbucket = bucket; if ((u_int32_t)hashp->cbucket > hashp->MAX_BUCKET) { - hashp->cbucket = -1; + hashp->cbucket = CURSOR_OVERFLOW; return (ABNORMAL); } } else { diff --git a/lib/libc/tests/db/dbm_nextkey_test.c b/lib/libc/tests/db/dbm_nextkey_test.c index 67b745efb196..993cec8d7f85 100644 --- a/lib/libc/tests/db/dbm_nextkey_test.c +++ b/lib/libc/tests/db/dbm_nextkey_test.c @@ -45,9 +45,42 @@ ATF_TC_BODY(dbm_nextkey_test, tc) dbm_close(db); } +ATF_TC(dbm_nextkey_cursor_test); +ATF_TC_HEAD(dbm_nextkey_cursor_test, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Check that dbm_nextkey acts as if R_FIRST was passed if the cursor is not set"); +} + +ATF_TC_BODY(dbm_nextkey_cursor_test, tc) +{ + DBM *db; + datum key, data; + + data.dptr = "bar"; + data.dsize = strlen("bar"); + key.dptr = "foo"; + key.dsize = strlen("foo"); + + db = dbm_open(path, O_RDWR | O_CREAT, 0755); + ATF_CHECK(db != NULL); + ATF_REQUIRE(atf_utils_file_exists(dbname)); + ATF_REQUIRE(dbm_store(db, key, data, DBM_INSERT) != -1); + dbm_close(db); + + db = dbm_open(path, O_RDWR | O_CREAT, 0755); + ATF_CHECK(db != NULL); + ATF_REQUIRE(atf_utils_file_exists(dbname)); + key = dbm_nextkey(db); + ATF_REQUIRE(key.dptr != NULL); + + dbm_close(db); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, dbm_nextkey_test); + ATF_TP_ADD_TC(tp, dbm_nextkey_cursor_test); return (atf_no_error()); }