1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

fix aligned memcpy()-like functions usage

I found that memcpy_aligned was used incorrectly at redo log and decided to put
assertions in aligned functions. And found even more incorrect cases.

Given the amount discovered of bugs, I left assertions to prevent future bugs.

my_assume_aligned(): instead of MY_ASSUME_ALIGNED macro
This commit is contained in:
Eugene Kosov
2020-01-21 22:22:48 +08:00
parent cdd54c852a
commit 700e010309
11 changed files with 38 additions and 32 deletions

View File

@@ -197,37 +197,50 @@ extern ulonglong strtoull(const char *str, char **ptr, int base);
} }
# ifdef _MSC_VER # ifdef _MSC_VER
# define MY_ASSUME_ALIGNED(x,n) x template <size_t Alignment, class T> static inline T my_assume_aligned(T ptr)
{
DBUG_ASSERT(reinterpret_cast<size_t>(ptr) % Alignment == 0);
__assume(reinterpret_cast<size_t>(ptr) % Alignment == 0);
return ptr;
}
# else # else
# define MY_ASSUME_ALIGNED(x,n) __builtin_assume_aligned(x,n) template <size_t Alignment, class T> static inline T my_assume_aligned(T ptr)
{
DBUG_ASSERT(reinterpret_cast<size_t>(ptr) % Alignment == 0);
return static_cast<T>(__builtin_assume_aligned(ptr, Alignment));
}
# endif # endif
template <size_t Alignment> template <size_t Alignment>
inline void *memcpy_aligned(void *dest, const void *src, size_t n) inline void *memcpy_aligned(void *dest, const void *src, size_t n)
{ {
static_assert(Alignment && !(Alignment & (Alignment - 1)), "power of 2"); static_assert(Alignment && !(Alignment & (Alignment - 1)), "power of 2");
return memcpy(MY_ASSUME_ALIGNED(dest, Alignment),
MY_ASSUME_ALIGNED(src, Alignment), n); return memcpy(my_assume_aligned<Alignment>(dest),
my_assume_aligned<Alignment>(src), n);
} }
template <size_t Alignment> template <size_t Alignment>
inline void *memmove_aligned(void *dest, const void *src, size_t n) inline void *memmove_aligned(void *dest, const void *src, size_t n)
{ {
static_assert(Alignment && !(Alignment & (Alignment - 1)), "power of 2"); static_assert(Alignment && !(Alignment & (Alignment - 1)), "power of 2");
return memmove(MY_ASSUME_ALIGNED(dest, Alignment),
MY_ASSUME_ALIGNED(src, Alignment), n); return memmove(my_assume_aligned<Alignment>(dest),
my_assume_aligned<Alignment>(src), n);
} }
template <size_t Alignment> template <size_t Alignment>
inline int memcmp_aligned(const void *s1, const void *s2, size_t n) inline int memcmp_aligned(const void *s1, const void *s2, size_t n)
{ {
static_assert(Alignment && !(Alignment & (Alignment - 1)), "power of 2"); static_assert(Alignment && !(Alignment & (Alignment - 1)), "power of 2");
return memcmp(MY_ASSUME_ALIGNED(s1, Alignment),
MY_ASSUME_ALIGNED(s2, Alignment), n); return memcmp(my_assume_aligned<Alignment>(s1),
my_assume_aligned<Alignment>(s2), n);
} }
template <size_t Alignment> template <size_t Alignment>
inline void *memset_aligned(void *s, int c, size_t n) inline void *memset_aligned(void *s, int c, size_t n)
{ {
static_assert(Alignment && !(Alignment & (Alignment - 1)), "power of 2"); static_assert(Alignment && !(Alignment & (Alignment - 1)), "power of 2");
return memset(MY_ASSUME_ALIGNED(s, Alignment), c, n);
return memset(my_assume_aligned<Alignment>(s), c, n);
} }
#endif #endif

View File

