1diff --git a/CMakeLists.txt b/CMakeLists.txt 2index 4a4bbfa72fa..0478561e66c 100644 3--- a/CMakeLists.txt 4+++ b/CMakeLists.txt 5@@ -688,6 +688,7 @@ IF(WITH_JEMALLOC AND (WITH_TCMALLOC OR WITH_TCMALLOC_DEBUG)) 6 MESSAGE(FATAL_ERROR "Specify only *one* of WITH_TCMALLOC and WITH_JEMALLOC") 7 ENDIF() 8 9+OPTION(FUZZING "Fuzzing" OFF) 10 OPTION(ENABLED_PROFILING "Enable profiling" ON) 11 OPTION(WITHOUT_SERVER OFF) 12 13@@ -1804,6 +1805,10 @@ IF(NOT WITHOUT_SERVER AND WITH_UNIT_TESTS) 14 ENDIF() 15 ENDIF() 16 17+IF (FUZZING) 18+ ADD_SUBDIRECTORY(fuzz) 19+ENDIF() 20+ 21 # scripts/mysql_config depends on client and server targets loaded above. 22 # It is referenced by some of the directories below, so we insert it here. 23 ADD_SUBDIRECTORY(scripts) 24diff --git a/cmake/os/Linux.cmake b/cmake/os/Linux.cmake 25index 0e25e8eb..3ae74839 100644 26--- a/cmake/os/Linux.cmake 27+++ b/cmake/os/Linux.cmake 28@@ -103,7 +103,8 @@ IF(NOT WITH_ASAN AND 29 NOT WITH_LSAN AND 30 NOT WITH_MSAN AND 31 NOT WITH_TSAN AND 32- NOT WITH_UBSAN) 33+ NOT WITH_UBSAN AND 34+ NOT FUZZING) 35 SET(LINK_FLAG_NO_UNDEFINED "-Wl,--no-undefined") 36 SET(LINK_FLAG_Z_DEFS "-z,defs") 37 ENDIF() 38diff --git a/include/mysql.h b/include/mysql.h 39index 4700d74b853..bdf9b765ffb 100644 40--- a/include/mysql.h 41+++ b/include/mysql.h 42@@ -262,7 +262,8 @@ enum mysql_protocol_type { 43 MYSQL_PROTOCOL_TCP, 44 MYSQL_PROTOCOL_SOCKET, 45 MYSQL_PROTOCOL_PIPE, 46- MYSQL_PROTOCOL_MEMORY 47+ MYSQL_PROTOCOL_MEMORY, 48+ MYSQL_PROTOCOL_FUZZ 49 }; 50 51 enum mysql_ssl_mode { 52diff --git a/include/mysql.h.pp b/include/mysql.h.pp 53index 39ebd0fcb93..c041cc4690f 100644 54--- a/include/mysql.h.pp 55+++ b/include/mysql.h.pp 56@@ -486,7 +486,8 @@ enum mysql_protocol_type { 57 MYSQL_PROTOCOL_TCP, 58 MYSQL_PROTOCOL_SOCKET, 59 MYSQL_PROTOCOL_PIPE, 60- MYSQL_PROTOCOL_MEMORY 61+ MYSQL_PROTOCOL_MEMORY, 62+ MYSQL_PROTOCOL_FUZZ 63 }; 64 enum mysql_ssl_mode { 65 SSL_MODE_DISABLED = 1, 66diff --git a/include/violite.h b/include/violite.h 67index a6ccd1a607d..8dc0d46dd7f 100644 68--- a/include/violite.h 69+++ b/include/violite.h 70@@ -108,12 +108,14 @@ enum enum_vio_type : int { 71 */ 72 VIO_TYPE_PLUGIN = 7, 73 74+ VIO_TYPE_FUZZ = 8, 75+ 76 FIRST_VIO_TYPE = VIO_TYPE_TCPIP, 77 /* 78 If a new type is added, please update LAST_VIO_TYPE. In addition, please 79 change get_vio_type_name() in vio/vio.c to return correct name for it. 80 */ 81- LAST_VIO_TYPE = VIO_TYPE_PLUGIN 82+ LAST_VIO_TYPE = VIO_TYPE_FUZZ 83 }; 84 85 /** 86@@ -444,4 +446,20 @@ struct Vio { 87 88 #define SSL_handle SSL * 89 90+ 91+//Vio fuzzing 92+bool vio_connect_fuzz(MYSQL_VIO vio, struct sockaddr *addr, socklen_t len, 93+ int timeout); 94+int vio_socket_timeout_fuzz(Vio *vio, uint which, bool b); 95+void sock_initfuzz(const uint8_t *Data, size_t Size); 96+size_t vio_read_buff_fuzz(Vio *vio, uchar *buf, size_t size); 97+size_t vio_write_buff_fuzz(Vio *vio, const uchar *buf, size_t size); 98+bool vio_is_connected_fuzz(Vio *vio); 99+bool vio_was_timeout_fuzz(Vio *vio); 100+int vio_shutdown_fuzz(Vio *vio); 101+int vio_keepalive_fuzz(Vio *vio, bool set_keep_alive); 102+int vio_io_wait_fuzz(Vio *vio, enum enum_vio_io_event event, int timeout); 103+int vio_fastsend_fuzz(Vio *vio); 104+bool vio_should_retry_fuzz(Vio *vio); 105+ 106 #endif /* vio_violite_h_ */ 107diff --git a/libmysql/CMakeLists.txt b/libmysql/CMakeLists.txt 108index 334d1b7d3ef..c37c5ad930e 100644 109--- a/libmysql/CMakeLists.txt 110+++ b/libmysql/CMakeLists.txt 111@@ -345,11 +345,11 @@ IF(LINUX_STANDALONE AND KERBEROS_CUSTOM_LIBRARY) 112 ENDIF() 113 114 IF(UNIX) 115- IF(LINK_FLAG_Z_DEFS) 116+ IF(LINK_FLAG_Z_DEFS AND NOT FUZZING) 117 MY_TARGET_LINK_OPTIONS(libmysql "LINKER:${LINK_FLAG_Z_DEFS}") 118 ENDIF() 119 120- IF(LINUX) 121+ IF(LINUX AND NOT FUZZING) 122 CONFIGURE_FILE(libmysql.ver.in ${CMAKE_CURRENT_BINARY_DIR}/libmysql.ver) 123 MY_TARGET_LINK_OPTIONS(libmysql 124 "LINKER:--version-script=${CMAKE_CURRENT_BINARY_DIR}/libmysql.ver") 125diff --git a/mysys/my_rnd.cc b/mysys/my_rnd.cc 126index 2fc7820eaa3..248ea909db8 100644 127--- a/mysys/my_rnd.cc 128+++ b/mysys/my_rnd.cc 129@@ -48,6 +48,9 @@ 130 */ 131 132 double my_rnd(struct rand_struct *rand_st) { 133+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 134+ return 65.43; 135+#endif 136 rand_st->seed1 = (rand_st->seed1 * 3 + rand_st->seed2) % rand_st->max_value; 137 rand_st->seed2 = (rand_st->seed1 + rand_st->seed2 + 33) % rand_st->max_value; 138 return (((double)rand_st->seed1) / rand_st->max_value_dbl); 139@@ -64,6 +67,12 @@ Fill a buffer with random bytes using the SSL library routines 140 */ 141 int my_rand_buffer(unsigned char *buffer, size_t buffer_size) { 142 int rc; 143+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 144+ for (size_t i = 0; i < buffer_size; i++) 145+ buffer[i] = i; 146+ return 0; 147+#endif 148+ 149 rc = RAND_bytes(buffer, (int)buffer_size); 150 151 if (!rc) { 152@@ -85,6 +94,9 @@ int my_rand_buffer(unsigned char *buffer, size_t buffer_size) { 153 double my_rnd_ssl(bool *failed) { 154 unsigned int res; 155 156+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 157+ return 34.56; 158+#endif 159 if (my_rand_buffer((unsigned char *)&res, sizeof(res))) { 160 *failed = true; 161 return 0; 162diff --git a/sql-common/client.cc b/sql-common/client.cc 163index b8050f2b1a7..9a65178c5c4 100644 164--- a/sql-common/client.cc 165+++ b/sql-common/client.cc 166@@ -5892,6 +5892,12 @@ static mysql_state_machine_status csm_begin_connect(mysql_async_connect *ctx) { 167 } 168 } 169 #endif /* _WIN32 */ 170+if (!net->vio && 171+ (mysql->options.protocol == MYSQL_PROTOCOL_FUZZ)) { 172+ net->vio = 173+ vio_new(0, VIO_TYPE_FUZZ, 0); 174+ ctx->host_info = (char *)ER_CLIENT(CR_LOCALHOST_CONNECTION); 175+} 176 #if defined(HAVE_SYS_UN_H) 177 if (!net->vio && 178 (!mysql->options.protocol || 179diff --git a/sql/mysqld.cc b/sql/mysqld.cc 180index 50b76e2fa75..871006c2d8f 100644 181--- a/sql/mysqld.cc 182+++ b/sql/mysqld.cc 183@@ -6991,7 +6991,9 @@ int mysqld_main(int argc, char **argv) 184 185 keyring_lockable_init(); 186 187+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 188 my_init_signals(); 189+#endif 190 191 size_t guardize = 0; 192 #ifndef _WIN32 193@@ -7497,8 +7499,10 @@ int mysqld_main(int argc, char **argv) 194 unireg_abort(MYSQLD_ABORT_EXIT); 195 196 #ifndef _WIN32 197+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 198 // Start signal handler thread. 199 start_signal_handler(); 200+#endif 201 #endif 202 203 /* set all persistent options */ 204@@ -7543,8 +7547,9 @@ int mysqld_main(int argc, char **argv) 205 } 206 207 start_handle_manager(); 208- 209+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 210 create_compress_gtid_table_thread(); 211+#endif 212 213 LogEvent() 214 .type(LOG_TYPE_ERROR) 215@@ -7591,6 +7596,10 @@ int mysqld_main(int argc, char **argv) 216 217 (void)RUN_HOOK(server_state, before_handle_connection, (nullptr)); 218 219+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 220+ return 0; 221+#endif 222+ 223 #if defined(_WIN32) 224 if (mysqld_socket_acceptor != nullptr) 225 mysqld_socket_acceptor->check_and_spawn_admin_connection_handler_thread(); 226@@ -10500,6 +10509,9 @@ static int get_options(int *argc_ptr, char ***argv_ptr) { 227 228 if (opt_short_log_format) opt_specialflag |= SPECIAL_SHORT_LOG_FORMAT; 229 230+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 231+ Connection_handler_manager::thread_handling = Connection_handler_manager::SCHEDULER_NO_THREADS; 232+#endif 233 if (Connection_handler_manager::init()) { 234 LogErr(ERROR_LEVEL, ER_CONNECTION_HANDLING_OOM); 235 return 1; 236diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc 237index 7ecc10961ac..5f13f94eb02 100644 238--- a/storage/innobase/buf/buf0buf.cc 239+++ b/storage/innobase/buf/buf0buf.cc 240@@ -1476,18 +1476,14 @@ dberr_t buf_pool_init(ulint total_size, ulint n_instances) { 241 n = n_instances; 242 } 243 244- std::vector<std::thread> threads; 245- 246 std::mutex m; 247 248 for (ulint id = i; id < n; ++id) { 249- threads.emplace_back(std::thread(buf_pool_create, &buf_pool_ptr[id], size, 250- id, &m, std::ref(errs[id]))); 251+ buf_pool_create(&buf_pool_ptr[id], size, 252+ id, &m, std::ref(errs[id])); 253 } 254 255 for (ulint id = i; id < n; ++id) { 256- threads[id - i].join(); 257- 258 if (errs[id] != DB_SUCCESS) { 259 err = errs[id]; 260 } 261diff --git a/vio/CMakeLists.txt b/vio/CMakeLists.txt 262index 35ab5f17f15..9b39bfdbdbf 100644 263--- a/vio/CMakeLists.txt 264+++ b/vio/CMakeLists.txt 265@@ -27,6 +27,7 @@ SET(VIO_SOURCES 266 viosocket.cc 267 viossl.cc 268 viosslfactories.cc 269+ viofuzz.cc 270 ) 271 272 IF(WIN32) 273diff --git a/vio/vio.cc b/vio/vio.cc 274index 368c8d7b581..50c3231a8b0 100644 275--- a/vio/vio.cc 276+++ b/vio/vio.cc 277@@ -284,6 +284,26 @@ static bool vio_init(Vio *vio, enum enum_vio_type type, my_socket sd, 278 vio->is_blocking_flag = true; 279 break; 280 281+ case VIO_TYPE_FUZZ: 282+ vio->viodelete = vio_delete; 283+ vio->vioerrno = vio_errno; 284+ vio->read = vio_read_buff_fuzz; 285+ vio->write = vio_write_buff_fuzz; 286+ vio->fastsend = vio_fastsend_fuzz; 287+ vio->viokeepalive = vio_keepalive_fuzz; 288+ vio->should_retry = vio_should_retry_fuzz; 289+ vio->was_timeout = vio_was_timeout_fuzz; 290+ vio->vioshutdown = vio_shutdown_fuzz; 291+ vio->peer_addr = vio_peer_addr; 292+ vio->timeout = vio_socket_timeout_fuzz; 293+ vio->io_wait = vio_io_wait_fuzz; 294+ vio->is_connected = vio_is_connected_fuzz; 295+ vio->has_data = vio->read_buffer ? vio_buff_has_data : has_no_data; 296+ vio->is_blocking = vio_is_blocking; 297+ vio->set_blocking = vio_set_blocking; 298+ vio->set_blocking_flag = vio_set_blocking_flag; 299+ vio->is_blocking_flag = false; 300+ 301 default: 302 vio->viodelete = vio_delete; 303 vio->vioerrno = vio_errno; 304@@ -568,7 +588,8 @@ static const vio_string vio_type_names[] = {{"", 0}, 305 {STRING_WITH_LEN("SSL/TLS")}, 306 {STRING_WITH_LEN("Shared Memory")}, 307 {STRING_WITH_LEN("Internal")}, 308- {STRING_WITH_LEN("Plugin")}}; 309+ {STRING_WITH_LEN("Plugin")}, 310+ {STRING_WITH_LEN("Fuzz")}}; 311 312 void get_vio_type_name(enum enum_vio_type vio_type, const char **str, 313 int *len) { 314diff --git a/vio/viofuzz.cc b/vio/viofuzz.cc 315new file mode 100644 316index 00000000000..5b368d685cb 317--- /dev/null 318+++ b/vio/viofuzz.cc 319@@ -0,0 +1,124 @@ 320+ 321+#include "my_config.h" 322+ 323+#include <errno.h> 324+#include <fcntl.h> 325+#include <sys/types.h> 326+#include <time.h> 327+#ifndef _WIN32 328+#include <netdb.h> 329+#endif 330+#include <stdio.h> 331+#include <stdlib.h> 332+ 333+#include "my_compiler.h" 334+#include "my_dbug.h" 335+#include "my_inttypes.h" 336+#include "my_io.h" 337+#include "my_macros.h" 338+#include "vio/vio_priv.h" 339+ 340+#ifdef FIONREAD_IN_SYS_FILIO 341+#include <sys/filio.h> 342+#endif 343+#ifndef _WIN32 344+#include <netinet/tcp.h> 345+#endif 346+#ifdef HAVE_POLL_H 347+#include <poll.h> 348+#endif 349+#ifdef HAVE_SYS_IOCTL_H 350+#include <sys/ioctl.h> 351+#endif 352+ 353+static const uint8_t *fuzzBuffer; 354+static size_t fuzzSize; 355+static size_t fuzzPos; 356+ 357+ 358+void sock_initfuzz(const uint8_t *Data, size_t Size) { 359+ fuzzPos = 0; 360+ fuzzSize = Size; 361+ fuzzBuffer = Data; 362+} 363+ 364+bool vio_connect_fuzz(Vio *vio, struct sockaddr *addr, socklen_t len, 365+ int timeout) { 366+ DBUG_ENTER("vio_socket_connect"); 367+ 368+ /* Only for socket-based transport types. */ 369+ //DBUG_ASSERT(vio->type == VIO_TYPE_SOCKET || vio->type == VIO_TYPE_TCPIP); 370+ 371+ /* Initiate the connection. */ 372+ return 0; 373+} 374+ 375+ 376+int vio_socket_timeout_fuzz(Vio *vio, uint which, bool b) { 377+ DBUG_ENTER("vio_socket_timeout_fuzz\n"); 378+ return 0; 379+} 380+ 381+ 382+size_t vio_read_buff_fuzz(Vio *vio, uchar *bufp, size_t size) { 383+ DBUG_ENTER("vio_read_buff_fuzz.\n"); 384+ if (size > fuzzSize - fuzzPos) { 385+ size = fuzzSize - fuzzPos; 386+ } 387+ if (fuzzPos < fuzzSize) { 388+ memcpy(bufp, fuzzBuffer + fuzzPos, size); 389+ } 390+ fuzzPos += size; 391+#ifdef FUZZ_DEBUG 392+ printf("net cli %zu ", size); 393+ for (size_t i=0; i<size; i++) 394+ printf("%02x ", bufp[i]); 395+ printf("\n"); 396+#endif //FUZZ_DEBUG 397+ return size; 398+} 399+ 400+size_t vio_write_buff_fuzz(Vio *vio, const uchar *bufp, size_t size) { 401+ DBUG_ENTER("vio_write_buff_fuzz\n"); 402+#ifdef FUZZ_DEBUG 403+ printf("net srv %zu ", size); 404+ for (size_t i=0; i<size; i++) 405+ printf("%02x ", bufp[i]); 406+ printf("\n"); 407+#endif //FUZZ_DEBUG 408+ return size; 409+} 410+ 411+bool vio_is_connected_fuzz(Vio *vio) { 412+ DBUG_ENTER("vio_is_connected_fuzz\n"); 413+ return (fuzzPos < fuzzSize); 414+} 415+ 416+bool vio_was_timeout_fuzz(Vio *vio) { 417+ DBUG_ENTER("vio_was_timeout_fuzz\n"); 418+ return false; 419+} 420+ 421+int vio_shutdown_fuzz(Vio *vio) { 422+ DBUG_ENTER("vio_shutdown_fuzz"); 423+ return 0; 424+} 425+ 426+int vio_keepalive_fuzz(Vio *vio, bool set_keep_alive) { 427+ DBUG_ENTER("vio_keepalive_fuzz\n"); 428+ return 0; 429+} 430+int vio_io_wait_fuzz(Vio *vio, enum enum_vio_io_event event, int timeout) { 431+ DBUG_ENTER("vio_io_wait_fuzz"); 432+ return 1; 433+} 434+ 435+int vio_fastsend_fuzz(Vio *vio) { 436+ DBUG_ENTER("vio_fastsend_fuzz\n"); 437+ return 0; 438+} 439+ 440+bool vio_should_retry_fuzz(Vio *vio) { 441+ DBUG_ENTER("vio_should_retry_fuzz\n"); 442+ return (fuzzPos < fuzzSize); 443+} 444