Commit 97569d3c authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-24196 WITH_UBSAN: member call on null pointer of log_phys_t

MDEV-12353 deliberately tries to avoid memory alignment overhead in
log_phys_t, storing the stream of log records bytes straight after
a header object. But, offsetof() is not allowed on C++ data objects,
and neither are attempts to emulate it by invoking a member function
on a null pointer.

log_phys_t::len: Remove. Make it part of the byte stream that
immediately follow the object. Thanks to Eugene Kosov for this idea.

log_phys_t::start(): The start address of the following byte stream.

log_phys_t::len(): Compute len.

log_phys_t::alloc_size(): Use a simple sizeof calculation.
parent b4a5ad8d
...@@ -96,13 +96,22 @@ struct log_phys_t : public log_rec_t ...@@ -96,13 +96,22 @@ struct log_phys_t : public log_rec_t
/** start LSN of the mini-transaction (not necessarily of this record) */ /** start LSN of the mini-transaction (not necessarily of this record) */
const lsn_t start_lsn; const lsn_t start_lsn;
private: private:
/** length of the record, in bytes */ /** @return the start of length and data */
uint16_t len; const byte *start() const
{
return my_assume_aligned<sizeof(size_t)>
(reinterpret_cast<const byte*>(&start_lsn + 1));
}
/** @return the start of length and data */
byte *start()
{ return const_cast<byte*>(const_cast<const log_phys_t*>(this)->start()); }
/** @return the length of the following record */
uint16_t len() const { uint16_t i; memcpy(&i, start(), 2); return i; }
/** @return start of the log records */ /** @return start of the log records */
byte *begin() { return reinterpret_cast<byte*>(&len + 1); } byte *begin() { return start() + 2; }
/** @return end of the log records */ /** @return end of the log records */
byte *end() { byte *e= begin() + len; ut_ad(!*e); return e; } byte *end() { byte *e= begin() + len(); ut_ad(!*e); return e; }
public: public:
/** @return start of the log records */ /** @return start of the log records */
const byte *begin() const { return const_cast<log_phys_t*>(this)->begin(); } const byte *begin() const { return const_cast<log_phys_t*>(this)->begin(); }
...@@ -112,11 +121,7 @@ struct log_phys_t : public log_rec_t ...@@ -112,11 +121,7 @@ struct log_phys_t : public log_rec_t
/** Determine the allocated size of the object. /** Determine the allocated size of the object.
@param len length of recs, excluding terminating NUL byte @param len length of recs, excluding terminating NUL byte
@return the total allocation size */ @return the total allocation size */
static size_t alloc_size(size_t len) static inline size_t alloc_size(size_t len);
{
return len + 1 +
reinterpret_cast<size_t>(reinterpret_cast<log_phys_t*>(0)->begin());
}
/** Constructor. /** Constructor.
@param start_lsn start LSN of the mini-transaction @param start_lsn start LSN of the mini-transaction
...@@ -124,11 +129,13 @@ struct log_phys_t : public log_rec_t ...@@ -124,11 +129,13 @@ struct log_phys_t : public log_rec_t
@param recs the first log record for the page in the mini-transaction @param recs the first log record for the page in the mini-transaction
@param size length of recs, in bytes, excluding terminating NUL byte */ @param size length of recs, in bytes, excluding terminating NUL byte */
log_phys_t(lsn_t start_lsn, lsn_t lsn, const byte *recs, size_t size) : log_phys_t(lsn_t start_lsn, lsn_t lsn, const byte *recs, size_t size) :
log_rec_t(lsn), start_lsn(start_lsn), len(static_cast<uint16_t>(size)) log_rec_t(lsn), start_lsn(start_lsn)
{ {
ut_ad(start_lsn); ut_ad(start_lsn);
ut_ad(start_lsn < lsn); ut_ad(start_lsn < lsn);
const uint16_t len= static_cast<uint16_t>(size);
ut_ad(len == size); ut_ad(len == size);
memcpy(start(), &len, 2);
reinterpret_cast<byte*>(memcpy(begin(), recs, size))[size]= 0; reinterpret_cast<byte*>(memcpy(begin(), recs, size))[size]= 0;
} }
...@@ -138,8 +145,10 @@ struct log_phys_t : public log_rec_t ...@@ -138,8 +145,10 @@ struct log_phys_t : public log_rec_t
void append(const byte *recs, size_t size) void append(const byte *recs, size_t size)
{ {
ut_ad(start_lsn < lsn); ut_ad(start_lsn < lsn);
uint16_t l= len();
reinterpret_cast<byte*>(memcpy(end(), recs, size))[size]= 0; reinterpret_cast<byte*>(memcpy(end(), recs, size))[size]= 0;
len= static_cast<uint16_t>(len + size); l= static_cast<uint16_t>(l + size);
memcpy(start(), &l, 2);
} }
/** Apply an UNDO_APPEND record. /** Apply an UNDO_APPEND record.
...@@ -514,6 +523,12 @@ struct log_phys_t : public log_rec_t ...@@ -514,6 +523,12 @@ struct log_phys_t : public log_rec_t
}; };
inline size_t log_phys_t::alloc_size(size_t len)
{
return len + (1 + 2 + sizeof(log_phys_t));
}
/** Tablespace item during recovery */ /** Tablespace item during recovery */
struct file_name_t { struct file_name_t {
/** Tablespace file name (FILE_MODIFY) */ /** Tablespace file name (FILE_MODIFY) */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment