From b98895b8c700f741f24468d061ab24e1fa6963bb Mon Sep 17 00:00:00 2001 From: Leonid Yuriev Date: Mon, 18 Jan 2021 14:27:58 +0300 Subject: [PATCH] mdbx: fix unaligned access to `bootid` on the meta-pages. Assume this fixes https://github.com/erthink/libmdbx/issues/153 Change-Id: I062c1bd99795a7b875d1cf60658790c1071a6775 --- ChangeLog.md | 2 +- src/core.c | 15 ++++++--------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 27db6b9e..5844ea50 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -23,7 +23,7 @@ Fixes: - Fixed missing cleanup (null assigned) in the C++ commit/abort (https://github.com/erthink/libmdbx/pull/143). - Fixed `mdbx_realloc()` for case of nullptr and `MDBX_AVOID_CRT=ON` for Windows. - Fixed the possibility to use invalid and renewed (closed & re-opened, dropped & re-created) DBI-handles (https://github.com/erthink/libmdbx/issues/146). - - Fixed 4-byte aligned access to 64-bit integers. + - Fixed 4-byte aligned access to 64-bit integers, including access to the `bootid` meta-page's field (https://github.com/erthink/libmdbx/issues/153). ## v0.9.2 scheduled at 2020-11-27 diff --git a/src/core.c b/src/core.c index 815778f0..8ac34a53 100644 --- a/src/core.c +++ b/src/core.c @@ -4355,7 +4355,7 @@ bailout: /*----------------------------------------------------------------------------*/ static __always_inline bool meta_bootid_match(const MDBX_meta *meta) { - return meta->mm_bootid.x == bootid.x && meta->mm_bootid.y == bootid.y && + return memcmp(&meta->mm_bootid, &bootid, 16) == 0 && (bootid.x | bootid.y) != 0; } @@ -4407,7 +4407,7 @@ static __inline void mdbx_meta_update_end(const MDBX_env *env, MDBX_meta *meta, mdbx_assert(env, unaligned_peek_u64(4, meta->mm_txnid_b) < txnid); (void)env; mdbx_jitter4testing(true); - meta->mm_bootid = bootid; + memcpy(&meta->mm_bootid, &bootid, 16); unaligned_poke_u64(4, meta->mm_txnid_b, txnid); } @@ -4417,7 +4417,7 @@ static __inline void mdbx_meta_set_txnid(const MDBX_env *env, MDBX_meta *meta, (void)env; /* update inconsistent since this function used ONLY for filling meta-image * for writing, but not the actual meta-page */ - meta->mm_bootid = bootid; + memcpy(&meta->mm_bootid, &bootid, 16); unaligned_poke_u64(4, meta->mm_txnid_a, txnid); unaligned_poke_u64(4, meta->mm_txnid_b, txnid); } @@ -17304,12 +17304,9 @@ __cold int mdbx_env_info_ex(const MDBX_env *env, const MDBX_txn *txn, arg->mi_meta2_txnid = mdbx_meta_txnid_fluid(env, meta2); arg->mi_meta2_sign = unaligned_peek_u64(4, meta2->mm_datasync_sign); if (likely(bytes > size_before_bootid)) { - arg->mi_bootid.meta0.x = meta0->mm_bootid.x; - arg->mi_bootid.meta1.x = meta0->mm_bootid.x; - arg->mi_bootid.meta2.x = meta0->mm_bootid.x; - arg->mi_bootid.meta0.y = meta0->mm_bootid.y; - arg->mi_bootid.meta1.y = meta0->mm_bootid.y; - arg->mi_bootid.meta2.y = meta0->mm_bootid.y; + memcpy(&arg->mi_bootid.meta0, &meta0->mm_bootid, 16); + memcpy(&arg->mi_bootid.meta1, &meta1->mm_bootid, 16); + memcpy(&arg->mi_bootid.meta2, &meta2->mm_bootid, 16); } const MDBX_meta *txn_meta = recent_meta;