• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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