| // 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); | |
| } |