Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-20923

UBSAN: member access within address … which does not point to an object of type 'xid_count_per_binlog'

    XMLWordPrintable

    Details

      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.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              sujatha.sivakumar Sujatha Sivakumar
              Reporter:
              marko Marko Mäkelä
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: