mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-31 11:18:21 +08:00
mdbx: устранение регресса вероятности SIGSEGV при вытеснении/spilling страниц.
Ошибка внесена коммитом `a6f7d74a32a3cbcc310916a624a31302dbebfa07` от 2024-03-07 и присутствует в выпусках v0.13.1, v0.13.2, v0.13.3. Проблема оставалась незамеченной из-за специфических условий и низкой вероятности проявления. Суть ошибки: - функция cursor_touch() подготавливает стек страниц курсора к внесению изменений, при этом все страницы в стеке (от корневой до листовой в текущей позиции курсора) должны стать доступными для модификации. - микрооптимизация добавленная коммитом пропускала обход стека, если корневая страница уже доступна для модификации, но это допустимо/корректно только при отсутствии в стеке вытесненных/spilled страниц. - если же складывалась ситуация когда в стека была вытесненная некорневая страница, то она так и оставалась недоступной для записи и при попытке её изменения возникал SIGSEGV.
This commit is contained in:
parent
f6d91b3c5b
commit
cb8eec6d11
@ -168,7 +168,7 @@ __hot int cursor_touch(MDBX_cursor *const mc, const MDBX_val *key, const MDBX_va
|
||||
return err;
|
||||
}
|
||||
|
||||
if (likely(mc->top >= 0) && !is_modifable(mc->txn, mc->pg[mc->top])) {
|
||||
if (likely(is_pointed(mc)) && ((mc->txn->flags & MDBX_TXN_SPILLS) || !is_modifable(mc->txn, mc->pg[mc->top]))) {
|
||||
const int8_t top = mc->top;
|
||||
mc->top = 0;
|
||||
do {
|
||||
|
@ -50,6 +50,7 @@ int __must_check_result node_add_branch(MDBX_cursor *mc, size_t indx, const MDBX
|
||||
is_subpage(mp) ? "sub-" : "", mp->pgno, indx, pgno, key ? key->iov_len : 0, DKEY_DEBUG(key));
|
||||
|
||||
cASSERT(mc, page_type(mp) == P_BRANCH);
|
||||
cASSERT(mc, mp->txnid >= mc->txn->front_txnid);
|
||||
STATIC_ASSERT(NODESIZE % 2 == 0);
|
||||
|
||||
/* Move higher pointers up one slot. */
|
||||
|
@ -457,6 +457,8 @@ static __always_inline pgr_t page_get_inline(const uint16_t ILL, const MDBX_curs
|
||||
goto bailout;
|
||||
}
|
||||
|
||||
TRACE("dbi %zu, mc %p, page %u, %p", cursor_dbi(mc), __Wpedantic_format_voidptr(mc), pgno,
|
||||
__Wpedantic_format_voidptr(r.page));
|
||||
if (unlikely(mc->checking & z_pagecheck))
|
||||
return check_page_complete(ILL, r.page, mc, front);
|
||||
|
||||
|
10
src/spill.c
10
src/spill.c
@ -72,6 +72,8 @@ static size_t spill_cursor_keep(const MDBX_txn *const txn, const MDBX_cursor *mc
|
||||
intptr_t i = 0;
|
||||
do {
|
||||
mp = mc->pg[i];
|
||||
TRACE("dbi %zu, mc-%p[%zu], page %u %p", cursor_dbi(mc), __Wpedantic_format_voidptr(mc), i, mp->pgno,
|
||||
__Wpedantic_format_voidptr(mp));
|
||||
tASSERT(txn, !is_subpage(mp));
|
||||
if (is_modifable(txn, mp)) {
|
||||
size_t const n = dpl_search(txn, mp->pgno);
|
||||
@ -81,16 +83,18 @@ static size_t spill_cursor_keep(const MDBX_txn *const txn, const MDBX_cursor *mc
|
||||
*ptr = txn->wr.dirtylru;
|
||||
tASSERT(txn, dpl_age(txn, n) == 0);
|
||||
++keep;
|
||||
DEBUG("keep page %" PRIaPGNO " (%p), dbi %zu, %scursor %p[%zu]", mp->pgno, __Wpedantic_format_voidptr(mp),
|
||||
cursor_dbi(mc), is_inner(mc) ? "sub-" : "", __Wpedantic_format_voidptr(mc), i);
|
||||
}
|
||||
}
|
||||
} while (++i <= mc->top);
|
||||
|
||||
tASSERT(txn, is_leaf(mp));
|
||||
if (!mc->subcur || mc->ki[mc->top] >= page_numkeys(mp))
|
||||
break;
|
||||
if (!(node_flags(page_node(mp, mc->ki[mc->top])) & N_TREE))
|
||||
if (!inner_pointed(mc))
|
||||
break;
|
||||
mc = &mc->subcur->cursor;
|
||||
if (is_subpage(mc->pg[0]))
|
||||
break;
|
||||
}
|
||||
return keep;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user