@@ -1967,9 +1967,8 @@ btr_root_raise_and_insert(
the field only matters on leaf pages, and the root no the field only matters on leaf pages, and the root no
longer is a leaf page. (Older versions of InnoDB did longer is a leaf page. (Older versions of InnoDB did
set PAGE_MAX_TRX_ID on all secondary index pages.) */ set PAGE_MAX_TRX_ID on all secondary index pages.) */
byte* p = static_cast<byte*>( byte* p = my_assume_aligned<8>(
MY_ASSUME_ALIGNED(PAGE_HEADER + PAGE_MAX_TRX_ID PAGE_HEADER + PAGE_MAX_TRX_ID + root->frame);
+ root->frame, 8));
if (UNIV_LIKELY_NULL(root_page_zip)) { if (UNIV_LIKELY_NULL(root_page_zip)) {
memset_aligned<8>(p, 0, 8); memset_aligned<8>(p, 0, 8);
page_zip_write_header(root_page_zip, p, 8, mtr); page_zip_write_header(root_page_zip, p, 8, mtr);
@@ -1980,9 +1979,8 @@ btr_root_raise_and_insert(
/* PAGE_ROOT_AUTO_INC is only present in the clustered index /* PAGE_ROOT_AUTO_INC is only present in the clustered index
root page; on other clustered index pages, we want to reserve root page; on other clustered index pages, we want to reserve
the field PAGE_MAX_TRX_ID for future use. */ the field PAGE_MAX_TRX_ID for future use. */
byte* p = static_cast<byte*>( byte* p = my_assume_aligned<8>(
MY_ASSUME_ALIGNED(PAGE_HEADER + PAGE_MAX_TRX_ID PAGE_HEADER + PAGE_MAX_TRX_ID + new_block->frame);
+ new_block->frame, 8));
if (UNIV_LIKELY_NULL(new_page_zip)) { if (UNIV_LIKELY_NULL(new_page_zip)) {
memset_aligned<8>(p, 0, 8); memset_aligned<8>(p, 0, 8);
page_zip_write_header(new_page_zip, p, 8, mtr); page_zip_write_header(new_page_zip, p, 8, mtr);

View File

@@ -338,7 +338,7 @@ Datafile::read_first_page(bool read_only_mode)
} }
if (m_order == 0) { if (m_order == 0) {
if (memcmp_aligned<4>(FIL_PAGE_SPACE_ID + m_first_page, if (memcmp_aligned<2>(FIL_PAGE_SPACE_ID + m_first_page,
FSP_HEADER_OFFSET + FSP_SPACE_ID FSP_HEADER_OFFSET + FSP_SPACE_ID
+ m_first_page, 4)) { + m_first_page, 4)) {
ib::error() ib::error()

View File

@@ -298,8 +298,7 @@ log_reserve_and_write_fast(
*start_lsn = log_sys.lsn; *start_lsn = log_sys.lsn;
memcpy_aligned<OS_FILE_LOG_BLOCK_SIZE>(log_sys.buf + log_sys.buf_free, memcpy(log_sys.buf + log_sys.buf_free, str, len);
str, len);
log_block_set_data_len( log_block_set_data_len(
reinterpret_cast<byte*>(ut_align_down( reinterpret_cast<byte*>(ut_align_down(

View File

@@ -398,8 +398,7 @@ page_rec_is_infimum(const rec_t* rec);
inline trx_id_t page_get_max_trx_id(const page_t *page) inline trx_id_t page_get_max_trx_id(const page_t *page)
{ {
static_assert((PAGE_HEADER + PAGE_MAX_TRX_ID) % 8 == 0, "alignment"); static_assert((PAGE_HEADER + PAGE_MAX_TRX_ID) % 8 == 0, "alignment");
const byte *p= static_cast<const byte*> const auto *p= my_assume_aligned<8>(page + PAGE_HEADER + PAGE_MAX_TRX_ID);
(MY_ASSUME_ALIGNED(page + PAGE_HEADER + PAGE_MAX_TRX_ID, 8));
return mach_read_from_8(p); return mach_read_from_8(p);
} }

View File

@@ -355,8 +355,7 @@ part_loop:
- log_sys.buf_free % OS_FILE_LOG_BLOCK_SIZE; - log_sys.buf_free % OS_FILE_LOG_BLOCK_SIZE;
} }
memcpy_aligned<OS_FILE_LOG_BLOCK_SIZE>(log_sys.buf + log_sys.buf_free, memcpy(log_sys.buf + log_sys.buf_free, str, len);
str, len);
str_len -= len; str_len -= len;
str = str + len; str = str + len;

View File

@@ -4518,7 +4518,7 @@ corrupted:
return false; return false;
} }
const ulint space_id = memcmp_aligned<4>( const ulint space_id = memcmp_aligned<2>(
FIL_PAGE_SPACE_ID + page, FIL_PAGE_SPACE_ID + page,
FSP_HEADER_OFFSET + FSP_SPACE_ID + page, 4) FSP_HEADER_OFFSET + FSP_SPACE_ID + page, 4)
? ULINT_UNDEFINED ? ULINT_UNDEFINED

View File

@@ -199,9 +199,8 @@ page_set_max_trx_id(
{ {
ut_ad(!mtr || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); ut_ad(!mtr || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
static_assert((PAGE_HEADER + PAGE_MAX_TRX_ID) % 8 == 0, "alignment"); static_assert((PAGE_HEADER + PAGE_MAX_TRX_ID) % 8 == 0, "alignment");
byte *max_trx_id= static_cast<byte*>(MY_ASSUME_ALIGNED(PAGE_MAX_TRX_ID byte *max_trx_id= my_assume_aligned<8>(PAGE_MAX_TRX_ID +
+ PAGE_HEADER PAGE_HEADER + block->frame);
+ block->frame, 8));
if (UNIV_LIKELY_NULL(page_zip)) if (UNIV_LIKELY_NULL(page_zip))
{ {

View File

@@ -84,7 +84,7 @@ static const byte infimum_data[] = {
0x6d, 0x75, 0x6d, 0x00 /* "infimum\0" */ 0x6d, 0x75, 0x6d, 0x00 /* "infimum\0" */
}; };
/** Extra bytes and data bytes of a supremum record */ /** Extra bytes and data bytes of a supremum record */
static const byte supremum_extra_data[] = { static const byte supremum_extra_data alignas(4) [] = {
/* 0x0?, */ /* info_bits=0, n_owned=1..8 */ /* 0x0?, */ /* info_bits=0, n_owned=1..8 */
0x00, 0x0b, /* heap_no=1, status=3 */ 0x00, 0x0b, /* heap_no=1, status=3 */
0x00, 0x00, /* next=0 */ 0x00, 0x00, /* next=0 */
@@ -4573,8 +4573,7 @@ page_zip_dir_add_slot(
/* Move the uncompressed area backwards to make space /* Move the uncompressed area backwards to make space
for one directory slot. */ for one directory slot. */
memmove_aligned<2>(stored - PAGE_ZIP_DIR_SLOT_SIZE, stored, memmove(stored - PAGE_ZIP_DIR_SLOT_SIZE, stored, ulint(dir - stored));
ulint(dir - stored));
} }
/***********************************************************//** /***********************************************************//**

View File

@@ -2015,7 +2015,7 @@ clear_page_max_trx_id:
inline dberr_t PageConverter::update_header(buf_block_t* block) UNIV_NOTHROW inline dberr_t PageConverter::update_header(buf_block_t* block) UNIV_NOTHROW
{ {
byte *frame= get_frame(block); byte *frame= get_frame(block);
if (memcmp_aligned<4>(FIL_PAGE_SPACE_ID + frame, if (memcmp_aligned<2>(FIL_PAGE_SPACE_ID + frame,
FSP_HEADER_OFFSET + FSP_SPACE_ID + frame, 4)) FSP_HEADER_OFFSET + FSP_SPACE_ID + frame, 4))
ib::warn() << "Space id check in the header failed: ignored"; ib::warn() << "Space id check in the header failed: ignored";
else if (!mach_read_from_4(FIL_PAGE_SPACE_ID + frame)) else if (!mach_read_from_4(FIL_PAGE_SPACE_ID + frame))
@@ -2025,7 +2025,7 @@ inline dberr_t PageConverter::update_header(buf_block_t* block) UNIV_NOTHROW
/* Write space_id to the tablespace header, page 0. */ /* Write space_id to the tablespace header, page 0. */
mach_write_to_4(FIL_PAGE_SPACE_ID + frame, get_space_id()); mach_write_to_4(FIL_PAGE_SPACE_ID + frame, get_space_id());
memcpy_aligned<4>(FSP_HEADER_OFFSET + FSP_SPACE_ID + frame, memcpy_aligned<2>(FSP_HEADER_OFFSET + FSP_SPACE_ID + frame,
FIL_PAGE_SPACE_ID + frame, 4); FIL_PAGE_SPACE_ID + frame, 4);
/* Write back the adjusted flags. */ /* Write back the adjusted flags. */
mach_write_to_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + frame, m_space_flags); mach_write_to_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + frame, m_space_flags);

View File

@@ -619,7 +619,7 @@ err_exit:
uint32_t id= mach_read_from_4(FIL_PAGE_SPACE_ID + page); uint32_t id= mach_read_from_4(FIL_PAGE_SPACE_ID + page);
if (id == 0 || id >= SRV_SPACE_ID_UPPER_BOUND || if (id == 0 || id >= SRV_SPACE_ID_UPPER_BOUND ||
memcmp_aligned<4>(FIL_PAGE_SPACE_ID + page, memcmp_aligned<2>(FIL_PAGE_SPACE_ID + page,
FSP_HEADER_OFFSET + FSP_SPACE_ID + page, 4)) FSP_HEADER_OFFSET + FSP_SPACE_ID + page, 4))
{ {
ib::error() << "Inconsistent tablespace ID in file " << name; ib::error() << "Inconsistent tablespace ID in file " << name;