mirror of https://github.com/google/oss-fuzz.git
165 lines
5.3 KiB
C++
165 lines
5.3 KiB
C++
//#include <stdint.h>
|
|
//#include <stdlib.h>
|
|
//#include <stdio.h>
|
|
//#include <string>
|
|
//#include <iostream>
|
|
//#include <mysql.h>
|
|
//#include <mysql/client_plugin.h>
|
|
//#include <mysqld_error.h>
|
|
#include "sql/sql_class.h"
|
|
#include "sql/protocol_classic.h"
|
|
#include "sql/conn_handler/channel_info.h"
|
|
#include "sql/conn_handler/connection_handler.h"
|
|
#include "sql/conn_handler/connection_handler_manager.h"
|
|
#include "sql/conn_handler/init_net_server_extension.h"
|
|
#include "sql/conn_handler/connection_handler_impl.h"
|
|
#include "sql/mysqld.h"
|
|
#include "sql/set_var.h"
|
|
#include "sql/rpl_handler.h"
|
|
#include "sql/log.h"
|
|
#include "sql/opt_costconstantcache.h"
|
|
#include "sql/sql_plugin.h"
|
|
#include "sql/sql_thd_internal_api.h"
|
|
#include "sql/mysqld_thd_manager.h"
|
|
#include "mysql/psi/mysql_socket.h"
|
|
#include "violite.h"
|
|
#include "util_fuzz.h"
|
|
#include <stdlib.h>
|
|
#include <libgen.h>
|
|
|
|
using namespace std;
|
|
FILE *logfile = NULL;
|
|
extern int mysqld_main(int argc, char **argv);
|
|
char *filepath = NULL;
|
|
|
|
extern "C" int LLVMFuzzerInitialize(const int* argc, char*** argv) {
|
|
filepath = dirname(strdup((*argv)[0]));
|
|
return 0;
|
|
}
|
|
|
|
class Channel_info_fuzz : public Channel_info {
|
|
bool m_is_admin_conn;
|
|
|
|
protected:
|
|
virtual Vio *create_and_init_vio() const {
|
|
Vio *vio = vio_new(0, VIO_TYPE_FUZZ, VIO_LOCALHOST);
|
|
return vio;
|
|
}
|
|
|
|
public:
|
|
Channel_info_fuzz(bool is_admin_conn) : m_is_admin_conn(is_admin_conn) {}
|
|
|
|
virtual THD *create_thd() {
|
|
Vio *vio_tmp = create_and_init_vio();
|
|
if (vio_tmp == NULL) return NULL;
|
|
|
|
THD *thd = new (std::nothrow) THD();
|
|
if (thd == NULL) {
|
|
vio_delete(vio_tmp);
|
|
return NULL;
|
|
}
|
|
thd->get_protocol_classic()->init_net(vio_tmp);
|
|
thd->set_admin_connection(m_is_admin_conn);
|
|
init_net_server_extension(thd);
|
|
return thd;
|
|
}
|
|
|
|
virtual bool is_admin_connection() const { return m_is_admin_conn; }
|
|
};
|
|
|
|
static void try_connection(Channel_info *channel_info) {
|
|
if (my_thread_init()) {
|
|
channel_info->send_error_and_close_channel(ER_OUT_OF_RESOURCES, 0, false);
|
|
return;
|
|
}
|
|
|
|
THD *thd = channel_info->create_thd();
|
|
if (thd == NULL) {
|
|
channel_info->send_error_and_close_channel(ER_OUT_OF_RESOURCES, 0, false);
|
|
return;
|
|
}
|
|
|
|
thd->set_new_thread_id();
|
|
|
|
/*
|
|
handle_one_connection() is normally the only way a thread would
|
|
start and would always be on the very high end of the stack ,
|
|
therefore, the thread stack always starts at the address of the
|
|
first local variable of handle_one_connection, which is thd. We
|
|
need to know the start of the stack so that we could check for
|
|
stack overruns.
|
|
*/
|
|
thd_set_thread_stack(thd, (char *)&thd);
|
|
thd->store_globals();
|
|
|
|
mysql_thread_set_psi_id(thd->thread_id());
|
|
mysql_socket_set_thread_owner(
|
|
thd->get_protocol_classic()->get_vio()->mysql_socket);
|
|
|
|
Global_THD_manager *thd_manager = Global_THD_manager::get_instance();
|
|
thd_manager->add_thd(thd);
|
|
|
|
if (!thd_prepare_connection(thd)) {
|
|
//authentication bypass
|
|
abort();
|
|
}
|
|
delete channel_info;
|
|
close_connection(thd, 0, false, false);
|
|
thd->release_resources();
|
|
thd_manager->remove_thd(thd);
|
|
delete thd;
|
|
}
|
|
|
|
|
|
#define MAX_SIZE 256
|
|
|
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
|
if (Size < 1) {
|
|
return 0;
|
|
}
|
|
if (logfile == NULL) {
|
|
my_progname = "fuzz_mysqld";
|
|
/* first init was run with
|
|
* mysqld --user=root --initialize-insecure --log-error-verbosity=5 --datadir=/out/mysql/data/ --basedir=/out/mysql/
|
|
*/
|
|
utilfuzz_rmrf("/tmp/mysqld");
|
|
char command[MAX_SIZE];
|
|
char argbase[MAX_SIZE];
|
|
char arginitfile[MAX_SIZE];
|
|
snprintf(command, MAX_SIZE-1, "%s/mysql/data", filepath);
|
|
utilfuzz_cpr(command, "/tmp/mysqld");
|
|
|
|
snprintf(argbase, MAX_SIZE-1, "--basedir=%s/mysql/", filepath);
|
|
snprintf(arginitfile, MAX_SIZE-1, "--init-file=%s/init.sql", filepath);
|
|
char *fakeargv[] = {const_cast<char *>("fuzz_mysqld"),
|
|
const_cast<char *>("--user=root"),
|
|
const_cast<char *>("--secure-file-priv=NULL"),
|
|
const_cast<char *>("--log-error-verbosity=5"),
|
|
const_cast<char *>("--explicit_defaults_for_timestamp"),
|
|
//we should adapt vio_fuzz to give a socket to openssl in order to support ssl
|
|
const_cast<char *>("--skip-ssl"),
|
|
const_cast<char *>("--mysqlx=0"),
|
|
const_cast<char *>("--event-scheduler=DISABLED"),
|
|
const_cast<char *>("--performance_schema=OFF"),
|
|
const_cast<char *>("--thread_stack=1048576"),
|
|
const_cast<char *>("--datadir=/tmp/mysqld/"),
|
|
const_cast<char *>("--port=3303"),
|
|
const_cast<char *>("--socket=/tmp/mysqld.sock"),
|
|
const_cast<char *>(argbase),
|
|
const_cast<char *>(arginitfile),
|
|
0};
|
|
int fakeargc = 15;
|
|
mysqld_main(fakeargc, fakeargv);
|
|
//terminate_compress_gtid_table_thread();
|
|
|
|
logfile = fopen("/dev/null", "w");
|
|
}
|
|
// The fuzzing takes place on network data received from client
|
|
sock_initfuzz(Data,Size-1);
|
|
|
|
Channel_info_fuzz *channel_info = new (std::nothrow) Channel_info_fuzz(Data[Size-1] & 0x80);
|
|
try_connection(channel_info);
|
|
|
|
return 0;
|
|
}
|