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