sql_run_queries.cc 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. // Adapted from sqlite's ossfuzz.c
  5. #include <cstdlib>
  6. #include <iostream> // TODO(mpdenton) remove
  7. #include <string>
  8. #include <vector>
  9. #include "third_party/sqlite/sqlite3.h"
  10. namespace sql_fuzzer {
  11. namespace {
  12. constexpr int kMaxNumRows = 10;
  13. constexpr int kMaxNumColumns = 10;
  14. sqlite3_int64 killTime;
  15. /* Return the current real-world time in milliseconds since the
  16. ** Julian epoch (-4714-11-24).
  17. */
  18. static sqlite3_int64 timeOfDay(void) {
  19. static sqlite3_vfs* clockVfs = 0;
  20. sqlite3_int64 t;
  21. if (clockVfs == 0) {
  22. clockVfs = sqlite3_vfs_find(0);
  23. if (clockVfs == 0)
  24. return 0;
  25. }
  26. if (clockVfs->iVersion >= 2 && clockVfs->xCurrentTimeInt64 != 0) {
  27. clockVfs->xCurrentTimeInt64(clockVfs, &t);
  28. } else {
  29. double r;
  30. clockVfs->xCurrentTime(clockVfs, &r);
  31. t = (sqlite3_int64)(r * 86400000.0);
  32. }
  33. return t;
  34. }
  35. int progress_handler(void*) {
  36. sqlite3_int64 iNow = timeOfDay();
  37. int rc = iNow >= killTime;
  38. return rc;
  39. }
  40. } // namespace
  41. void RunSqlQueriesOnSameDB() {
  42. // TODO(mpdenton) unimplemented
  43. }
  44. sqlite3* InitConnectionForFuzzing() {
  45. int rc; // Return code from various interfaces.
  46. sqlite3* db; // Sqlite db.
  47. rc = sqlite3_initialize();
  48. if (rc) {
  49. std::cerr << "Failed initialization. " << std::endl;
  50. return nullptr;
  51. }
  52. // Open the database connection. Only use an in-memory database.
  53. rc = sqlite3_open_v2(
  54. "fuzz.db", &db,
  55. SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY, 0);
  56. if (rc) {
  57. std::cerr << "Failed to open DB. " << std::endl;
  58. return nullptr;
  59. }
  60. // Enables foreign key constraints
  61. sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_FKEY, 1, &rc);
  62. // sqlite3_db_config(db, SQLITE_DBCONFIG_DEFENSIVE, 0, &rc); // TODO(pwnall)
  63. return db;
  64. }
  65. void EnableSqliteTracing(sqlite3* db) {
  66. sqlite3_exec(db, "PRAGMA vdbe_debug=ON", 0, 0, 0);
  67. }
  68. void CloseConnection(sqlite3* db) {
  69. // Cleanup and return.
  70. sqlite3_exec(db, "PRAGMA temp_store_directory=''", 0, 0, 0);
  71. sqlite3_close(db);
  72. }
  73. void RunSqlQueriesOnConnection(sqlite3* db, std::vector<std::string> queries) {
  74. int rc;
  75. for (size_t i = 0; i < queries.size(); i++) {
  76. // Run each query one by one.
  77. // First, compile the query.
  78. sqlite3_stmt* stmt;
  79. const char* pzTail;
  80. rc = sqlite3_prepare_v2(db, queries[i].c_str(), -1, &stmt, &pzTail);
  81. if (rc != SQLITE_OK) {
  82. if (::getenv("PRINT_SQLITE_ERRORS")) {
  83. std::cerr << "Could not compile: " << queries[i] << std::endl;
  84. std::cerr << "Error message from db: " << sqlite3_errmsg(db)
  85. << std::endl;
  86. std::cerr << "-----------------------------" << std::endl;
  87. }
  88. continue;
  89. }
  90. // No sqlite3_bind.
  91. // Reset progress callback for every query. Timeout after 1 second.
  92. // ClusterFuzz timeouts are not useful, so we try to avoid them.
  93. // This will hopefully make Clusterfuzz find better, smaller SELECT
  94. // statements.
  95. #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  96. killTime = timeOfDay() + 1000;
  97. sqlite3_progress_handler(db, 100, progress_handler, nullptr);
  98. #endif
  99. // Now run the compiled query.
  100. int col_cnt = sqlite3_column_count(stmt);
  101. int count = 0;
  102. rc = SQLITE_ROW;
  103. while (rc == SQLITE_ROW && count++ <= kMaxNumRows) {
  104. rc = sqlite3_step(stmt);
  105. if (rc != SQLITE_DONE && rc != SQLITE_ROW) {
  106. if (::getenv("PRINT_SQLITE_ERRORS")) {
  107. std::cerr << "Step problem: " << queries[i] << std::endl;
  108. std::cerr << "Error message from db: " << sqlite3_errmsg(db)
  109. << std::endl;
  110. std::cerr << "-----------------------------" << std::endl;
  111. }
  112. goto free_stmt;
  113. }
  114. // Loop through the columns to catch a little bit more coverage.
  115. for (int i = 0; i < col_cnt && i < kMaxNumColumns; i++) {
  116. switch (sqlite3_column_type(stmt, i)) {
  117. case SQLITE_INTEGER:
  118. sqlite3_column_int(stmt, i);
  119. break;
  120. case SQLITE_FLOAT:
  121. sqlite3_column_double(stmt, i);
  122. break;
  123. case SQLITE_TEXT:
  124. sqlite3_column_text(stmt, i);
  125. break;
  126. case SQLITE_BLOB:
  127. sqlite3_column_blob(stmt, i);
  128. break;
  129. default:
  130. break;
  131. }
  132. }
  133. }
  134. // Finalize the query
  135. free_stmt:
  136. sqlite3_finalize(stmt);
  137. }
  138. }
  139. void RunSqlQueries(std::vector<std::string> queries, bool enable_tracing) {
  140. sqlite3* db = InitConnectionForFuzzing();
  141. if (enable_tracing)
  142. EnableSqliteTracing(db);
  143. RunSqlQueriesOnConnection(db, queries);
  144. CloseConnection(db);
  145. }
  146. } // namespace sql_fuzzer