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