fixes for UBSAN warnings (#4223)

Problem: UBSAN shows warnings

Solution: fix alignment issues and signed to unsigned conversion
This commit is contained in:
Bill Torpey
2021-06-29 08:02:35 -04:00
committed by GitHub
parent fb9fb00eda
commit ca8e30ed48
5 changed files with 17 additions and 14 deletions

View File

@@ -70,7 +70,7 @@ endif()
option(ENABLE_UBSAN "Build with undefined behavior sanitizer" OFF) option(ENABLE_UBSAN "Build with undefined behavior sanitizer" OFF)
if(ENABLE_UBSAN) if(ENABLE_UBSAN)
message(STATUS "Instrumenting with Undefined Behavior Sanitizer") message(STATUS "Instrumenting with Undefined Behavior Sanitizer")
set(CMAKE_BUILD_TYPE "RelWithDebInfo") set(CMAKE_BUILD_TYPE "Debug")
set(UBSAN_FLAGS "${UBSAN_FLAGS} -fno-omit-frame-pointer") set(UBSAN_FLAGS "${UBSAN_FLAGS} -fno-omit-frame-pointer")
set(UBSAN_FLAGS "${UBSAN_FLAGS} -fsanitize=undefined") set(UBSAN_FLAGS "${UBSAN_FLAGS} -fsanitize=undefined")
set(UBSAN_FLAGS "${UBSAN_FLAGS} -fsanitize=implicit-conversion") set(UBSAN_FLAGS "${UBSAN_FLAGS} -fsanitize=implicit-conversion")
@@ -464,6 +464,7 @@ message(STATUS "Using polling method in zmq_poll(er)_* API: ${API_POLLER}")
string(TOUPPER ${API_POLLER} UPPER_API_POLLER) string(TOUPPER ${API_POLLER} UPPER_API_POLLER)
set(ZMQ_POLL_BASED_ON_${UPPER_API_POLLER} 1) set(ZMQ_POLL_BASED_ON_${UPPER_API_POLLER} 1)
# special alignment settings
execute_process( execute_process(
COMMAND getconf LEVEL1_DCACHE_LINESIZE COMMAND getconf LEVEL1_DCACHE_LINESIZE
OUTPUT_VARIABLE CACHELINE_SIZE OUTPUT_VARIABLE CACHELINE_SIZE
@@ -476,6 +477,7 @@ else()
set(ZMQ_CACHELINE_SIZE ${CACHELINE_SIZE}) set(ZMQ_CACHELINE_SIZE ${CACHELINE_SIZE})
endif() endif()
message(STATUS "Using ${ZMQ_CACHELINE_SIZE} bytes alignment for lock-free data structures") message(STATUS "Using ${ZMQ_CACHELINE_SIZE} bytes alignment for lock-free data structures")
check_cxx_symbol_exists(posix_memalign stdlib.h HAVE_POSIX_MEMALIGN)
if(NOT CYGWIN) if(NOT CYGWIN)
# TODO cannot we simply do 'if(WIN32) set(ZMQ_HAVE_WINDOWS ON)' or similar? # TODO cannot we simply do 'if(WIN32) set(ZMQ_HAVE_WINDOWS ON)' or similar?
@@ -1366,7 +1368,7 @@ else()
add_library(libzmq SHARED $<TARGET_OBJECTS:objects> ${public_headers} ${html-docs} ${readme-docs} add_library(libzmq SHARED $<TARGET_OBJECTS:objects> ${public_headers} ${html-docs} ${readme-docs}
${zmq-pkgconfig} ${CMAKE_CURRENT_BINARY_DIR}/version.rc) ${zmq-pkgconfig} ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
endif() endif()
endif() endif()
# NOTE: the SOVERSION and VERSION MUST be the same as the one generated by libtool! It is NOT the same as the # NOTE: the SOVERSION and VERSION MUST be the same as the one generated by libtool! It is NOT the same as the
# version of the package. # version of the package.

View File

@@ -16,6 +16,7 @@
#cmakedefine ZMQ_POLL_BASED_ON_SELECT #cmakedefine ZMQ_POLL_BASED_ON_SELECT
#cmakedefine ZMQ_POLL_BASED_ON_POLL #cmakedefine ZMQ_POLL_BASED_ON_POLL
#cmakedefine HAVE_POSIX_MEMALIGN @HAVE_POSIX_MEMALIGN@
#cmakedefine ZMQ_CACHELINE_SIZE @ZMQ_CACHELINE_SIZE@ #cmakedefine ZMQ_CACHELINE_SIZE @ZMQ_CACHELINE_SIZE@
#cmakedefine ZMQ_FORCE_MUTEXES #cmakedefine ZMQ_FORCE_MUTEXES

View File

@@ -33,6 +33,7 @@
#include <string> #include <string>
#include "stdint.hpp" #include "stdint.hpp"
#include "endpoint.hpp" #include "endpoint.hpp"
#include "platform.hpp"
namespace zmq namespace zmq
{ {
@@ -44,12 +45,7 @@ class socket_base_t;
// This structure defines the commands that can be sent between threads. // This structure defines the commands that can be sent between threads.
#ifdef _MSC_VER struct command_t
#pragma warning(push)
#pragma warning(disable : 4324) // C4324: alignment padding warnings
__declspec(align (64))
#endif
struct command_t
{ {
// Object to process the command. // Object to process the command.
zmq::object_t *destination; zmq::object_t *destination;
@@ -216,9 +212,12 @@ __declspec(align (64))
} args; } args;
#ifdef _MSC_VER #ifdef _MSC_VER
}; };
#pragma warning(pop)
#else #else
} __attribute__ ((aligned (64))); }
#ifdef HAVE_POSIX_MEMALIGN
__attribute__ ((aligned (ZMQ_CACHELINE_SIZE)))
#endif
;
#endif #endif
} }

