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

UBSAN runtime error: call to function crc32c_3way through pointer to incorrect function type

Details

    Description

      Running UBSAN-built server MTR tests, eg.

      UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=0 ./mysql-test/mtr binlog.binlog_show_binlog_events_invalid_offset_silent
      

      can produce

      ./server/mysys/crc32/crc32c.cc:531:10: runtime error: call to function crc32c_3way through pointer to incorrect function type 'unsigned int (*)(unsigned int, const void *, unsigned long)'
      ./server/mysys/crc32/crc32c_amd64.cc:188: note: crc32c_3way defined here
          #0 0x555b61a5362e in my_crc32c ./server/mysys/crc32/crc32c.cc:531:10
          #1 0x555b60cd4b96 in ut_crc32(unsigned char const*, unsigned long) ./server/storage/innobase/include/ut0crc32.h:34:10
          #2 0x555b60cd9941 in log_block_calc_checksum_crc32(unsigned char const*) ./server/storage/innobase/include/log0log.inl:196:9
          #3 0x555b60cce9b4 in log_block_store_checksum(unsigned char*) ./server/storage/innobase/log/log0log.cc:488:33
          #4 0x555b60cce5ca in log_t::file::write_header_durable(unsigned long) ./server/storage/innobase/log/log0log.cc:508:3
          #5 0x555b610a273a in create_log_file(bool, unsigned long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>&) ./server/storage/innobase/srv/srv0start.cc:325:14
          #6 0x555b6109bd9f in srv_start(bool) ./server/storage/innobase/srv/srv0start.cc:1331:9
          #7 0x555b60a7a7ad in innodb_init(void*) ./server/storage/innobase/handler/ha_innodb.cc:4059:8
          #8 0x555b5f5dbde7 in ha_initialize_handlerton(st_plugin_int*) ./server/sql/handler.cc:651:37
          #9 0x555b5e46e045 in plugin_do_initialize(st_plugin_int*, unsigned int&) ./server/sql/sql_plugin.cc:1451:18
          #10 0x555b5e46d0a8 in plugin_initialize(st_mem_root*, st_plugin_int*, int*, char**, bool) ./server/sql/sql_plugin.cc:1504:10
          #11 0x555b5e46bd35 in plugin_init(int*, char**, int) ./server/sql/sql_plugin.cc:1761:18
          #12 0x555b5dd75164 in init_server_components() ./server/sql/mysqld.cc:4975:7
          #13 0x555b5dd6e8a1 in mysqld_main(int, char**) ./server/sql/mysqld.cc:5566:7
          #14 0x555b5dd647a9 in main ./server/sql/main.cc:25:10
          #15 0x7f50f7029d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
          #16 0x7f50f7029e3f in __libc_start_main csu/../csu/libc-start.c:392:3
          #17 0x555b5dd3b5b4 in _start (./server/build105_ubsan/sql/mariadbd+0x3b175b4) (BuildId: 2dd1b28fa609bdad67a5080e4548b43d6a0f9390)
       
      SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior ./server/mysys/crc32/crc32c.cc:531:10 in  
      
      

      Attachments

        Issue Links

          Activity

            Hi Marko!

            This is ready for review: PR-3312

            bnestere Brandon Nesterenko added a comment - Hi Marko! This is ready for review: PR-3312

            Thank you, Brandon! You forgot to mention that only clang -fsanitize=undefined reports such function pointer signature mismatch; GCC’s sanitizer won’t.

            By applying the following patch, I was hoping to identify another function pointer signature mismatch:

            diff --git a/storage/innobase/include/ut0crc32.h b/storage/innobase/include/ut0crc32.h
            index 0cbccb976e2..33c0b3e5af7 100644
            --- a/storage/innobase/include/ut0crc32.h
            +++ b/storage/innobase/include/ut0crc32.h
            @@ -31,7 +31,7 @@ Created Aug 10, 2011 Vasil Dimov
             #include <my_sys.h>
             static inline uint32_t ut_crc32(const byte *s, size_t size)
             {
            -  return my_crc32c(0, s, size);
            +  return my_checksum(0, s, size);
             }
             
             #endif /* ut0crc32_h */
            

            Alas, no error was flagged for the crc32_pclmul invocation. That function would be invoked already on the server bootstrap by create_control_file() in ENGINE=Aria initialization. It seems that unsigned, uint32 and uint32_t are being treated as equal. The mismatch would have been issued because of a mismatch between const char* and const void*.

            The minimal test for reproducing this would seem to be:

            ./mtr main.1st
            

            The minimal ‘fix’ would seem to be the first line of the following:

            diff --git a/mysys/crc32/crc32c_amd64.cc b/mysys/crc32/crc32c_amd64.cc
            index 147c0ccaba6..6706ed0fadc 100644
            --- a/mysys/crc32/crc32c_amd64.cc
            +++ b/mysys/crc32/crc32c_amd64.cc
            @@ -184,9 +184,9 @@ static inline uint64_t CombineCRC(
             // Compute CRC-32C using the Intel hardware instruction.
             extern "C"
             USE_PCLMUL
            -uint32_t crc32c_3way(uint32_t crc, const char *buf, size_t len)
            +uint32_t crc32c_3way(uint32_t crc, const void *buf, size_t len)
             {
            -  const unsigned char* next = (const unsigned char*)buf;
            +  const unsigned char* next = static_cast<const unsigned char*>(buf);
               uint64_t count;
               uint64_t crc0, crc1, crc2;
               crc0 = crc ^ 0xffffffffu;
            

            I updated the pull request with my suggested version of the fix, which also makes some additional effort to unify the 32-bit CRC parameters and return values.

            marko Marko Mäkelä added a comment - Thank you, Brandon! You forgot to mention that only clang -fsanitize=undefined reports such function pointer signature mismatch; GCC’s sanitizer won’t. By applying the following patch, I was hoping to identify another function pointer signature mismatch: diff --git a/storage/innobase/include/ut0crc32.h b/storage/innobase/include/ut0crc32.h index 0cbccb976e2..33c0b3e5af7 100644 --- a/storage/innobase/include/ut0crc32.h +++ b/storage/innobase/include/ut0crc32.h @@ -31,7 +31,7 @@ Created Aug 10, 2011 Vasil Dimov #include <my_sys.h> static inline uint32_t ut_crc32(const byte *s, size_t size) { - return my_crc32c(0, s, size); + return my_checksum(0, s, size); } #endif /* ut0crc32_h */ Alas, no error was flagged for the crc32_pclmul invocation. That function would be invoked already on the server bootstrap by create_control_file() in ENGINE=Aria initialization. It seems that unsigned , uint32 and uint32_t are being treated as equal. The mismatch would have been issued because of a mismatch between const char* and const void* . The minimal test for reproducing this would seem to be: ./mtr main.1st The minimal ‘fix’ would seem to be the first line of the following: diff --git a/mysys/crc32/crc32c_amd64.cc b/mysys/crc32/crc32c_amd64.cc index 147c0ccaba6..6706ed0fadc 100644 --- a/mysys/crc32/crc32c_amd64.cc +++ b/mysys/crc32/crc32c_amd64.cc @@ -184,9 +184,9 @@ static inline uint64_t CombineCRC( // Compute CRC-32C using the Intel hardware instruction. extern "C" USE_PCLMUL -uint32_t crc32c_3way(uint32_t crc, const char *buf, size_t len) +uint32_t crc32c_3way(uint32_t crc, const void *buf, size_t len) { - const unsigned char* next = (const unsigned char*)buf; + const unsigned char* next = static_cast<const unsigned char*>(buf); uint64_t count; uint64_t crc0, crc1, crc2; crc0 = crc ^ 0xffffffffu; I updated the pull request with my suggested version of the fix, which also makes some additional effort to unify the 32-bit CRC parameters and return values.

            People

              marko Marko Mäkelä
              bnestere Brandon Nesterenko
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.