From 7a923b3d41f54c17c8e9f2a44eaa18269947bd7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9B=D0=B5=D0=BE=D0=BD=D0=B8=D0=B4=20=D0=AE=D1=80=D1=8C?= =?UTF-8?q?=D0=B5=D0=B2=20=28Leonid=20Yuriev=29?= Date: Mon, 17 Mar 2025 11:56:36 +0300 Subject: [PATCH] =?UTF-8?q?mdbx:=20=D1=80=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D0=BE=D0=BA=20=D1=81=20=D0=B2=D1=8B=D0=BD=D0=BE=D1=81?= =?UTF-8?q?=D0=BE=D0=BC=20=D0=B2=20`cursor=5Fcheck=5Fmultiple()`.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api-cursor.c | 18 +++--------------- src/api-txn-data.c | 13 +++++++++++++ src/cursor.c | 15 +++++++++++++++ src/cursor.h | 3 +++ 4 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/api-cursor.c b/src/api-cursor.c index 4489a64f..4a506b41 100644 --- a/src/api-cursor.c +++ b/src/api-cursor.c @@ -712,22 +712,10 @@ int mdbx_cursor_put(MDBX_cursor *mc, const MDBX_val *key, MDBX_val *data, MDBX_p if (unlikely(rc != MDBX_SUCCESS)) return LOG_IFERR(rc); - /* Check this first so counter will always be zero on any early failures. */ if (unlikely(flags & MDBX_MULTIPLE)) { - if (unlikely(flags & MDBX_RESERVE)) - return LOG_IFERR(MDBX_EINVAL); - if (unlikely(!(mc->tree->flags & MDBX_DUPFIXED))) - return LOG_IFERR(MDBX_INCOMPATIBLE); - const size_t dcount = data[1].iov_len; - if (unlikely(dcount < 2 || data->iov_len == 0)) - return LOG_IFERR(MDBX_BAD_VALSIZE); - if (unlikely(mc->tree->dupfix_size != data->iov_len) && mc->tree->dupfix_size) - return LOG_IFERR(MDBX_BAD_VALSIZE); - if (unlikely(dcount > MAX_MAPSIZE / 2 / (BRANCH_NODE_MAX(MDBX_MAX_PAGESIZE) - NODESIZE))) { - /* checking for multiplication overflow */ - if (unlikely(dcount > MAX_MAPSIZE / 2 / data->iov_len)) - return LOG_IFERR(MDBX_TOO_LARGE); - } + rc = cursor_check_multiple(mc, key, data, flags); + if (unlikely(rc != MDBX_SUCCESS)) + return LOG_IFERR(rc); } if (flags & MDBX_RESERVE) { diff --git a/src/api-txn-data.c b/src/api-txn-data.c index 2be54df8..cc0891cb 100644 --- a/src/api-txn-data.c +++ b/src/api-txn-data.c @@ -266,6 +266,19 @@ int mdbx_put(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *key, MDBX_val *data, M rc = cursor_init(&cx.outer, txn, dbi); if (unlikely(rc != MDBX_SUCCESS)) return LOG_IFERR(rc); + + if (unlikely(flags & MDBX_MULTIPLE)) { + rc = cursor_check_multiple(&cx.outer, key, data, flags); + if (unlikely(rc != MDBX_SUCCESS)) + return LOG_IFERR(rc); + } + + if (flags & MDBX_RESERVE) { + if (unlikely(cx.outer.tree->flags & (MDBX_DUPSORT | MDBX_REVERSEDUP | MDBX_INTEGERDUP | MDBX_DUPFIXED))) + return LOG_IFERR(MDBX_INCOMPATIBLE); + data->iov_base = nullptr; + } + cx.outer.next = txn->cursors[dbi]; txn->cursors[dbi] = &cx.outer; diff --git a/src/cursor.c b/src/cursor.c index 9da14343..233c2246 100644 --- a/src/cursor.c +++ b/src/cursor.c @@ -1439,6 +1439,21 @@ insert_node:; return rc; } +int cursor_check_multiple(MDBX_cursor *mc, const MDBX_val *key, MDBX_val *data, unsigned flags) { + (void)key; + if (unlikely(flags & MDBX_RESERVE)) + return MDBX_EINVAL; + if (unlikely(!(mc->tree->flags & MDBX_DUPFIXED))) + return MDBX_INCOMPATIBLE; + const size_t number = data[1].iov_len; + if (unlikely(number > MAX_MAPSIZE / 2 / (BRANCH_NODE_MAX(MDBX_MAX_PAGESIZE) - NODESIZE))) { + /* checking for multiplication overflow */ + if (unlikely(number > MAX_MAPSIZE / 2 / data->iov_len)) + return MDBX_TOO_LARGE; + } + return MDBX_SUCCESS; +} + __hot int cursor_put_checklen(MDBX_cursor *mc, const MDBX_val *key, MDBX_val *data, unsigned flags) { cASSERT(mc, (mc->flags & z_inner) == 0); if (unlikely(key->iov_len > mc->clc->k.lmax || key->iov_len < mc->clc->k.lmin)) { diff --git a/src/cursor.h b/src/cursor.h index d8100999..d07be856 100644 --- a/src/cursor.h +++ b/src/cursor.h @@ -315,6 +315,9 @@ MDBX_INTERNAL MDBX_cursor *cursor_cpstk(const MDBX_cursor *csrc, MDBX_cursor *cd MDBX_INTERNAL int __must_check_result cursor_ops(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data, const MDBX_cursor_op op); +MDBX_INTERNAL int __must_check_result cursor_check_multiple(MDBX_cursor *mc, const MDBX_val *key, MDBX_val *data, + unsigned flags); + MDBX_INTERNAL int __must_check_result cursor_put_checklen(MDBX_cursor *mc, const MDBX_val *key, MDBX_val *data, unsigned flags);