summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2020-11-11 16:49:29 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2020-11-11 16:49:29 +0200
commit59fe22d01c55c09e391454953f3331b3880c7a3e (patch)
tree10de7d2062124949a8b9d14c02cde6e9c590903f
parente9b3d44c6eef3d7b4944d724ba597035798324ad (diff)
downloadmariadb-git-bb-10.5-MDEV-24196.tar.gz
MDEV-24196 WITH_UBSAN: member call on null pointer of log_phys_tbb-10.5-MDEV-24196
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.
-rw-r--r--storage/innobase/log/log0recv.cc37
1 files changed, 26 insertions, 11 deletions
diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index c5cf21bf59a..fe691a4b256 100644
--- a/storage/innobase/log/log0recv.cc
+++ b/storage/innobase/log/log0recv.cc
@@ -96,13 +96,22 @@ struct log_phys_t : public log_rec_t
/** start LSN of the mini-transaction (not necessarily of this record) */
const lsn_t start_lsn;
private:
- /** length of the record, in bytes */
- uint16_t len;
+ /** @return the start of length and data */
+ 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 */
- byte *begin() { return reinterpret_cast<byte*>(&len + 1); }
+ byte *begin() { return start() + 2; }
/** @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:
/** @return start of the log records */
const byte *begin() const { return const_cast<log_phys_t*>(this)->begin(); }
@@ -112,11 +121,7 @@ public:
/** Determine the allocated size of the object.
@param len length of recs, excluding terminating NUL byte
@return the total allocation size */
- static size_t alloc_size(size_t len)
- {
- return len + 1 +
- reinterpret_cast<size_t>(reinterpret_cast<log_phys_t*>(0)->begin());
- }
+ static inline size_t alloc_size(size_t len);
/** Constructor.
@param start_lsn start LSN of the mini-transaction
@@ -124,11 +129,13 @@ public:
@param recs the first log record for the page in the mini-transaction
@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_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 < lsn);
+ const uint16_t len= static_cast<uint16_t>(size);
ut_ad(len == size);
+ memcpy(start(), &len, 2);
reinterpret_cast<byte*>(memcpy(begin(), recs, size))[size]= 0;
}
@@ -138,8 +145,10 @@ public:
void append(const byte *recs, size_t size)
{
ut_ad(start_lsn < lsn);
+ uint16_t l= len();
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.
@@ -514,6 +523,12 @@ page_corrupted:
};
+inline size_t log_phys_t::alloc_size(size_t len)
+{
+ return len + (1 + 2 + sizeof(log_phys_t));
+}
+
+
/** Tablespace item during recovery */
struct file_name_t {
/** Tablespace file name (FILE_MODIFY) */