[MDEV-20923] UBSAN: member access within address … which does not point to an object of type 'xid_count_per_binlog' Created: 2019-10-30  Updated: 2020-02-04  Resolved: 2020-01-29

Status: Closed
Project: MariaDB Server
Component/s: Replication
Affects Version/s: 10.1, 10.2, 10.3, 10.4, 10.5
Fix Version/s: 10.1.45, 10.2.32, 10.3.23, 10.4.13

Type: Bug Priority: Major
Reporter: Marko Mäkelä Assignee: Sujatha Sivakumar (Inactive)
Resolution: Fixed Votes: 0
Labels: undefined

Issue Links:
Blocks
Duplicate
is duplicated by MDEV-21521 UBSan crashes in MYSQL_BIN_LOG::open Closed
Relates
relates to MDEV-20778 UBSAN: call to function free_rpl_filt... Closed

 Description   

For some reason, I am only seeing this reported for 10.4 and 10.5, not for earlier versions.
To repeat (I used GCC 9.2.1; clang’s UBSAN would not even bootstrap):

mkdir build; cd build
cmake -DCONC_WITH_{UNITTEST,SSL}=OFF -DWITH_EMBEDDED_SERVER=OFF -DWITH_UNIT_TESTS=OFF -DCMAKE_BUILD_TYPE=Debug -DPLUGIN_{ARCHIVE,TOKUDB,MROONGA,OQGRAPH,ROCKSDB,CONNECT,SPIDER}=NO -DWITH_SAFEMALLOC=OFF -DWITH_{SSL,ZLIB}=system "$@" -DCMAKE_C{,XX}_FLAGS='-O2 -march=native' -DWITH_UBSAN=ON ..
make -j$(nproc)
cd mysql-test
nice ./mtr --parallel=$(($(nproc) * 3 / 2)) --force --retry=0 --max-test-fail=0 --big-test
grep 'log.*runtime error' var/*/log/mysqld*err*|cut -d: -f2-|sed -e 's/0x[0-9a-fA-F]*/0xXXX/'|sort|uniq -c|sort -nr

The top of the output looks like this:

10.4 576c96a9385f20cf4b6fe685e079dcf8026c3a24

   1740 /mariadb/10.4/sql/log.cc:3812:25: runtime error: member access within address 0xXXX which does not point to an object of type 'xid_count_per_binlog'
   1740 /mariadb/10.4/sql/log.cc:3714:41: runtime error: member access within address 0xXXX which does not point to an object of type 'xid_count_per_binlog'
   1740 /mariadb/10.4/sql/log.cc:3694:29: runtime error: member access within address 0xXXX which does not point to an object of type 'xid_count_per_binlog'

For some reason, not all such access is flagged. Here is a sample around line 3694:

        if (!(new_xid_list_entry = (xid_count_per_binlog *)
              my_multi_malloc(MYF(MY_WME),
                              &entry_mem, sizeof(xid_count_per_binlog),
                              &name_mem, len,
                              NULL)))
          goto err;
        memcpy(name_mem, log_file_name+off, len);
        new_xid_list_entry->binlog_name= name_mem;
        new_xid_list_entry->binlog_name_len= (int)len;
        new_xid_list_entry->xid_count= 0;
        new_xid_list_entry->notify_count= 0;

The problem appears to be that no constructor for xid_count_per_binlog is being called, and thus the vtable will not be initialized. It looks like there is no constructor at all provided for xid_count_per_binlog, even though it is a derived class:

  struct xid_count_per_binlog : public ilink {
    xid_count_per_binlog();   /* Give link error if constructor used. */
  };

A definition of MYSQL_BIN_LOG::xid_count_per_binlog::xid_count_per_binlog() is nowhere to be seen. Side note: starting with 10.4, we could use the standard C++11 way to omit default member functions:

    xid_count_per_binlog() = delete;

Here is an attempted patch, which fails to compile due to missing constructor:

diff --git a/sql/log.cc b/sql/log.cc
index 7f632b43cb6..9a5081ab94a 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -3684,13 +3684,13 @@ bool MYSQL_BIN_LOG::open(const char *log_name,
         size_t off= dirname_length(log_file_name);
         size_t len= strlen(log_file_name) - off;
         char *entry_mem, *name_mem;
-        if (!(new_xid_list_entry = (xid_count_per_binlog *)
-              my_multi_malloc(MYF(MY_WME),
-                              &entry_mem, sizeof(xid_count_per_binlog),
-                              &name_mem, len,
-                              NULL)))
+        if (!my_multi_malloc(MYF(MY_WME),
+                             &entry_mem, sizeof(xid_count_per_binlog),
+                             &name_mem, len,
+                             NULL)))
           goto err;
         memcpy(name_mem, log_file_name+off, len);
+        new_xid_list_entry = new (entry_mem) xid_count_per_binlog();
         new_xid_list_entry->binlog_name= name_mem;
         new_xid_list_entry->binlog_name_len= (int)len;
         new_xid_list_entry->xid_count= 0;

(Note: my_multi_malloc() would return entry_mem.)

I do not know why I am not seeing any UBSAN errors reported for sql/log.cc in 10.2 or 10.3. It does not look like the code has changed. So, the affectedVersion and fixVersion may need to be revised.



 Comments   
Comment by Marko Mäkelä [ 2019-10-30 ]

All of these are possibly related:

grep 'sql_list.*runtime error' var/*/log/mysqld*err*|
cut -d: -f2,5-|
sed -e 's/0x[0-9a-fA-F]*/0xXXX/'|sort|uniq -c|sort -nr

10.4 576c96a9385f20cf4b6fe685e079dcf8026c3a24

   6329 /mariadb/10.4/sql/sql_list.h: runtime error: downcast of address 0xXXX which does not point to an object of type 'xid_count_per_binlog'
   3261 /mariadb/10.4/sql/sql_list.h: runtime error: member call on address 0xXXX which does not point to an object of type 'ilink'
   2009 /mariadb/10.4/sql/sql_list.h: runtime error: member access within address 0xXXX which does not point to an object of type 'ilink'

Comment by Sujatha Sivakumar (Inactive) [ 2019-11-12 ]

Hello Andrei,

Can you please review the changes for MDEV-20923.

Patch: https://github.com/MariaDB/server/commit/f72427f463d316a54ebf87c2e84c73947e3c5fe4

Build Bot testing: http://buildbot.askmonty.org/buildbot/grid?category=main&branch=bb-10.1-sujatha

Thank you.

Comment by Andrei Elkin [ 2019-11-27 ]

Sent my comments, cc-d to KN.

Comment by Marko Mäkelä [ 2020-01-23 ]

The duplicate report MDEV-21521 mentions that this is repeatable on 10.1 already, so I think we have no other option than to fix it there.

Comment by Sujatha Sivakumar (Inactive) [ 2020-01-29 ]

Fix is implemented in 10.1.45.

Generated at Thu Feb 08 09:03:15 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.