View File

@@ -131,7 +131,7 @@ void zmq::epoll_t::reset_pollin (handle_t handle_)
{ {
check_thread (); check_thread ();
poll_entry_t *pe = static_cast<poll_entry_t *> (handle_); poll_entry_t *pe = static_cast<poll_entry_t *> (handle_);
pe->ev.events &= ~(static_cast<short> (EPOLLIN)); pe->ev.events &= ~(static_cast<uint32_t> (EPOLLIN));
const int rc = epoll_ctl (_epoll_fd, EPOLL_CTL_MOD, pe->fd, &pe->ev); const int rc = epoll_ctl (_epoll_fd, EPOLL_CTL_MOD, pe->fd, &pe->ev);
errno_assert (rc != -1); errno_assert (rc != -1);
} }
@@ -149,7 +149,7 @@ void zmq::epoll_t::reset_pollout (handle_t handle_)
{ {
check_thread (); check_thread ();
poll_entry_t *pe = static_cast<poll_entry_t *> (handle_); poll_entry_t *pe = static_cast<poll_entry_t *> (handle_);
pe->ev.events &= ~(static_cast<short> (EPOLLOUT)); pe->ev.events &= ~(static_cast<uint32_t> (EPOLLOUT));
const int rc = epoll_ctl (_epoll_fd, EPOLL_CTL_MOD, pe->fd, &pe->ev); const int rc = epoll_ctl (_epoll_fd, EPOLL_CTL_MOD, pe->fd, &pe->ev);
errno_assert (rc != -1); errno_assert (rc != -1);
} }

5
src/yqueue.hpp Normal file → Executable file
View File

@@ -35,6 +35,7 @@
#include "err.hpp" #include "err.hpp"
#include "atomic_ptr.hpp" #include "atomic_ptr.hpp"
#include "platform.hpp"
namespace zmq namespace zmq
{ {
@@ -50,7 +51,7 @@ namespace zmq
// T is the type of the object in the queue. // T is the type of the object in the queue.
// N is granularity of the queue (how many pushes have to be done till // N is granularity of the queue (how many pushes have to be done till
// actual memory allocation is required). // actual memory allocation is required).
#ifdef HAVE_POSIX_MEMALIGN #if defined HAVE_POSIX_MEMALIGN
// ALIGN is the memory alignment size to use in the case where we have // ALIGN is the memory alignment size to use in the case where we have
// posix_memalign available. Default value is 64, this alignment will // posix_memalign available. Default value is 64, this alignment will
// prevent two queue chunks from occupying the same CPU cache line on // prevent two queue chunks from occupying the same CPU cache line on
@@ -181,7 +182,7 @@ template <typename T, int N> class yqueue_t
static inline chunk_t *allocate_chunk () static inline chunk_t *allocate_chunk ()
{ {
#ifdef HAVE_POSIX_MEMALIGN #if defined HAVE_POSIX_MEMALIGN
void *pv; void *pv;
if (posix_memalign (&pv, ALIGN, sizeof (chunk_t)) == 0) if (posix_memalign (&pv, ALIGN, sizeof (chunk_t)) == 0)
return (chunk_t *) pv; return (chunk_t *) pv;