1diff --git a/CMakeLists.txt b/CMakeLists.txt 2index ce1d1bb05b5..d1d0b04f202 100644 3--- a/CMakeLists.txt 4+++ b/CMakeLists.txt 5@@ -528,6 +528,7 @@ IF(WITH_JEMALLOC) 6 STRING_APPEND(CMAKE_CXX_FLAGS " -fno-builtin-realloc -fno-builtin-free") 7 ENDIF() 8 9+OPTION(FUZZING "Fuzzing" OFF) 10 OPTION(ENABLED_PROFILING "Enable profiling" ON) 11 OPTION(WITHOUT_SERVER OFF) 12 IF(UNIX) 13@@ -1348,6 +1349,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 1f499e9d9e5..a85c181ae78 100644 26--- a/include/mysql.h 27+++ b/include/mysql.h 28@@ -261,7 +261,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/violite.h b/include/violite.h 39index 76f2ed2017a..56900e11349 100644 40--- a/include/violite.h 41+++ b/include/violite.h 42@@ -108,12 +108,14 @@ enum enum_vio_type : int { 43 */ 44 VIO_TYPE_PLUGIN = 7, 45 46+ VIO_TYPE_FUZZ = 8, 47+ 48 FIRST_VIO_TYPE = VIO_TYPE_TCPIP, 49 /* 50 If a new type is added, please update LAST_VIO_TYPE. In addition, please 51 change get_vio_type_name() in vio/vio.c to return correct name for it. 52 */ 53- LAST_VIO_TYPE = VIO_TYPE_PLUGIN 54+ LAST_VIO_TYPE = VIO_TYPE_FUZZ 55 }; 56 57 /** 58@@ -450,4 +452,20 @@ struct Vio { 59 #define SSL_handle void * 60 #endif 61 62+ 63+//Vio fuzzing 64+bool vio_connect_fuzz(MYSQL_VIO vio, struct sockaddr *addr, socklen_t len, 65+ int timeout); 66+int vio_socket_timeout_fuzz(Vio *vio, uint which, bool b); 67+void sock_initfuzz(const uint8_t *Data, size_t Size); 68+size_t vio_read_buff_fuzz(Vio *vio, uchar *buf, size_t size); 69+size_t vio_write_buff_fuzz(Vio *vio, const uchar *buf, size_t size); 70+bool vio_is_connected_fuzz(Vio *vio); 71+bool vio_was_timeout_fuzz(Vio *vio); 72+int vio_shutdown_fuzz(Vio *vio); 73+int vio_keepalive_fuzz(Vio *vio, bool set_keep_alive); 74+int vio_io_wait_fuzz(Vio *vio, enum enum_vio_io_event event, int timeout); 75+int vio_fastsend_fuzz(Vio *vio); 76+bool vio_should_retry_fuzz(Vio *vio); 77+ 78 #endif /* vio_violite_h_ */ 79diff --git a/libmysql/CMakeLists.txt b/libmysql/CMakeLists.txt 80index 0979a2b7b8c..0c896297a9f 100644 81--- a/libmysql/CMakeLists.txt 82+++ b/libmysql/CMakeLists.txt 83@@ -324,7 +324,7 @@ IF(UNIX) 84 ADD_INSTALL_RPATH_FOR_OPENSSL(libmysql) 85 86 GET_TARGET_PROPERTY(libmysql_link_flags libmysql LINK_FLAGS) 87- IF(LINK_FLAG_NO_UNDEFINED) 88+ IF(LINK_FLAG_NO_UNDEFINED AND NOT FUZZING) 89 STRING_APPEND(libmysql_link_flags 90 " ${LINK_FLAG_NO_UNDEFINED}") 91 STRING_APPEND(libmysql_link_flags 92diff --git a/mysys/my_rnd.cc b/mysys/my_rnd.cc 93index fa96e35eb02..e03ee47c220 100644 94--- a/mysys/my_rnd.cc 95+++ b/mysys/my_rnd.cc 96@@ -51,6 +51,9 @@ 97 */ 98 99 double my_rnd(struct rand_struct *rand_st) { 100+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 101+ return 65.43; 102+#endif 103 rand_st->seed1 = (rand_st->seed1 * 3 + rand_st->seed2) % rand_st->max_value; 104 rand_st->seed2 = (rand_st->seed1 + rand_st->seed2 + 33) % rand_st->max_value; 105 return (((double)rand_st->seed1) / rand_st->max_value_dbl); 106@@ -67,6 +70,12 @@ Fill a buffer with random bytes using the SSL library routines 107 */ 108 int my_rand_buffer(unsigned char *buffer, size_t buffer_size) { 109 int rc; 110+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 111+ for (size_t i = 0; i < buffer_size; i++) 112+ buffer[i] = i; 113+ return 0; 114+#endif 115+ 116 rc = RAND_bytes(buffer, (int)buffer_size); 117 118 if (!rc) { 119@@ -88,6 +97,9 @@ int my_rand_buffer(unsigned char *buffer, size_t buffer_size) { 120 double my_rnd_ssl(bool *failed) { 121 unsigned int res; 122 123+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 124+ return 34.56; 125+#endif 126 if (my_rand_buffer((unsigned char *)&res, sizeof(res))) { 127 *failed = true; 128 return 0; 129diff --git a/sql-common/client.cc b/sql-common/client.cc 130index fd36e9950cf..c8cae8c3cbf 100644 131--- a/sql-common/client.cc 132+++ b/sql-common/client.cc 133@@ -5852,6 +5852,12 @@ static mysql_state_machine_status csm_begin_connect(mysql_async_connect *ctx) { 134 } 135 } 136 #endif /* _WIN32 */ 137+if (!net->vio && 138+ (mysql->options.protocol == MYSQL_PROTOCOL_FUZZ)) { 139+ net->vio = 140+ vio_new(0, VIO_TYPE_FUZZ, 0); 141+ ctx->host_info = (char *)ER_CLIENT(CR_LOCALHOST_CONNECTION); 142+} 143 #if defined(HAVE_SYS_UN_H) 144 if (!net->vio && 145 (!mysql->options.protocol || 146diff --git a/sql/mysqld.cc b/sql/mysqld.cc 147index c30315d4702..4413d95915d 100644 148--- a/sql/mysqld.cc 149+++ b/sql/mysqld.cc 150@@ -6395,7 +6395,9 @@ int mysqld_main(int argc, char **argv) 151 unireg_abort(MYSQLD_ABORT_EXIT); // Will do exit 152 } 153 154+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 155 my_init_signals(); 156+#endif 157 158 size_t guardize = 0; 159 #ifndef _WIN32 160@@ -6879,8 +6881,10 @@ int mysqld_main(int argc, char **argv) 161 unireg_abort(MYSQLD_ABORT_EXIT); 162 163 #ifndef _WIN32 164+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 165 // Start signal handler thread. 166 start_signal_handler(); 167+#endif 168 #endif 169 170 /* set all persistent options */ 171@@ -7022,8 +7026,9 @@ int mysqld_main(int argc, char **argv) 172 } 173 174 start_handle_manager(); 175- 176+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 177 create_compress_gtid_table_thread(); 178+#endif 179 180 LogEvent() 181 .type(LOG_TYPE_ERROR) 182@@ -7070,6 +7075,10 @@ int mysqld_main(int argc, char **argv) 183 184 (void)RUN_HOOK(server_state, before_handle_connection, (NULL)); 185 186+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 187+ return 0; 188+#endif 189+ 190 #if defined(_WIN32) 191 setup_conn_event_handler_threads(); 192 #else 193@@ -9895,6 +9904,9 @@ static int get_options(int *argc_ptr, char ***argv_ptr) { 194 195 if (opt_short_log_format) opt_specialflag |= SPECIAL_SHORT_LOG_FORMAT; 196 197+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 198+ Connection_handler_manager::thread_handling = Connection_handler_manager::SCHEDULER_NO_THREADS; 199+#endif 200 if (Connection_handler_manager::init()) { 201 LogErr(ERROR_LEVEL, ER_CONNECTION_HANDLING_OOM); 202 return 1; 203diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc 204index 983603eb58c..d577c6fcc05 100644 205--- a/storage/innobase/buf/buf0buf.cc 206+++ b/storage/innobase/buf/buf0buf.cc 207@@ -1484,18 +1484,14 @@ dberr_t buf_pool_init(ulint total_size, ulint n_instances) { 208 n = n_instances; 209 } 210 211- std::vector<std::thread> threads; 212- 213 std::mutex m; 214 215 for (ulint id = i; id < n; ++id) { 216- threads.emplace_back(std::thread(buf_pool_create, &buf_pool_ptr[id], size, 217- id, &m, std::ref(errs[id]))); 218+ buf_pool_create(&buf_pool_ptr[id], size, 219+ id, &m, std::ref(errs[id])); 220 } 221 222 for (ulint id = i; id < n; ++id) { 223- threads[id - i].join(); 224- 225 if (errs[id] != DB_SUCCESS) { 226 err = errs[id]; 227 } 228diff --git a/vio/CMakeLists.txt b/vio/CMakeLists.txt 229index d44eebce63a..975bc878e17 100644 230--- a/vio/CMakeLists.txt 231+++ b/vio/CMakeLists.txt 232@@ -27,6 +27,7 @@ SET(VIO_SOURCES 233 viosocket.cc 234 viossl.cc 235 viosslfactories.cc 236+ viofuzz.cc 237 ) 238 239 IF(WIN32) 240diff --git a/vio/vio.cc b/vio/vio.cc 241index f2007bbc928..3b2ca196ec5 100644 242--- a/vio/vio.cc 243+++ b/vio/vio.cc 244@@ -301,6 +301,27 @@ static bool vio_init(Vio *vio, enum enum_vio_type type, my_socket sd, 245 return false; 246 } 247 #endif /* HAVE_OPENSSL */ 248+ if (type == VIO_TYPE_FUZZ) { 249+ vio->viodelete = vio_delete; 250+ vio->vioerrno = vio_errno; 251+ vio->read = vio_read_buff_fuzz; 252+ vio->write = vio_write_buff_fuzz; 253+ vio->fastsend = vio_fastsend_fuzz; 254+ vio->viokeepalive = vio_keepalive_fuzz; 255+ vio->should_retry = vio_should_retry_fuzz; 256+ vio->was_timeout = vio_was_timeout_fuzz; 257+ vio->vioshutdown = vio_shutdown_fuzz; 258+ vio->peer_addr = vio_peer_addr; 259+ vio->timeout = vio_socket_timeout_fuzz; 260+ vio->io_wait = vio_io_wait_fuzz; 261+ vio->is_connected = vio_is_connected_fuzz; 262+ vio->has_data = vio->read_buffer ? vio_buff_has_data : has_no_data; 263+ vio->is_blocking = vio_is_blocking; 264+ vio->set_blocking = vio_set_blocking; 265+ vio->set_blocking_flag = vio_set_blocking_flag; 266+ vio->is_blocking_flag = false; 267+ return false; 268+ } 269 vio->viodelete = vio_delete; 270 vio->vioerrno = vio_errno; 271 vio->read = vio->read_buffer ? vio_read_buff : vio_read; 272@@ -576,7 +597,8 @@ static const vio_string vio_type_names[] = {{"", 0}, 273 {STRING_WITH_LEN("SSL/TLS")}, 274 {STRING_WITH_LEN("Shared Memory")}, 275 {STRING_WITH_LEN("Internal")}, 276- {STRING_WITH_LEN("Plugin")}}; 277+ {STRING_WITH_LEN("Plugin")}, 278+ {STRING_WITH_LEN("Fuzz")}}; 279 280 void get_vio_type_name(enum enum_vio_type vio_type, const char **str, 281 int *len) { 282diff --git a/vio/viofuzz.cc b/vio/viofuzz.cc 283new file mode 100644 284index 00000000000..83f22a5dbb9 285--- /dev/null 286+++ b/vio/viofuzz.cc 287@@ -0,0 +1,124 @@ 288+ 289+#include "my_config.h" 290+ 291+#include <errno.h> 292+#include <fcntl.h> 293+#include <sys/types.h> 294+#include <time.h> 295+#ifndef _WIN32 296+#include <netdb.h> 297+#endif 298+#include <stdio.h> 299+#include <stdlib.h> 300+ 301+#include "my_compiler.h" 302+#include "my_dbug.h" 303+#include "my_inttypes.h" 304+#include "my_io.h" 305+#include "my_macros.h" 306+#include "vio/vio_priv.h" 307+ 308+#ifdef FIONREAD_IN_SYS_FILIO 309+#include <sys/filio.h> 310+#endif 311+#ifndef _WIN32 312+#include <netinet/tcp.h> 313+#endif 314+#ifdef HAVE_POLL_H 315+#include <poll.h> 316+#endif 317+#ifdef HAVE_SYS_IOCTL_H 318+#include <sys/ioctl.h> 319+#endif 320+ 321+static const uint8_t *fuzzBuffer; 322+static size_t fuzzSize; 323+static size_t fuzzPos; 324+ 325+ 326+void sock_initfuzz(const uint8_t *Data, size_t Size) { 327+ fuzzPos = 0; 328+ fuzzSize = Size; 329+ fuzzBuffer = Data; 330+} 331+ 332+bool vio_connect_fuzz(Vio *vio, struct sockaddr *addr, socklen_t len, 333+ int timeout) { 334+ DBUG_ENTER("vio_socket_connect"); 335+ 336+ /* Only for socket-based transport types. */ 337+ DBUG_ASSERT(vio->type == VIO_TYPE_SOCKET || vio->type == VIO_TYPE_TCPIP); 338+ 339+ /* Initiate the connection. */ 340+ return 0; 341+} 342+ 343+ 344+int vio_socket_timeout_fuzz(Vio *vio, uint which, bool b) { 345+ DBUG_ENTER("vio_socket_timeout_fuzz\n"); 346+ return 0; 347+} 348+ 349+ 350+size_t vio_read_buff_fuzz(Vio *vio, uchar *bufp, size_t size) { 351+ DBUG_ENTER("vio_read_buff_fuzz.\n"); 352+ if (size > fuzzSize - fuzzPos) { 353+ size = fuzzSize - fuzzPos; 354+ } 355+ if (fuzzPos < fuzzSize) { 356+ memcpy(bufp, fuzzBuffer + fuzzPos, size); 357+ } 358+ fuzzPos += size; 359+#ifdef FUZZ_DEBUG 360+ printf("net cli %zu ", size); 361+ for (size_t i=0; i<size; i++) 362+ printf("%02x ", bufp[i]); 363+ printf("\n"); 364+#endif //FUZZ_DEBUG 365+ return size; 366+} 367+ 368+size_t vio_write_buff_fuzz(Vio *vio, const uchar *bufp, size_t size) { 369+ DBUG_ENTER("vio_write_buff_fuzz\n"); 370+#ifdef FUZZ_DEBUG 371+ printf("net srv %zu ", size); 372+ for (size_t i=0; i<size; i++) 373+ printf("%02x ", bufp[i]); 374+ printf("\n"); 375+#endif //FUZZ_DEBUG 376+ return size; 377+} 378+ 379+bool vio_is_connected_fuzz(Vio *vio) { 380+ DBUG_ENTER("vio_is_connected_fuzz\n"); 381+ return (fuzzPos < fuzzSize); 382+} 383+ 384+bool vio_was_timeout_fuzz(Vio *vio) { 385+ DBUG_ENTER("vio_was_timeout_fuzz\n"); 386+ return false; 387+} 388+ 389+int vio_shutdown_fuzz(Vio *vio) { 390+ DBUG_ENTER("vio_shutdown_fuzz"); 391+ return 0; 392+} 393+ 394+int vio_keepalive_fuzz(Vio *vio, bool set_keep_alive) { 395+ DBUG_ENTER("vio_keepalive_fuzz\n"); 396+ return 0; 397+} 398+int vio_io_wait_fuzz(Vio *vio, enum enum_vio_io_event event, int timeout) { 399+ DBUG_ENTER("vio_io_wait_fuzz"); 400+ return 1; 401+} 402+ 403+int vio_fastsend_fuzz(Vio *vio) { 404+ DBUG_ENTER("vio_fastsend_fuzz\n"); 405+ return 0; 406+} 407+ 408+bool vio_should_retry_fuzz(Vio *vio) { 409+ DBUG_ENTER("vio_should_retry_fuzz\n"); 410+ return (fuzzPos < fuzzSize); 411+} 412