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