// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Unused because SQLite is so serialized and concurrency-unfriendly that this
// really wouldn't test anything.
#include <condition_variable>
#include <cstdlib>
#include <iostream>
#include <mutex>
#include <string>
#include <thread>
#include <vector>
#include "testing/libfuzzer/proto/lpm_interface.h"
#include "third_party/sqlite/fuzz/disabled_queries_parser.h"
#include "third_party/sqlite/fuzz/sql_query_grammar.pb.h"
#include "third_party/sqlite/fuzz/sql_query_proto_to_string.h"
#include "third_party/sqlite/fuzz/sql_run_queries.h"
#include "third_party/sqlite/sqlite3.h"
using namespace sql_query_grammar;
namespace {
constexpr int kNumThreads = 4; // Must change with MultipleSQLQueries protobuf.
}
DEFINE_BINARY_PROTO_FUZZER(const MultipleSQLQueries& multiple_sql_queries) {
char* skip_queries = ::getenv("SQL_SKIP_QUERIES");
if (skip_queries) {
sql_fuzzer::SetDisabledQueries(
sql_fuzzer::ParseDisabledQueries(skip_queries));
}
assert(multiple_sql_queries.GetDescriptor()->field_count() == kNumThreads);
sqlite3* db = sql_fuzzer::InitConnectionForFuzzing();
if (!db)
return;
if (::getenv("LPM_SQLITE_TRACE")) {
sql_fuzzer::EnableSqliteTracing(db);
}
std::vector<std::string> query_strs[kNumThreads];
query_strs[0] = sql_fuzzer::SQLQueriesToVec(multiple_sql_queries.queries1());
query_strs[1] = sql_fuzzer::SQLQueriesToVec(multiple_sql_queries.queries2());
query_strs[2] = sql_fuzzer::SQLQueriesToVec(multiple_sql_queries.queries3());
query_strs[3] = sql_fuzzer::SQLQueriesToVec(multiple_sql_queries.queries4());
if (::getenv("LPM_DUMP_NATIVE_INPUT")) {
std::cout << "_________________________" << std::endl;
for (int i = 0; i < kNumThreads; i++) {
std::cout << "Thread " << i << ":" << std::endl;
for (std::string query : query_strs[i]) {
if (query == ";")
continue;
std::cout << query << std::endl;
}
}
std::cout << "------------------------" << std::endl;
}
int num_threads_started = 0;
std::mutex m;
std::condition_variable cv;
std::vector<std::thread> threads;
auto to_run = [&](std::vector<std::string> queries) {
// Wait for all the threads to start.
std::unique_lock<std::mutex> lk(m);
num_threads_started++;
cv.notify_all();
cv.wait(lk, [&] { return num_threads_started == kNumThreads; });
m.unlock();
sql_fuzzer::RunSqlQueriesOnConnection(db, queries);
};
for (int i = 0; i < kNumThreads; i++) {
threads.emplace_back(to_run, query_strs[i]);
}
for (int i = 0; i < kNumThreads; i++) {
threads[i].join();
}
sql_fuzzer::CloseConnection(db);
}