checkfreelist.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /*
  2. ** 2017 October 11
  3. **
  4. ** The author disclaims copyright to this source code. In place of
  5. ** a legal notice, here is a blessing:
  6. **
  7. ** May you do good and not evil.
  8. ** May you find forgiveness for yourself and forgive others.
  9. ** May you share freely, never taking more than you give.
  10. **
  11. *************************************************************************
  12. **
  13. ** This module exports a single C function:
  14. **
  15. ** int sqlite3_check_freelist(sqlite3 *db, const char *zDb);
  16. **
  17. ** This function checks the free-list in database zDb (one of "main",
  18. ** "temp", etc.) and reports any errors by invoking the sqlite3_log()
  19. ** function. It returns SQLITE_OK if successful, or an SQLite error
  20. ** code otherwise. It is not an error if the free-list is corrupted but
  21. ** no IO or OOM errors occur.
  22. **
  23. ** If this file is compiled and loaded as an SQLite loadable extension,
  24. ** it adds an SQL function "checkfreelist" to the database handle, to
  25. ** be invoked as follows:
  26. **
  27. ** SELECT checkfreelist(<database-name>);
  28. **
  29. ** This function performs the same checks as sqlite3_check_freelist(),
  30. ** except that it returns all error messages as a single text value,
  31. ** separated by newline characters. If the freelist is not corrupted
  32. ** in any way, an empty string is returned.
  33. **
  34. ** To compile this module for use as an SQLite loadable extension:
  35. **
  36. ** gcc -Os -fPIC -shared checkfreelist.c -o checkfreelist.so
  37. */
  38. #include "sqlite3ext.h"
  39. SQLITE_EXTENSION_INIT1
  40. #ifndef SQLITE_AMALGAMATION
  41. # include <string.h>
  42. # include <stdio.h>
  43. # include <stdlib.h>
  44. # include <assert.h>
  45. # if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
  46. # define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
  47. # endif
  48. # if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
  49. # define ALWAYS(X) (1)
  50. # define NEVER(X) (0)
  51. # elif !defined(NDEBUG)
  52. # define ALWAYS(X) ((X)?1:(assert(0),0))
  53. # define NEVER(X) ((X)?(assert(0),1):0)
  54. # else
  55. # define ALWAYS(X) (X)
  56. # define NEVER(X) (X)
  57. # endif
  58. typedef unsigned char u8;
  59. typedef unsigned short u16;
  60. typedef unsigned int u32;
  61. #define get4byte(x) ( \
  62. ((u32)((x)[0])<<24) + \
  63. ((u32)((x)[1])<<16) + \
  64. ((u32)((x)[2])<<8) + \
  65. ((u32)((x)[3])) \
  66. )
  67. #endif
  68. /*
  69. ** Execute a single PRAGMA statement and return the integer value returned
  70. ** via output parameter (*pnOut).
  71. **
  72. ** The SQL statement passed as the third argument should be a printf-style
  73. ** format string containing a single "%s" which will be replace by the
  74. ** value passed as the second argument. e.g.
  75. **
  76. ** sqlGetInteger(db, "main", "PRAGMA %s.page_count", pnOut)
  77. **
  78. ** executes "PRAGMA main.page_count" and stores the results in (*pnOut).
  79. */
  80. static int sqlGetInteger(
  81. sqlite3 *db, /* Database handle */
  82. const char *zDb, /* Database name ("main", "temp" etc.) */
  83. const char *zFmt, /* SQL statement format */
  84. u32 *pnOut /* OUT: Integer value */
  85. ){
  86. int rc, rc2;
  87. char *zSql;
  88. sqlite3_stmt *pStmt = 0;
  89. int bOk = 0;
  90. zSql = sqlite3_mprintf(zFmt, zDb);
  91. if( zSql==0 ){
  92. rc = SQLITE_NOMEM;
  93. }else{
  94. rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
  95. sqlite3_free(zSql);
  96. }
  97. if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
  98. *pnOut = (u32)sqlite3_column_int(pStmt, 0);
  99. bOk = 1;
  100. }
  101. rc2 = sqlite3_finalize(pStmt);
  102. if( rc==SQLITE_OK ) rc = rc2;
  103. if( rc==SQLITE_OK && bOk==0 ) rc = SQLITE_ERROR;
  104. return rc;
  105. }
  106. /*
  107. ** Argument zFmt must be a printf-style format string and must be
  108. ** followed by its required arguments. If argument pzOut is NULL,
  109. ** then the results of printf()ing the format string are passed to
  110. ** sqlite3_log(). Otherwise, they are appended to the string
  111. ** at (*pzOut).
  112. */
  113. static int checkFreelistError(char **pzOut, const char *zFmt, ...){
  114. int rc = SQLITE_OK;
  115. char *zErr = 0;
  116. va_list ap;
  117. va_start(ap, zFmt);
  118. zErr = sqlite3_vmprintf(zFmt, ap);
  119. if( zErr==0 ){
  120. rc = SQLITE_NOMEM;
  121. }else{
  122. if( pzOut ){
  123. *pzOut = sqlite3_mprintf("%s%z%s", *pzOut?"\n":"", *pzOut, zErr);
  124. if( *pzOut==0 ) rc = SQLITE_NOMEM;
  125. }else{
  126. sqlite3_log(SQLITE_ERROR, "checkfreelist: %s", zErr);
  127. }
  128. sqlite3_free(zErr);
  129. }
  130. va_end(ap);
  131. return rc;
  132. }
  133. static int checkFreelist(
  134. sqlite3 *db,
  135. const char *zDb,
  136. char **pzOut
  137. ){
  138. /* This query returns one row for each page on the free list. Each row has
  139. ** two columns - the page number and page content. */
  140. const char *zTrunk =
  141. "WITH freelist_trunk(i, d, n) AS ("
  142. "SELECT 1, NULL, sqlite_readint32(data, 32) "
  143. "FROM sqlite_dbpage(:1) WHERE pgno=1 "
  144. "UNION ALL "
  145. "SELECT n, data, sqlite_readint32(data) "
  146. "FROM freelist_trunk, sqlite_dbpage(:1) WHERE pgno=n "
  147. ")"
  148. "SELECT i, d FROM freelist_trunk WHERE i!=1;";
  149. int rc, rc2; /* Return code */
  150. sqlite3_stmt *pTrunk = 0; /* Compilation of zTrunk */
  151. u32 nPage = 0; /* Number of pages in db */
  152. u32 nExpected = 0; /* Expected number of free pages */
  153. u32 nFree = 0; /* Number of pages on free list */
  154. if( zDb==0 ) zDb = "main";
  155. if( (rc = sqlGetInteger(db, zDb, "PRAGMA %s.page_count", &nPage))
  156. || (rc = sqlGetInteger(db, zDb, "PRAGMA %s.freelist_count", &nExpected))
  157. ){
  158. return rc;
  159. }
  160. rc = sqlite3_prepare_v2(db, zTrunk, -1, &pTrunk, 0);
  161. if( rc!=SQLITE_OK ) return rc;
  162. sqlite3_bind_text(pTrunk, 1, zDb, -1, SQLITE_STATIC);
  163. while( rc==SQLITE_OK && sqlite3_step(pTrunk)==SQLITE_ROW ){
  164. u32 i;
  165. u32 iTrunk = (u32)sqlite3_column_int(pTrunk, 0);
  166. const u8 *aData = (const u8*)sqlite3_column_blob(pTrunk, 1);
  167. u32 nData = (u32)sqlite3_column_bytes(pTrunk, 1);
  168. u32 iNext = get4byte(&aData[0]);
  169. u32 nLeaf = get4byte(&aData[4]);
  170. if( nLeaf>((nData/4)-2-6) ){
  171. rc = checkFreelistError(pzOut,
  172. "leaf count out of range (%d) on trunk page %d",
  173. (int)nLeaf, (int)iTrunk
  174. );
  175. nLeaf = (nData/4) - 2 - 6;
  176. }
  177. nFree += 1+nLeaf;
  178. if( iNext>nPage ){
  179. rc = checkFreelistError(pzOut,
  180. "trunk page %d is out of range", (int)iNext
  181. );
  182. }
  183. for(i=0; rc==SQLITE_OK && i<nLeaf; i++){
  184. u32 iLeaf = get4byte(&aData[8 + 4*i]);
  185. if( iLeaf==0 || iLeaf>nPage ){
  186. rc = checkFreelistError(pzOut,
  187. "leaf page %d is out of range (child %d of trunk page %d)",
  188. (int)iLeaf, (int)i, (int)iTrunk
  189. );
  190. }
  191. }
  192. }
  193. if( rc==SQLITE_OK && nFree!=nExpected ){
  194. rc = checkFreelistError(pzOut,
  195. "free-list count mismatch: actual=%d header=%d",
  196. (int)nFree, (int)nExpected
  197. );
  198. }
  199. rc2 = sqlite3_finalize(pTrunk);
  200. if( rc==SQLITE_OK ) rc = rc2;
  201. return rc;
  202. }
  203. int sqlite3_check_freelist(sqlite3 *db, const char *zDb){
  204. return checkFreelist(db, zDb, 0);
  205. }
  206. static void checkfreelist_function(
  207. sqlite3_context *pCtx,
  208. int nArg,
  209. sqlite3_value **apArg
  210. ){
  211. const char *zDb;
  212. int rc;
  213. char *zOut = 0;
  214. sqlite3 *db = sqlite3_context_db_handle(pCtx);
  215. assert( nArg==1 );
  216. zDb = (const char*)sqlite3_value_text(apArg[0]);
  217. rc = checkFreelist(db, zDb, &zOut);
  218. if( rc==SQLITE_OK ){
  219. sqlite3_result_text(pCtx, zOut?zOut:"ok", -1, SQLITE_TRANSIENT);
  220. }else{
  221. sqlite3_result_error_code(pCtx, rc);
  222. }
  223. sqlite3_free(zOut);
  224. }
  225. /*
  226. ** An SQL function invoked as follows:
  227. **
  228. ** sqlite_readint32(BLOB) -- Decode 32-bit integer from start of blob
  229. */
  230. static void readint_function(
  231. sqlite3_context *pCtx,
  232. int nArg,
  233. sqlite3_value **apArg
  234. ){
  235. const u8 *zBlob;
  236. int nBlob;
  237. int iOff = 0;
  238. u32 iRet = 0;
  239. if( nArg!=1 && nArg!=2 ){
  240. sqlite3_result_error(
  241. pCtx, "wrong number of arguments to function sqlite_readint32()", -1
  242. );
  243. return;
  244. }
  245. if( nArg==2 ){
  246. iOff = sqlite3_value_int(apArg[1]);
  247. }
  248. zBlob = sqlite3_value_blob(apArg[0]);
  249. nBlob = sqlite3_value_bytes(apArg[0]);
  250. if( nBlob>=(iOff+4) ){
  251. iRet = get4byte(&zBlob[iOff]);
  252. }
  253. sqlite3_result_int64(pCtx, (sqlite3_int64)iRet);
  254. }
  255. /*
  256. ** Register the SQL functions.
  257. */
  258. static int cflRegister(sqlite3 *db){
  259. int rc = sqlite3_create_function(
  260. db, "sqlite_readint32", -1, SQLITE_UTF8, 0, readint_function, 0, 0
  261. );
  262. if( rc!=SQLITE_OK ) return rc;
  263. rc = sqlite3_create_function(
  264. db, "checkfreelist", 1, SQLITE_UTF8, 0, checkfreelist_function, 0, 0
  265. );
  266. return rc;
  267. }
  268. /*
  269. ** Extension load function.
  270. */
  271. #ifdef _WIN32
  272. __declspec(dllexport)
  273. #endif
  274. int sqlite3_checkfreelist_init(
  275. sqlite3 *db,
  276. char **pzErrMsg,
  277. const sqlite3_api_routines *pApi
  278. ){
  279. SQLITE_EXTENSION_INIT2(pApi);
  280. return cflRegister(db);
  281. }