From 1c0593280b4c9575b4214c2675e6d20e1b8a4b15 Mon Sep 17 00:00:00 2001 From: lxlxlxl Date: Thu, 7 Nov 2024 21:47:57 +0800 Subject: [PATCH 1/4] =?UTF-8?q?1.=E4=BF=AE=E5=A4=8D=E4=B8=8D=E5=90=8CDB?= =?UTF-8?q?=E7=9A=84=E5=85=A8=E5=B1=80=E5=8A=A0=E5=AF=86=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E7=9B=B8=E4=BA=92=E5=BD=B1=E5=93=8D=E9=97=AE=E9=A2=98=202.?= =?UTF-8?q?=E4=BF=AE=E5=A4=8Dattach=E9=BB=98=E8=AE=A4=E5=8A=A0=E5=AF=86?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E4=B8=8D=E7=94=9F=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: ryne3366 --- src/sqlite3.c | 139 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 84 insertions(+), 55 deletions(-) diff --git a/src/sqlite3.c b/src/sqlite3.c index 2b77ee8..dedbd85 100644 --- a/src/sqlite3.c +++ b/src/sqlite3.c @@ -17004,6 +17004,17 @@ SQLITE_PRIVATE void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**); typedef void (*sqlite3_xDropTableHandle)(sqlite3*, const char*, const char*); +#if defined(SQLITE_HAS_CODEC) && defined(SQLITE_CODEC_ATTACH_CHANGED) +typedef struct CodecParameter { + int kdfIter; + int pageSize; + u8 cipher; + u8 hmacAlgo; + u8 kdfAlgo; + u8 reserved; +} CodecParameter; +#endif + /* ** Each database connection is an instance of the following structure. */ @@ -17153,6 +17164,9 @@ struct sqlite3 { char *mDropSchemaName; sqlite3_xDropTableHandle xDropTableHandle; /* User drop table callback */ #endif +#if defined(SQLITE_HAS_CODEC) && defined(SQLITE_CODEC_ATTACH_CHANGED) + CodecParameter codecParm; +#endif }; /* @@ -20128,6 +20142,9 @@ SQLITE_PRIVATE int sqlite3CodecQueryParameters(sqlite3*,const char*,const char #else # define sqlite3CodecQueryParameters(A,B,C) 0 #endif +#if defined(SQLITE_HAS_CODEC) && defined(SQLITE_CODEC_ATTACH_CHANGED) +SQLITE_PRIVATE void sqlite3CodecResetParameters(CodecParameter *p); +#endif SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3*,const char*); #ifdef SQLITE_UNTESTABLE @@ -67209,9 +67226,9 @@ SQLITE_PRIVATE int sqlite3WalFrames( WALTRACE(("WAL%p: frame write %s\n", pWal, rc ? "failed" : "ok")); return rc; } - +#ifdef LOG_DUMP static sqlite3_int64 g_lastCkptTime = 0; - +#endif /* ** This routine is called to implement sqlite3_wal_checkpoint() and ** related interfaces. @@ -176979,8 +176996,14 @@ opendb_out: sqlite3GlobalConfig.xSqllog(pArg, db, zFilename, 0); } #endif + #if defined(SQLITE_HAS_CODEC) - if( rc==SQLITE_OK ) sqlite3CodecQueryParameters(db, 0, zOpen); + if( rc==SQLITE_OK ) { +#ifdef SQLITE_CODEC_ATTACH_CHANGED + sqlite3CodecResetParameters(&db->codecParm); +#endif + sqlite3CodecQueryParameters(db, 0, zOpen); + } #endif sqlite3_free_filename(zOpen); return rc; @@ -245165,28 +245188,31 @@ CODEC_STATIC int sqlite3CodecSetIter(KeyContext *keyCtx, int iter){ #define CIPHER_NAME_AES_256_CBC "aes-256-cbc" #define CIPHER_NAME_AES_256_GCM "aes-256-gcm" -static int g_defaultAttachKdfIter = 10000; -static int g_defaultAttachCipher = CIPHER_ID_AES_256_GCM; -static int g_defaultAttachHmacAlgo = DEFAULT_HMAC_ALGORITHM; -static int g_defaultAttachKdfAlgo = DEFAULT_KDF_ALGORITHM; -static int g_defaultAttachPageSize = DEFAULT_PAGE_SIZE; - struct CodecCipherNameId { int cipherId; const char *cipherName; }; -struct CodecCipherNameId g_cipherNameIdMap[CIPHER_TOTAL_NUM] = { +static const struct CodecCipherNameId g_cipherNameIdMap[CIPHER_TOTAL_NUM] = { { CIPHER_ID_AES_256_CBC, CIPHER_NAME_AES_256_CBC }, { CIPHER_ID_AES_256_GCM, CIPHER_NAME_AES_256_GCM } }; -CODEC_STATIC void sqlite3CodecSetDefaultAttachCipher(const char *cipherName){ +SQLITE_PRIVATE void sqlite3CodecResetParameters(CodecParameter *p) +{ + p->kdfIter = DEFAULT_ITER; + p->pageSize = DEFAULT_PAGE_SIZE; + p->cipher = CIPHER_ID_AES_256_GCM; + p->hmacAlgo = DEFAULT_HMAC_ALGORITHM; + p->kdfAlgo = DEFAULT_KDF_ALGORITHM; +} + +CODEC_STATIC void sqlite3CodecSetDefaultAttachCipher(CodecParameter *parm, const char *cipherName){ int i; for( i=0; icipher = g_cipherNameIdMap[i].cipherId; sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); return; } @@ -245194,67 +245220,67 @@ CODEC_STATIC void sqlite3CodecSetDefaultAttachCipher(const char *cipherName){ sqlite3_log(SQLITE_WARNING, "invalid attach cipher algorithm"); } -CODEC_STATIC const char *sqlite3CodecGetDefaultAttachCipher(){ +CODEC_STATIC const char *sqlite3CodecGetDefaultAttachCipher(CodecParameter *parm){ const char *attachedCipher = CIPHER_NAME_AES_256_GCM; sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); - if( (g_defaultAttachCipher>=0) && (g_defaultAttachCiphercipher>=0) && (parm->ciphercipher].cipherName; } sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); return attachedCipher; } -CODEC_STATIC void sqlite3CodecSetDefaultAttachKdfIter(int iter){ +CODEC_STATIC void sqlite3CodecSetDefaultAttachKdfIter(CodecParameter *parm, int iter){ if( iter<=0 ){ return; } sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); - g_defaultAttachKdfIter = iter; + parm->kdfIter = iter; sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); } -CODEC_STATIC int sqlite3CodecGetDefaultAttachKdfIter(){ +CODEC_STATIC int sqlite3CodecGetDefaultAttachKdfIter(CodecParameter *parm){ sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); - int iterNum = g_defaultAttachKdfIter; + int iterNum = parm->kdfIter; sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); return iterNum; } -CODEC_STATIC void sqlite3CodecSetDefaultAttachHmacAlgo(int hmacAlgo){ +CODEC_STATIC void sqlite3CodecSetDefaultAttachHmacAlgo(CodecParameter *parm, int hmacAlgo){ sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); - g_defaultAttachHmacAlgo = hmacAlgo; + parm->hmacAlgo = hmacAlgo; sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); } -CODEC_STATIC int sqlite3CodecGetDefaultAttachHmacAlgo(){ +CODEC_STATIC int sqlite3CodecGetDefaultAttachHmacAlgo(CodecParameter *parm){ sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); - int hmacAlgo = g_defaultAttachHmacAlgo; + int hmacAlgo = parm->hmacAlgo; sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); return hmacAlgo; } -CODEC_STATIC void sqlite3CodecSetDefaultAttachKdfAlgo(int kdfAlgo){ +CODEC_STATIC void sqlite3CodecSetDefaultAttachKdfAlgo(CodecParameter *parm, int kdfAlgo){ sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); - g_defaultAttachKdfAlgo = kdfAlgo; + parm->kdfAlgo = kdfAlgo; sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); } -CODEC_STATIC int sqlite3CodecGetDefaultAttachKdfAlgo(){ +CODEC_STATIC int sqlite3CodecGetDefaultAttachKdfAlgo(CodecParameter *parm){ sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); - int kdfAlgo = g_defaultAttachKdfAlgo; + int kdfAlgo = parm->kdfAlgo; sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); return kdfAlgo; } -CODEC_STATIC void sqlite3CodecSetDefaultAttachPageSize(int pageSize){ +CODEC_STATIC void sqlite3CodecSetDefaultAttachPageSize(CodecParameter *parm, int pageSize){ sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); - g_defaultAttachPageSize = pageSize; + parm->pageSize = pageSize; sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); } -CODEC_STATIC int sqlite3CodecGetDefaultAttachPageSize(){ +CODEC_STATIC int sqlite3CodecGetDefaultAttachPageSize(CodecParameter *parm){ sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); - int pageSize = g_defaultAttachPageSize; + int pageSize = parm->pageSize; sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); return pageSize; } @@ -245341,8 +245367,7 @@ CODEC_STATIC int sqlite3CodecCopyKeyContext(KeyContext *input, KeyContext *outpu // You should clear key context before you call this function #ifdef SQLITE_CODEC_ATTACH_CHANGED -CODEC_STATIC int sqlite3CodecInitKeyContext(CodecContext *ctx, Btree *p, const void *zKey, int nKey, int attachFlag, - int hmacAlgo){ +CODEC_STATIC int sqlite3CodecInitKeyContext(CodecContext *ctx, Btree *p, const void *zKey, int nKey, int attachFlag){ #else CODEC_STATIC int sqlite3CodecInitKeyContext(CodecContext *ctx, Btree *p, const void *zKey, int nKey){ #endif @@ -245350,16 +245375,18 @@ CODEC_STATIC int sqlite3CodecInitKeyContext(CodecContext *ctx, Btree *p, const v KeyContext *keyCtx = ctx->readCtx; #ifdef SQLITE_CODEC_ATTACH_CHANGED if( attachFlag!=0 ){ - rc = sqlite3CodecSetCodecConstant(keyCtx, sqlite3CodecGetDefaultAttachCipher()); - rc += sqlite3CodecSetIter(keyCtx, sqlite3CodecGetDefaultAttachKdfIter()); + CodecParameter *parm = &p->db->codecParm; + int hmacAlgo = sqlite3CodecGetDefaultAttachHmacAlgo(parm); + rc = sqlite3CodecSetCodecConstant(keyCtx, sqlite3CodecGetDefaultAttachCipher(parm)); + rc += sqlite3CodecSetIter(keyCtx, sqlite3CodecGetDefaultAttachKdfIter(parm)); if( hmacAlgo!=0 ){ rc += sqlite3CodecSetHmacAlgorithm(keyCtx, hmacAlgo); } - int attachKdfAlgo = sqlite3CodecGetDefaultAttachKdfAlgo(); + int attachKdfAlgo = sqlite3CodecGetDefaultAttachKdfAlgo(parm); if( attachKdfAlgo!=0 ){ rc += sqlite3CodecSetKdfAlgorithm(keyCtx, attachKdfAlgo); } - int cipherPageSize = sqlite3CodecGetDefaultAttachPageSize(); + int cipherPageSize = sqlite3CodecGetDefaultAttachPageSize(parm); if( cipherPageSize!=0 ){ rc += sqlite3CodecSetCipherPageSize(ctx, cipherPageSize); if ( rc != SQLITE_OK ) { @@ -245413,31 +245440,32 @@ CODEC_STATIC void sqlite3CodecFreeContext(CodecContext *ctx){ #ifdef SQLITE_CODEC_ATTACH_CHANGED CODEC_STATIC int sqlite3CodecInitContext(CodecContext *ctx, Btree *p, const void *zKey, int nKey, int nDb){ int attachFlag = (nDb > 1) ? 1 : 0; + int defaultPageSz = attachFlag ? p->db->codecParm.pageSize : DEFAULT_PAGE_SIZE; #else CODEC_STATIC int sqlite3CodecInitContext(CodecContext *ctx, Btree *p, const void *zKey, int nKey){ + int defaultPageSz = DEFAULT_PAGE_SIZE; #endif sqlite3_file *fd = p->pBt->pPager->fd; ctx->pBt = p; ctx->savePassword = 0; - ctx->buffer = (unsigned char *)sqlite3Malloc(DEFAULT_PAGE_SIZE); + ctx->buffer = (unsigned char *)sqlite3Malloc(defaultPageSz); ctx->readCtx = (KeyContext *)sqlite3Malloc(sizeof(KeyContext)); ctx->writeCtx = (KeyContext *)sqlite3Malloc(sizeof(KeyContext)); if(ctx->buffer == NULL || ctx->readCtx == NULL || ctx->writeCtx == NULL){ sqlite3CodecFreeContext(ctx); return SQLITE_NOMEM; } - errno_t memsetRc = memset_s(ctx->buffer, DEFAULT_PAGE_SIZE, 0, DEFAULT_PAGE_SIZE); + errno_t memsetRc = memset_s(ctx->buffer, defaultPageSz, 0, defaultPageSz); memsetRc += memset_s(ctx->readCtx, sizeof(KeyContext), 0, sizeof(KeyContext)); memsetRc += memset_s(ctx->writeCtx, sizeof(KeyContext), 0, sizeof(KeyContext)); if(memsetRc != EOK){ sqlite3CodecFreeContext(ctx); return SQLITE_ERROR; } - ctx->readCtx->codecConst.cipherPageSize = DEFAULT_PAGE_SIZE; - ctx->writeCtx->codecConst.cipherPageSize = DEFAULT_PAGE_SIZE; + ctx->readCtx->codecConst.cipherPageSize = defaultPageSz; + ctx->writeCtx->codecConst.cipherPageSize = defaultPageSz; #ifdef SQLITE_CODEC_ATTACH_CHANGED - int attachHmacAlgo = sqlite3CodecGetDefaultAttachHmacAlgo(); - int rc = sqlite3CodecInitKeyContext(ctx, p, zKey, nKey, attachFlag, attachHmacAlgo); + int rc = sqlite3CodecInitKeyContext(ctx, p, zKey, nKey, attachFlag); #else int rc = sqlite3CodecInitKeyContext(ctx, p, zKey, nKey); #endif @@ -245879,11 +245907,12 @@ int sqlite3CodecPragma(sqlite3 *db, int iDb, Parse *parse, const char *zLeft, co } CodecContext *ctx = (CodecContext *)(p->pBt->pPager->pCodec); #ifdef SQLITE_CODEC_ATTACH_CHANGED + CodecParameter *parm = &db->codecParm; if(sqlite3StrICmp(zLeft, "cipher_default_attach_cipher") == 0 && zRight != NULL){ - (void)sqlite3CodecSetDefaultAttachCipher(zRight); + (void)sqlite3CodecSetDefaultAttachCipher(parm, zRight); return 1; }else if(sqlite3StrICmp(zLeft, "cipher_default_attach_kdf_iter") == 0 && zRight != NULL){ - (void)sqlite3CodecSetDefaultAttachKdfIter(atoi(zRight)); + (void)sqlite3CodecSetDefaultAttachKdfIter(parm, atoi(zRight)); return 1; }else if( sqlite3StrICmp(zLeft, "cipher_default_attach_hmac_algo")==0 && zRight!=NULL ){ /* @@ -245891,31 +245920,31 @@ int sqlite3CodecPragma(sqlite3 *db, int iDb, Parse *parse, const char *zLeft, co ** This behavior is to ensure backward compatible. */ if( sqlite3_stricmp(zRight, CIPHER_HMAC_ALGORITHM_NAME_SHA1)==0 ){ - sqlite3CodecSetDefaultAttachHmacAlgo(CIPHER_HMAC_ALGORITHM_SHA1); - sqlite3CodecSetDefaultAttachKdfAlgo(CIPHER_KDF_ALGORITHM_SHA1); + sqlite3CodecSetDefaultAttachHmacAlgo(parm, CIPHER_HMAC_ALGORITHM_SHA1); + sqlite3CodecSetDefaultAttachKdfAlgo(parm, CIPHER_KDF_ALGORITHM_SHA1); }else if( sqlite3_stricmp(zRight, CIPHER_HMAC_ALGORITHM_NAME_SHA256)==0 ){ - sqlite3CodecSetDefaultAttachHmacAlgo(CIPHER_HMAC_ALGORITHM_SHA256); - sqlite3CodecSetDefaultAttachKdfAlgo(CIPHER_KDF_ALGORITHM_SHA256); + sqlite3CodecSetDefaultAttachHmacAlgo(parm, CIPHER_HMAC_ALGORITHM_SHA256); + sqlite3CodecSetDefaultAttachKdfAlgo(parm, CIPHER_KDF_ALGORITHM_SHA256); }else if( sqlite3_stricmp(zRight, CIPHER_HMAC_ALGORITHM_NAME_SHA512)==0 ){ - sqlite3CodecSetDefaultAttachHmacAlgo(CIPHER_HMAC_ALGORITHM_SHA512); - sqlite3CodecSetDefaultAttachKdfAlgo(CIPHER_KDF_ALGORITHM_SHA512); + sqlite3CodecSetDefaultAttachHmacAlgo(parm, CIPHER_HMAC_ALGORITHM_SHA512); + sqlite3CodecSetDefaultAttachKdfAlgo(parm, CIPHER_KDF_ALGORITHM_SHA512); }else{ return 0; } return 1; }else if( sqlite3StrICmp(zLeft, "cipher_default_attach_kdf_algo")==0 && zRight!=NULL ){ if( sqlite3_stricmp(zRight, CIPHER_KDF_ALGORITHM_NAME_SHA1)==0 ){ - sqlite3CodecSetDefaultAttachKdfAlgo(CIPHER_KDF_ALGORITHM_SHA1); + sqlite3CodecSetDefaultAttachKdfAlgo(parm, CIPHER_KDF_ALGORITHM_SHA1); }else if( sqlite3_stricmp(zRight, CIPHER_KDF_ALGORITHM_NAME_SHA256)==0 ){ - sqlite3CodecSetDefaultAttachKdfAlgo(CIPHER_KDF_ALGORITHM_SHA256); + sqlite3CodecSetDefaultAttachKdfAlgo(parm, CIPHER_KDF_ALGORITHM_SHA256); }else if( sqlite3_stricmp(zRight, CIPHER_KDF_ALGORITHM_NAME_SHA512)==0 ){ - sqlite3CodecSetDefaultAttachKdfAlgo(CIPHER_KDF_ALGORITHM_SHA512); + sqlite3CodecSetDefaultAttachKdfAlgo(parm, CIPHER_KDF_ALGORITHM_SHA512); }else{ return 0; } return 1; }else if( sqlite3StrICmp(zLeft, "cipher_default_attach_page_size")==0 && zRight!=NULL ){ - (void)sqlite3CodecSetDefaultAttachPageSize(atoi(zRight)); + (void)sqlite3CodecSetDefaultAttachPageSize(parm, atoi(zRight)); return 1; } #endif -- Gitee From fa913e0093b4f1350c6e4a7337f7105f0466c418 Mon Sep 17 00:00:00 2001 From: Lee <18800203378@163.com> Date: Wed, 27 Nov 2024 20:49:04 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E6=B7=BB=E5=8A=A0busy=E6=97=B6=E7=BB=B4?= =?UTF-8?q?=E6=B5=8B=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: ryne3366 --- src/sqlite3.c | 391 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 306 insertions(+), 85 deletions(-) diff --git a/src/sqlite3.c b/src/sqlite3.c index 2b77ee8..7504a3d 100644 --- a/src/sqlite3.c +++ b/src/sqlite3.c @@ -874,6 +874,7 @@ SQLITE_API int sqlite3_exec( #define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8)) #define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8)) #define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8)) +#define SQLITE_WARNING_DUMP (SQLITE_WARNING | (2<<8)) #define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8)) #define SQLITE_OK_LOAD_PERMANENTLY (SQLITE_OK | (1<<8)) #define SQLITE_OK_SYMLINK (SQLITE_OK | (2<<8)) /* internal use only */ @@ -36767,6 +36768,44 @@ SQLITE_PRIVATE int sqlite3KvvfsInit(void){ #endif /************** End of os_kv.c ***********************************************/ +/************** Define dump function *****************************************/ +#if SQLITE_OS_UNIX +#define DB_LOCK_NUM 3 +#define WAL_LOCK_NUM 9 +// 8 wal lock, 1 SHM_DMS lock, 1 TRX lock +#define MAX_LOCK_NUM (WAL_LOCK_NUM + 1) +#define SHM_DMS_IDX (WAL_LOCK_NUM - 1) +#define TRX_LOCK_IDX WAL_LOCK_NUM +#define LOCK_BY_PROCESS 1 +#define LOCK_BY_THREAD 0 +#define DUMP_BUF_MAX_LEN 180 +#define DUMP_MAX_STR_LEN 21 + +typedef struct LocalLockStatus { + u8 busyLockIdx; + u8 busyLockType; + u8 lockByProcess; + u8 reserved; + u32 lockLen; + u32 busyLine; + u8 lockStatus[MAX_LOCK_NUM]; // last index is trx lock +} LocalLockStatus; +__thread LocalLockStatus g_lockStatus = {0}; + +#define MARK_LAST_BUSY_LINE(rc) {if ((rc)==SQLITE_BUSY || (rc) == SQLITE_LOCKED) g_lockStatus.busyLine = __LINE__;} +static void ResetLockStatus(void); +static void TryRecordTid(int *tidBuf, int ofs, int lockLen); +static void TryClearTid(int *tidBuf, int ofs, int lockLen); +static void MarkLockBusy(u32 lockIdx, u32 lockLen, u8 lockType, u8 lockByProcess); +static void MarkLockStatus(u32 lockIdx, u32 lockLen, u8 lockType); +static void MarkLockStatusByRc(int rc, u32 lockIdx, u32 lockLen, u8 lockType, u8 lockByProcess); +#else +#define MARK_LAST_BUSY_LINE(rc) +#define ResetLockStatus(void) +#define MarkLockBusy(A, B, C, D) +#define MarkLockStatusByRc(A, B, C, D, E) +#endif +/************** End define dump function *************************************/ /************** Begin file os_unix.c *****************************************/ /* ** 2004 May 22 @@ -38541,6 +38580,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ if( pFile->eFileLock>=eFileLock ){ OSTRACE(("LOCK %d %s ok (already held) (unix)\n", pFile->h, azFileLock(eFileLock))); + MarkLockStatus(TRX_LOCK_IDX, 1, eFileLock); return SQLITE_OK; } @@ -38565,6 +38605,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ (pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK)) ){ rc = SQLITE_BUSY; + MarkLockBusy(TRX_LOCK_IDX, 1, eFileLock, LOCK_BY_THREAD); goto end_lock; } @@ -38580,6 +38621,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ pFile->eFileLock = SHARED_LOCK; pInode->nShared++; pInode->nLock++; + MarkLockStatus(TRX_LOCK_IDX, 1, eFileLock); goto end_lock; } @@ -38601,11 +38643,11 @@ static int unixLock(sqlite3_file *id, int eFileLock){ if( rc!=SQLITE_BUSY ){ storeLastErrno(pFile, tErrno); } + MarkLockStatusByRc(rc, TRX_LOCK_IDX, 1, SHARED_LOCK, LOCK_BY_PROCESS); goto end_lock; } } - /* If control gets to this point, then actually go ahead and make ** operating system calls for the specified lock. */ @@ -38621,7 +38663,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ tErrno = errno; rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); } - + MarkLockStatusByRc(rc, TRX_LOCK_IDX, 1, SHARED_LOCK, LOCK_BY_PROCESS); /* Drop the temporary PENDING lock */ lock.l_start = PENDING_BYTE; lock.l_len = 1L; @@ -38646,6 +38688,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ /* We are trying for an exclusive lock but another thread in this ** same process is still holding a shared lock. */ rc = SQLITE_BUSY; + MarkLockBusy(TRX_LOCK_IDX, 1, eFileLock, LOCK_BY_THREAD); }else{ /* The request was for a RESERVED or EXCLUSIVE lock. It is ** assumed that there is a SHARED or greater lock on the file @@ -38670,6 +38713,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ storeLastErrno(pFile, tErrno); } } + MarkLockStatusByRc(rc, TRX_LOCK_IDX, 1, eFileLock, LOCK_BY_PROCESS); } @@ -38867,7 +38911,6 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ pFile->eFileLock = NO_LOCK; } } - /* Decrement the count of locks against this same file. When the ** count reaches zero, close any other file descriptors whose close ** was deferred because of outstanding locks. @@ -41179,6 +41222,7 @@ struct unixShmNode { int nRef; /* Number of unixShm objects pointing to this */ unixShm *pFirst; /* All unixShm objects pointing to this */ int aLock[SQLITE_SHM_NLOCK]; /* # shared locks on slot, -1==excl lock */ + int aLockTid[SQLITE_SHM_NLOCK]; #ifdef SQLITE_DEBUG u8 exclMask; /* Mask of exclusive locks held */ u8 sharedMask; /* Mask of shared locks held */ @@ -41421,6 +41465,8 @@ static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){ rc = SQLITE_READONLY_CANTINIT; }else{ rc = unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1); + MarkLockStatusByRc(rc, SHM_DMS_IDX, 1, EXCLUSIVE_LOCK, LOCK_BY_PROCESS); + MARK_LAST_BUSY_LINE(rc); /* The first connection to attach must truncate the -shm file. We ** truncate to 3 bytes (an arbitrary small number, less than the ** -shm header size) rather than 0 as a system debugging aid, to @@ -41432,11 +41478,15 @@ static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){ } }else if( lock.l_type==F_WRLCK ){ rc = SQLITE_BUSY; + MarkLockStatusByRc(rc, SHM_DMS_IDX, 1, SHARED_LOCK, LOCK_BY_PROCESS); + MARK_LAST_BUSY_LINE(rc); } if( rc==SQLITE_OK ){ assert( lock.l_type==F_UNLCK || lock.l_type==F_RDLCK ); rc = unixShmSystemLock(pDbFd, F_RDLCK, UNIX_SHM_DMS, 1); + MarkLockStatusByRc(rc, SHM_DMS_IDX, 1, SHARED_LOCK, LOCK_BY_PROCESS); + MARK_LAST_BUSY_LINE(rc); } return rc; } @@ -41821,7 +41871,7 @@ static int unixShmLock( return SQLITE_IOERR_SHMLOCK; } aLock = pShmNode->aLock; - + int *aLockTid = pShmNode->aLockTid; assert( pShmNode==pDbFd->pInode->pShmNode ); assert( pShmNode->pInode==pDbFd->pInode ); assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK ); @@ -41860,6 +41910,7 @@ static int unixShmLock( assert( n>1 || mask==(1<pShmMutex); assert( assertLockingArrayOk(pShmNode) ); + u8 useProcessLock = LOCK_BY_THREAD; if( flags & SQLITE_SHM_UNLOCK ){ if( (p->exclMask|p->sharedMask) & mask ){ int ii; @@ -41870,21 +41921,22 @@ static int unixShmLock( bUnlock = 0; } } - if( bUnlock ){ rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n); if( rc==SQLITE_OK ){ memset(&aLock[ofst], 0, sizeof(int)*n); } + useProcessLock = LOCK_BY_PROCESS; }else if( ALWAYS(p->sharedMask & (1<1 ); aLock[ofst]--; } - + MarkLockStatusByRc(rc, ofst, n, NO_LOCK, useProcessLock); /* Undo the local locks */ if( rc==SQLITE_OK ){ p->exclMask &= ~mask; p->sharedMask &= ~mask; + TryClearTid(aLockTid, ofst, n); } } }else if( flags & SQLITE_SHM_SHARED ){ @@ -41895,12 +41947,14 @@ static int unixShmLock( rc = SQLITE_BUSY; }else if( aLock[ofst]==0 ){ rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n); + useProcessLock = LOCK_BY_PROCESS; } - + MarkLockStatusByRc(rc, ofst, n, SHARED_LOCK, useProcessLock); /* Get the local shared locks */ if( rc==SQLITE_OK ){ p->sharedMask |= mask; aLock[ofst]++; + TryRecordTid(aLockTid, ofst, n); } } }else{ @@ -41919,14 +41973,17 @@ static int unixShmLock( ** also update the in-memory values. */ if( rc==SQLITE_OK ){ rc = unixShmSystemLock(pDbFd, F_WRLCK, ofst+UNIX_SHM_BASE, n); + useProcessLock = LOCK_BY_PROCESS; if( rc==SQLITE_OK ){ assert( (p->sharedMask & mask)==0 ); p->exclMask |= mask; for(ii=ofst; iipShmMutex); @@ -59794,6 +59851,7 @@ static int syncJournal(Pager *pPager, int newHdr){ assert( !pagerUseWal(pPager) ); rc = sqlite3PagerExclusiveLock(pPager); + MARK_LAST_BUSY_LINE(rc); if( rc!=SQLITE_OK ) return rc; if( !pPager->noSync ){ @@ -60703,6 +60761,7 @@ static int hasHotJournal(Pager *pPager, int *pExists){ sqlite3OsDelete(pVfs, pPager->zJournal, 0); if( !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK); } + MARK_LAST_BUSY_LINE(rc); sqlite3EndBenignMalloc(); }else{ /* The journal file exists and no other connection has a reserved @@ -60792,6 +60851,7 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){ assert( pPager->tempFile==0 || pPager->eLock==EXCLUSIVE_LOCK ); rc = pager_wait_on_lock(pPager, SHARED_LOCK); + MARK_LAST_BUSY_LINE(rc); if( rc!=SQLITE_OK ){ assert( pPager->eLock==NO_LOCK || pPager->eLock==UNKNOWN_LOCK ); goto failed; @@ -60828,6 +60888,7 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){ ** downgraded to SHARED_LOCK before this function returns. */ rc = pagerLockDb(pPager, EXCLUSIVE_LOCK); + MARK_LAST_BUSY_LINE(rc); if( rc!=SQLITE_OK ){ goto failed; } @@ -61442,6 +61503,7 @@ SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory */ if( pPager->exclusiveMode && sqlite3WalExclusiveMode(pPager->pWal, -1) ){ rc = pagerLockDb(pPager, EXCLUSIVE_LOCK); + MARK_LAST_BUSY_LINE(rc); if( rc!=SQLITE_OK ){ return rc; } @@ -61454,6 +61516,7 @@ SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory ** holds the write-lock. If possible, the upper layer will call it. */ rc = sqlite3WalBeginWriteTransaction(pPager->pWal); + MARK_LAST_BUSY_LINE(rc); }else{ /* Obtain a RESERVED lock on the database file. If the exFlag parameter ** is true, then immediately upgrade this to an EXCLUSIVE lock. The @@ -61461,8 +61524,10 @@ SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory ** lock, but not when obtaining the RESERVED lock. */ rc = pagerLockDb(pPager, RESERVED_LOCK); + MARK_LAST_BUSY_LINE(rc); if( rc==SQLITE_OK && exFlag ){ rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); + MARK_LAST_BUSY_LINE(rc); } } @@ -62963,6 +63028,7 @@ SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){ if( pPager->eState==PAGER_READER ){ assert( rc==SQLITE_OK ); rc = pagerLockDb(pPager, RESERVED_LOCK); + MARK_LAST_BUSY_LINE(rc); } if( rc==SQLITE_OK ){ sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); @@ -63127,6 +63193,7 @@ static int pagerOpenWal(Pager *pPager){ */ if( pPager->exclusiveMode ){ rc = pagerExclusiveLock(pPager); + MARK_LAST_BUSY_LINE(rc); } /* Open the connection to the log file. If this operation fails, @@ -63210,6 +63277,7 @@ SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){ if( !pPager->pWal ){ int logexists = 0; rc = pagerLockDb(pPager, SHARED_LOCK); + MARK_LAST_BUSY_LINE(rc); if( rc==SQLITE_OK ){ rc = sqlite3OsAccess( pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &logexists @@ -63225,6 +63293,7 @@ SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){ */ if( rc==SQLITE_OK && pPager->pWal ){ rc = pagerExclusiveLock(pPager); + MARK_LAST_BUSY_LINE(rc); if( rc==SQLITE_OK ){ rc = sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize, (u8*)pPager->pTmpSpace); @@ -64599,6 +64668,7 @@ static int walIndexRecover(Wal *pWal){ iLock = WAL_ALL_BUT_WRITE + pWal->ckptLock; rc = walLockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock); if( rc ){ + MARK_LAST_BUSY_LINE(rc); return rc; } @@ -65436,6 +65506,7 @@ static int walCheckpoint( if( mxSafeFrame>y ){ assert( y<=pWal->hdr.mxFrame ); rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1); + MARK_LAST_BUSY_LINE(rc); if( rc==SQLITE_OK ){ u32 iMark = (i==1 ? mxSafeFrame : READMARK_NOT_USED); AtomicStore(pInfo->aReadMark+i, iMark); @@ -65528,6 +65599,8 @@ static int walCheckpoint( /* Release the reader lock held while backfilling */ walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1); + } else { + MARK_LAST_BUSY_LINE(rc); } if( rc==SQLITE_BUSY ){ @@ -65546,11 +65619,13 @@ static int walCheckpoint( assert( pWal->writeLock ); if( pInfo->nBackfillhdr.mxFrame ){ rc = SQLITE_BUSY; + MARK_LAST_BUSY_LINE(rc); }else if( eMode>=SQLITE_CHECKPOINT_RESTART ){ u32 salt1; sqlite3_randomness(4, &salt1); assert( pInfo->nBackfill==pWal->hdr.mxFrame ); rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(1), WAL_NREADER-1); + MARK_LAST_BUSY_LINE(rc); if( rc==SQLITE_OK ){ if( eMode==SQLITE_CHECKPOINT_TRUNCATE ){ /* IMPLEMENTATION-OF: R-44699-57140 This mode works the same way as @@ -65648,8 +65723,9 @@ SQLITE_PRIVATE int sqlite3WalClose( walLimitSize(pWal, 0); } } + } else { + MARK_LAST_BUSY_LINE(rc); } - walIndexClose(pWal, isDelete); sqlite3OsClose(pWal->pWalFd); if( isDelete ){ @@ -65802,6 +65878,7 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){ walUnlockShared(pWal, WAL_WRITE_LOCK); rc = SQLITE_READONLY_RECOVERY; } + MARK_LAST_BUSY_LINE(rc); }else{ int bWriteLock = pWal->writeLock; if( bWriteLock || SQLITE_OK==(rc = walLockWriter(pWal)) ){ @@ -65822,6 +65899,7 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){ walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); } } + MARK_LAST_BUSY_LINE(rc); } } @@ -65841,6 +65919,7 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){ ** writer truncated the WAL out from under it. If that happens, it ** indicates that a writer has fixed the SHM file for us, so retry */ if( rc==SQLITE_IOERR_SHORT_READ ) rc = WAL_RETRY; + MARK_LAST_BUSY_LINE(rc); } pWal->exclusiveMode = WAL_NORMAL_MODE; } @@ -66072,7 +66151,7 @@ static int walBeginShmUnreliable(Wal *pWal, int *pChanged){ ** so it takes care to hold an exclusive lock on the corresponding ** WAL_READ_LOCK() while changing values. */ -static void printLockInfoUsingWal(Wal *pWal); +static void DumpLocksByWal(Wal *pWal); static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ volatile WalCkptInfo *pInfo; /* Checkpoint information in wal-index */ u32 mxReadMark; /* Largest aReadMark[] value */ @@ -66111,7 +66190,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ } if( cnt>=10 ) nDelay = (cnt-9)*(cnt-9)*39; #if SQLITE_OS_UNIX - if( cnt>=15 ) printLockInfoUsingWal(pWal); + if( cnt>=15 ) DumpLocksByWal(pWal); #endif /* SQLITE_OS_UNIX */ sqlite3OsSleep(pWal->pVfs, nDelay); } @@ -66139,11 +66218,14 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ ** must be zeroed before the requested page is returned. */ rc = WAL_RETRY; + MARK_LAST_BUSY_LINE(SQLITE_BUSY); }else if( SQLITE_OK==(rc = walLockShared(pWal, WAL_RECOVER_LOCK)) ){ walUnlockShared(pWal, WAL_RECOVER_LOCK); rc = WAL_RETRY; + MARK_LAST_BUSY_LINE(SQLITE_BUSY); }else if( rc==SQLITE_BUSY ){ rc = SQLITE_BUSY_RECOVERY; + MARK_LAST_BUSY_LINE(SQLITE_BUSY); } } if( rc!=SQLITE_OK ){ @@ -66166,6 +66248,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ ** and can be safely ignored. */ rc = walLockShared(pWal, WAL_READ_LOCK(0)); + MARK_LAST_BUSY_LINE(SQLITE_BUSY); walShmBarrier(pWal); if( rc==SQLITE_OK ){ if( memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) ){ @@ -66183,6 +66266,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ ** it finished. Leaving a corrupt image in the database file. */ walUnlockShared(pWal, WAL_READ_LOCK(0)); + MARK_LAST_BUSY_LINE(SQLITE_BUSY); return WAL_RETRY; } pWal->readLock = 0; @@ -66227,6 +66311,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ }else if( rc!=SQLITE_BUSY ){ return rc; } + MARK_LAST_BUSY_LINE(rc); } } if( mxI==0 ){ @@ -66236,6 +66321,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ rc = walLockShared(pWal, WAL_READ_LOCK(mxI)); if( rc ){ + MARK_LAST_BUSY_LINE(rc); return rc==SQLITE_BUSY ? WAL_RETRY : rc; } /* Now that the read-lock has been obtained, check that neither the @@ -66278,6 +66364,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) ){ walUnlockShared(pWal, WAL_READ_LOCK(mxI)); + MARK_LAST_BUSY_LINE(rc); return WAL_RETRY; }else{ assert( mxReadMark<=pWal->hdr.mxFrame ); @@ -66404,7 +66491,7 @@ SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ (void)walEnableBlocking(pWal); rc = walLockShared(pWal, WAL_CKPT_LOCK); walDisableBlocking(pWal); - + MARK_LAST_BUSY_LINE(rc); if( rc!=SQLITE_OK ){ return rc; } @@ -67241,7 +67328,7 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint( assert( pWal->ckptLock==0 ); assert( pWal->writeLock==0 ); - + ResetLockStatus(); /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked ** in the SQLITE_CHECKPOINT_PASSIVE mode. */ assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 ); @@ -67263,6 +67350,7 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint( ** it will not be invoked in this case. */ rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); + MARK_LAST_BUSY_LINE(rc); testcase( rc==SQLITE_BUSY ); testcase( rc!=SQLITE_OK && xBusy2!=0 ); if( rc==SQLITE_OK ){ @@ -67279,6 +67367,7 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint( */ if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){ rc = walBusyLock(pWal, xBusy2, pBusyArg, WAL_WRITE_LOCK, 1); + MARK_LAST_BUSY_LINE(rc); if( rc==SQLITE_OK ){ pWal->writeLock = 1; }else if( rc==SQLITE_BUSY ){ @@ -71032,7 +71121,7 @@ static void pageReinit(DbPage *pData){ } } -static void printLockInfoUsingPager(Pager *pPager); +static void DumpLocksByPager(Pager *pPager); /* ** Invoke the busy handler for a btree. */ @@ -71042,8 +71131,8 @@ static int btreeInvokeBusyHandler(void *pArg){ assert( sqlite3_mutex_held(pBt->db->mutex) ); int rc = sqlite3InvokeBusyHandler(&pBt->db->busyHandler); #if SQLITE_OS_UNIX - if( rc==0 ){ - printLockInfoUsingPager( pBt->pPager ); + if (rc == 0) { + DumpLocksByPager(pBt->pPager); } #endif /* SQLITE_OS_UNIX */ return rc; @@ -72134,7 +72223,7 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVers sqlite3BtreeEnter(p); btreeIntegrity(p); - + ResetLockStatus(); /* If the btree is already in a write-transaction, or it ** is already in a read-transaction and a read-transaction ** is requested, this is a no-op. @@ -79504,6 +79593,7 @@ SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree *p, int eMode, int *pnLog, int * sqlite3BtreeEnter(p); if( pBt->inTransaction!=TRANS_NONE ){ rc = SQLITE_LOCKED; + MARK_LAST_BUSY_LINE(rc); }else{ rc = sqlite3PagerCheckpoint(pBt->pPager, p->db, eMode, pnLog, pnCkpt); } @@ -85350,6 +85440,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){ nTrans++; } rc = sqlite3PagerExclusiveLock(pPager); + MARK_LAST_BUSY_LINE(rc); sqlite3BtreeLeave(pBt); } } @@ -246220,106 +246311,236 @@ export_finish: } /************** End file hw_codec.c *****************************************/ #endif - #if SQLITE_OS_UNIX -#define DB_LOCK_NUM 3 -#define DB_SHARED_LOCK_OFFSET 2 -#define WAL_LOCK_NUM 8 -#define WAL_READ_LOCK_POS 3 -#define LOCK_NUM (DB_LOCK_NUM+WAL_LOCK_NUM) -static void printLockInfo(unixFile *dbFile, int walStat) +#if defined(__linux__) && !defined(gettid) +#include +#define gettid() syscall(__NR_gettid) +#endif +static void ResetLockStatus(void) { - const char *lockType[DB_LOCK_NUM] = {"F_RDLCK", "F_WRLCK", "F_UNLCK"}; + (void)memset(&g_lockStatus, 0, sizeof(g_lockStatus)); +} +/* +** Record lock info, correspond wal aLock buf, 1 aLock: 1 +*/ +static void TryRecordTid(int *tidBuf, int ofs, int lockLen) +{ + int lockOfs = ofs + lockLen; + for (int i = ofs; i < lockOfs; i++) { + if (tidBuf[i] == 0) { + tidBuf[i] = gettid(); + } + } +} +/* +** Clear locks info. +*/ +static void TryClearTid(int *tidBuf, int ofs, int lockLen) +{ + int lockOfs = ofs + lockLen; + for (int i = ofs; i < lockOfs; i++) { + if (tidBuf[i] == gettid()) { + tidBuf[i] = 0; + } + } +} - sqlite3_log(SQLITE_WARNING, "*** SQLITE_LOG DB Lock ***"); - if( dbFile==NULL ){ - sqlite3_log(SQLITE_WARNING, "NO DB FILE !"); +static void MarkLockBusy(u32 lockIdx, u32 lockLen, u8 lockType, u8 lockByProcess) +{ + g_lockStatus.busyLockIdx = lockIdx; + g_lockStatus.busyLockType = lockType; + g_lockStatus.lockByProcess = lockByProcess; + g_lockStatus.lockLen = lockLen; +} + +static void MarkLockStatus(u32 lockIdx, u32 lockLen, u8 lockType) +{ + if ((lockIdx + lockLen) > MAX_LOCK_NUM || lockLen == 0) { + sqlite3_log(SQLITE_ERROR, "Unexpect lock index %u lockLen %d!", lockIdx, lockLen); return; } - unixInodeInfo *inode = dbFile->pInode; - if( inode==NULL ){ - sqlite3_log(SQLITE_ERROR, "Inode is NULL !"); + if (lockIdx == g_lockStatus.busyLockIdx) { + g_lockStatus.busyLockIdx = 0; + g_lockStatus.lockLen = 0; + } + if (lockLen == 1) { + g_lockStatus.lockStatus[lockIdx] = lockType; + } else { + size_t len = sizeof(u8) * lockLen; + (void)memset(&g_lockStatus.lockStatus[lockIdx], lockType, len); + } +} + +static void MarkLockStatusByRc(int rc, u32 lockIdx, u32 lockLen, u8 lockType, u8 lockByProcess) +{ + if (rc == SQLITE_BUSY) { + MarkLockBusy(lockIdx, lockLen, lockType, lockByProcess); return; } - sqlite3_log(SQLITE_WARNING, "fileLock %d inodeRef %d inodeLockCnt %d inodeFileLock %d inodeProcessLock %d", - dbFile->eFileLock, inode->nRef, inode->nLock, inode->eFileLock, inode->bProcessLock); - - /* Set param list */ - int fdDb = dbFile->h; - const char *lockNameList[LOCK_NUM] = {"pending lock ", - "reserved lock", - "shared lock ", - "wal_write lock ", - "wal_ckpt lock ", - "wal_recover lock"}; - for(int i=DB_LOCK_NUM+WAL_READ_LOCK_POS; ipInode->pShmNode; - int hasShm = (dbFile->pShm==NULL || pShmNode==NULL) ? 0 : 1; - off_t startPos = PENDING_BYTE; - for(int i=0; ihShm; - } - off_t lockLen = i==DB_SHARED_LOCK_OFFSET ? SHARED_SIZE : 1; - struct flock flDb = { .l_type=F_WRLCK, .l_start=startPos, .l_len=lockLen, .l_whence=SEEK_SET }; - int ret = osFcntl(fdDb, F_GETLK, &flDb); - if( ret!=SQLITE_OK ){ - sqlite3_log(SQLITE_ERROR, "Get File Lock Info Fail! errno: %d", ret); - return; - } - if( flDb.l_type!=F_UNLCK ){ - sqlite3_log(SQLITE_WARNING, "lock name: %s, pos: 0x%x, len: 0x%x, lock type: %s, owner pId: %d", - lockNameList[i], startPos, lockLen, lockType[flDb.l_type], flDb.l_pid); + if (rc == SQLITE_OK) { + MarkLockStatus(lockIdx, lockLen, lockType); + } + // only busy error code need record + if (lockIdx == g_lockStatus.busyLockIdx && g_lockStatus.lockLen != 0) { + g_lockStatus.busyLockIdx = 0; + g_lockStatus.busyLockType = NO_LOCK; + g_lockStatus.lockLen = 0; + } +} + +static inline const char *TrxLockName(int eLock) +{ + return eLock == NO_LOCK ? "NO_LOCK" : + eLock == RESERVED_LOCK ? "RESERVED" : + eLock == EXCLUSIVE_LOCK ? "EXCLUSIVE" : + eLock == SHARED_LOCK ? "SHARED" : + eLock == UNKNOWN_LOCK ? "UNKNOWN" : "?error?"; +} + +static inline const char *IdxToLockName(u32 idx) +{ + const char *lockName[MAX_LOCK_NUM] = {"write", "ckpt", "recover", "read0", + "read1", "read2", "read3", "read4", "wal_dms", "trxLock"}; + return (idx < MAX_LOCK_NUM) ? lockName[idx] : "errLock"; +} + +static void DumpHandleLock(char *dumpBuf, int dumpBufLen) +{ + char *tmp = dumpBuf; + u8 *lockStatus = g_lockStatus.lockStatus; + int availLen = dumpBufLen - 1; + dumpBuf[availLen] = '\0'; + for (int i = 0; i < MAX_LOCK_NUM && availLen > DUMP_MAX_STR_LEN; i++) { + if (lockStatus[i] != NO_LOCK) { + tmp[0] = '\0'; + sqlite3_snprintf(availLen, tmp, "<%s, %s>", IdxToLockName((u32)i), TrxLockName(lockStatus[i])); + int len = strlen(tmp); + tmp += len; + availLen -= len; } - startPos++; } - - /* thread WAL Lock Info */ - for(int i=0; ipShm->pShmNode->aLock[i] ){ - sqlite3_log(SQLITE_WARNING, "Local WAL Lock[%d] for DB file: %d", i, dbFile->pShm->pShmNode->aLock[i]); + sqlite3_log(SQLITE_WARNING_DUMP, "[SQLite]BusyLine:%d, idx:%d, type:%d, fileLock:%d, len:%d, handleLocks:%s", + g_lockStatus.busyLine, g_lockStatus.busyLockIdx, g_lockStatus.busyLockType, g_lockStatus.lockByProcess, + g_lockStatus.lockLen, tmp != dumpBuf ? dumpBuf : "none"); +} + +static const char *FlockToName(int l_type) +{ + return l_type == F_RDLCK ? "F_RDLCK" : + l_type == F_WRLCK ? "F_WRLCK" : + l_type == F_UNLCK ? "F_UNLCK" : "F_UNKNOWN"; +} + +static int DumpProcessLocks(int fd, struct flock *lock, const char *lockName, char *dumpBuf, int bufLen) +{ + dumpBuf[0] = '\0'; + if (osFcntl(fd, F_GETLK, lock) != SQLITE_OK) { + sqlite3_log(SQLITE_ERROR, "[SQLite]Get wal file lock ofs %u failed, errno: %d", lock->l_start, errno); + return 0; + } + if (lock->l_type != F_UNLCK) { + sqlite3_snprintf(bufLen, dumpBuf, "<%s, pid:%u, %s>", lockName, lock->l_pid, FlockToName(lock->l_type)); + return strlen(dumpBuf); + } + return 0; +} + +static void DumpTrxProcessLocks(unixFile *file, char *dumpBuf, int dumpBufLen) +{ + unixInodeInfo *inode = file->pInode; + if (inode == NULL) { + sqlite3_log(SQLITE_ERROR, "[SQLite]Inode is null!"); + return; + } + sqlite3_log(SQLITE_WARNING_DUMP, "[SQLite]acqLock:%s, dbRef:%d, lockCnt:%d, curLock:%s, processLock:%d", + TrxLockName(file->eFileLock), inode->nRef, inode->nLock, TrxLockName(inode->eFileLock), inode->bProcessLock); + const char *lockName[DB_LOCK_NUM] = {"pending", "reserved", "shared_first"}; + char *tmp = dumpBuf; + int availLen = dumpBufLen - 1; + dumpBuf[availLen] = '\0'; + for (int i = 0; i < DB_LOCK_NUM && availLen > DUMP_MAX_STR_LEN; i++) { + off_t ofs = i + PENDING_BYTE; + off_t lockLen = (ofs == SHARED_FIRST) ? SHARED_SIZE : 1; + struct flock lock = {.l_type = F_WRLCK, .l_start = ofs, .l_len = lockLen, .l_whence = SEEK_SET}; + int lockBufLen = DumpProcessLocks(file->h, &lock, lockName[i], tmp, availLen); + tmp += lockBufLen; + availLen -= lockBufLen; + } + if (tmp != dumpBuf) { + sqlite3_log(SQLITE_WARNING_DUMP, "[SQLite]Trx locks: %s", dumpBuf); + } +} + +static void DumpWalLocks(unixFile *file, u8 walEnabled, char *dumpBuf, int dumpBufLen) +{ + if (!walEnabled || file->pShm == NULL || file->pShm->pShmNode == NULL) { + sqlite3_log(SQLITE_ERROR, "[SQLite]Wal mode disabled!"); + return; + } + unixShmNode *pShmNode = file->pShm->pShmNode; + char *tmp = dumpBuf; + int availLen = dumpBufLen - 1; + dumpBuf[availLen] = '\0'; + for (int i = 0; i < WAL_LOCK_NUM && availLen > DUMP_MAX_STR_LEN; i++) { + if (pShmNode->aLock[i] && i < SQLITE_SHM_NLOCK) { + tmp[0] = '\0'; + sqlite3_snprintf(availLen, tmp, "<%s, %d, tid:%d>", IdxToLockName((u32)i), pShmNode->aLock[i], + pShmNode->aLockTid[i]); + int strLen = strlen(tmp); + tmp += strLen; + availLen -= strLen; } + off_t ofs = i + WALINDEX_LOCK_OFFSET; + struct flock lock = {.l_type = F_WRLCK, .l_start = ofs, .l_len = 1, .l_whence = SEEK_SET}; + int bufLen = DumpProcessLocks(pShmNode->hShm, &lock, IdxToLockName((u32)i), tmp, availLen); + tmp += bufLen; + availLen -= bufLen; + } + if (tmp != dumpBuf) { + sqlite3_log(SQLITE_WARNING_DUMP, "[SQLite]Wal locks: %s", dumpBuf); + } +} + +static void DumpLocksInfo(unixFile *file, int walEnabled) +{ + char *dumpBuf = sqlite3Malloc(DUMP_BUF_MAX_LEN); + if (dumpBuf == NULL) { + sqlite3_log(SQLITE_ERROR, "[SQLite]Can't alloc bufferSz %d for dump!", DUMP_BUF_MAX_LEN); + return; } + DumpHandleLock(dumpBuf, DUMP_BUF_MAX_LEN); + DumpTrxProcessLocks(file, dumpBuf, DUMP_BUF_MAX_LEN); + DumpWalLocks(file, walEnabled, dumpBuf, DUMP_BUF_MAX_LEN); + sqlite3_free(dumpBuf); } #ifndef SQLITE_OMIT_WAL -static void printLockInfoUsingWal(Wal *pWal) +static void DumpLocksByWal(Wal *pWal) { - if( pWal==NULL ){ + if (pWal == NULL) { sqlite3_log(SQLITE_ERROR, "Wal ptr is NULL!"); return; } - if( pWal->pVfs==NULL || sqlite3_stricmp(pWal->pVfs->zName, "unix")!=0 ){ + if (pWal->pVfs == NULL || sqlite3_stricmp(pWal->pVfs->zName, "unix") != 0) { return; } - printLockInfo((unixFile *)(pWal->pDbFd), 1); + DumpLocksInfo((unixFile *)(pWal->pDbFd), 1); } #endif /* #ifndef SQLITE_OMIT_WAL */ -static void printLockInfoUsingPager(Pager *pPager) +static void DumpLocksByPager(Pager *pPager) { - if( pPager==NULL ){ + if (pPager == NULL) { sqlite3_log(SQLITE_ERROR, "Pager ptr is NULL!"); return; } - if( pPager->pVfs==NULL || sqlite3_stricmp(pPager->pVfs->zName, "unix")!=0 ){ + if (pPager->pVfs == NULL || sqlite3_stricmp(pPager->pVfs->zName, "unix") != 0) { return; } #ifndef SQLITE_OMIT_WAL - printLockInfo((unixFile *)(pPager->fd), pPager->pWal!=NULL); + DumpLocksInfo((unixFile *)(pPager->fd), pPager->pWal != NULL); #else /* #ifndef SQLITE_OMIT_WAL */ - printLockInfo((unixFile *)(pPager->fd), 0); + DumpLocksInfo((unixFile *)(pPager->fd), 0); #endif /* #ifndef SQLITE_OMIT_WAL */ } #endif /* SQLITE_OS_UNIX */ -- Gitee From 3e697093b2a101ef8014b19accb8e04bf2634b1e Mon Sep 17 00:00:00 2001 From: MartinChoo <214582617@qq.com> Date: Thu, 21 Nov 2024 10:57:20 +0800 Subject: [PATCH 3/4] Report corruption when runtime detected Signed-off-by: MartinChoo <214582617@qq.com> --- include/sqlite3.h | 16 ++ src/sqlite3.c | 660 ++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 591 insertions(+), 85 deletions(-) diff --git a/include/sqlite3.h b/include/sqlite3.h index 445640f..e383b92 100644 --- a/include/sqlite3.h +++ b/include/sqlite3.h @@ -2120,6 +2120,21 @@ struct sqlite3_mem_methods { ** configuration setting is never used, then the default maximum is determined ** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option. If that ** compile-time option is not set, then the default maximum is 1073741824. +** +** [[SQLITE_CONFIG_CORRUPTION]]
SQLITE_CONFIG_CORRUPTION
+**
The SQLITE_CONFIG_CORRUPTION option is used to configure the SQLite +** global [ corruption error]. +** (^The SQLITE_CONFIG_CORRUPTION option takes two arguments: a pointer to a +** function with a call signature of void(*)(void*,const void*), +** and a pointer to void. ^If the function pointer is not NULL, it is +** invoked to process each data corruption event. ^If the +** function pointer is NULL, no=op will do when corruption detect. +** ^The void pointer that is the second argument to SQLITE_CONFIG_CORRUPTION is +** passed through as the first parameter to the application-defined corruption +** function whenever that function is invoked. ^The second parameter to +** the corruption function is a corruption message after formatting via [sqlite3_snprintf()]. +** In a multi-threaded application, the application-defined corruption +** function must be threadsafe.
** */ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ @@ -2151,6 +2166,7 @@ struct sqlite3_mem_methods { #define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */ #define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */ #define SQLITE_CONFIG_MEMDB_MAXSIZE 29 /* sqlite3_int64 */ +#define SQLITE_CONFIG_CORRUPTION 30 /* xCorruption */ /* ** CAPI3REF: Database Connection Configuration Options diff --git a/src/sqlite3.c b/src/sqlite3.c index 2b77ee8..a28a1b1 100644 --- a/src/sqlite3.c +++ b/src/sqlite3.c @@ -2430,6 +2430,21 @@ struct sqlite3_mem_methods { ** configuration setting is never used, then the default maximum is determined ** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option. If that ** compile-time option is not set, then the default maximum is 1073741824. +** +** [[SQLITE_CONFIG_CORRUPTION]]
SQLITE_CONFIG_CORRUPTION
+**
The SQLITE_CONFIG_CORRUPTION option is used to configure the SQLite +** global [ corruption error]. +** (^The SQLITE_CONFIG_CORRUPTION option takes two arguments: a pointer to a +** function with a call signature of void(*)(void*,const void*), +** and a pointer to void. ^If the function pointer is not NULL, it is +** invoked to process each data corruption event. ^If the +** function pointer is NULL, no=op will do when corruption detect. +** ^The void pointer that is the second argument to SQLITE_CONFIG_CORRUPTION is +** passed through as the first parameter to the application-defined corruption +** function whenever that function is invoked. ^The second parameter to +** the corruption function is a corruption message after formatting via [sqlite3_snprintf()]. +** In a multi-threaded application, the application-defined corruption +** function must be threadsafe.
** */ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ @@ -2461,6 +2476,7 @@ struct sqlite3_mem_methods { #define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */ #define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */ #define SQLITE_CONFIG_MEMDB_MAXSIZE 29 /* sqlite3_int64 */ +#define SQLITE_CONFIG_CORRUPTION 30 /* xCorruption */ /* ** CAPI3REF: Database Connection Configuration Options @@ -19527,6 +19543,8 @@ struct Sqlite3Config { int iOnceResetThreshold; /* When to reset OP_Once counters */ u32 szSorterRef; /* Min size in bytes to use sorter-refs */ unsigned int iPrngSeed; /* Alternative fixed seed for the PRNG */ + void (*xCorruption)(void *, const void *); + void *pCorruptionArg; /* vvvv--- must be last ---vvv */ #ifdef SQLITE_DEBUG sqlite3_int64 aTune[SQLITE_NTUNE]; /* Tuning parameters */ @@ -19778,6 +19796,57 @@ SQLITE_PRIVATE Window *sqlite3WindowAssemble(Parse*, Window*, ExprList*, ExprLis } \ } +#define SQLITE_PRINT_CORRUPT_SIZE (SQLITE_PRINT_BUF_SIZE * 2) + +#define SQLITE_CORRUPT_CONTEXT(N,P,T,O,S,M,R) \ + { .nPage=(N), .pgno=(P), .type=(T), \ + .zoneRange={(O),(S)}, .zMsg=(M), .reservedArgs=(R) } + +typedef struct { + int offset; + size_t size; +}sqlite3CorruptRange; + +typedef enum { + CORRUPT_TYPE_PAGE_BTREE_LEAF, + CORRUPT_TYPE_PAGE_BTREE_INTERIOR, + CORRUPT_TYPE_PAGE_INDEX_LEAF, + CORRUPT_TYPE_PAGE_INDEX_INTERIOR, + CORRUPT_TYPE_PAGE_OVERFLOW, + CORRUPT_TYPE_PAGE_PTR_MAP, + CORRUPT_TYPE_PAGE_FREE_LIST, + CORRUPT_TYPE_FRAME_WAL, + CORRUPT_TYPE_ENTRY_JOURNAL, + CORRUPT_TYPE_VDBE, + CORRUPT_TYPE_FILE_HEADER, + CORRUPT_TYPE_UNKOWN, +} CorruptType; + +typedef struct { + size_t nPage; /* Number of pages */ + unsigned int pgno; /* Page number for corrupted page */ + CorruptType type; + sqlite3CorruptRange zoneRange; + const char *zMsg; + void *reservedArgs; +}sqlite3CorruptContext; + +// Encode buffer with base16, return size after encode +static size_t sqlite3base16Encode(const unsigned char *buffer, size_t bufSize, char *encodeBuf, size_t encodeBufSize) +{ + if (buffer == NULL || bufSize == 0 || encodeBuf == NULL || encodeBufSize == 0) { + return 0; + } + static const char base16Code[] = "0123456789ABCDEF"; + size_t i = 0; + for (; i < bufSize && (i * 2 < encodeBufSize - 1); i++) { + *encodeBuf++ = base16Code[(buffer[i] >> 4) & 0x0F]; + *encodeBuf++ = base16Code[buffer[i] & 0x0F]; + } + *encodeBuf = '\0'; + return i * 2; +} + /* ** The SQLITE_*_BKPT macros are substitutes for the error codes with ** the same name but without the _BKPT suffix. These macros invoke @@ -19786,10 +19855,11 @@ SQLITE_PRIVATE Window *sqlite3WindowAssemble(Parse*, Window*, ExprList*, ExprLis ** to set a debugger breakpoint. */ SQLITE_PRIVATE int sqlite3ReportError(int iErr, int lineno, const char *zType); -SQLITE_PRIVATE int sqlite3CorruptError(int); +SQLITE_PRIVATE int sqlite3CorruptError(int lineno, sqlite3CorruptContext *context); SQLITE_PRIVATE int sqlite3MisuseError(int); SQLITE_PRIVATE int sqlite3CantopenError(int); -#define SQLITE_CORRUPT_BKPT sqlite3CorruptError(__LINE__) +#define SQLITE_CORRUPT_REPORT(context) sqlite3CorruptError(__LINE__,(context)) +#define SQLITE_CORRUPT_BKPT sqlite3CorruptError(__LINE__,NULL) #define SQLITE_MISUSE_BKPT sqlite3MisuseError(__LINE__) #define SQLITE_CANTOPEN_BKPT sqlite3CantopenError(__LINE__) #ifdef SQLITE_DEBUG @@ -19803,10 +19873,11 @@ SQLITE_PRIVATE int sqlite3IoerrnomemError(int); #endif #if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_CORRUPT_PGNO) SQLITE_PRIVATE int sqlite3CorruptPgnoError(int,Pgno); -# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptPgnoError(__LINE__,(P)) +# define SQLITE_CORRUPT_PGNO(P,context) sqlite3CorruptPgnoError(__LINE__,(P),(context)) #else -# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptError(__LINE__) +# define SQLITE_CORRUPT_PGNO(P,context) sqlite3CorruptError(__LINE__,(context)) #endif +# define SQLITE_CORRUPT_REPORT_PGNO(context) SQLITE_CORRUPT_PGNO((context)->pgno,(context)) /* ** FTS3 and FTS4 both require virtual table support @@ -58537,7 +58608,7 @@ static int readDbPage(PgHdr *pPg){ assert( isOpen(pPager->fd) ); if( pagerUseWal(pPager) ){ - rc = sqlite3WalFindFrame(pPager->pWal, pPg->pgno, &iFrame); + rc = sqlite3WalFindFrame(pPager->pWal, pPg->pgno, &iFrame); // find in wal-index if( rc ) return rc; } if( iFrame ){ @@ -61070,7 +61141,12 @@ static int getPageNormal( assert( assert_pager_state(pPager) ); assert( pPager->hasHeldSharedLock==1 ); - if( pgno==0 ) return SQLITE_CORRUPT_BKPT; + if( pgno==0 ) { + const char *zMsg = "pgno should not be 0"; + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPager->dbSize, 0, CORRUPT_TYPE_UNKOWN, + -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_REPORT(&context); + } pBase = sqlite3PcacheFetch(pPager->pPCache, pgno, 3); if( pBase==0 ){ pPg = 0; @@ -61102,7 +61178,11 @@ static int getPageNormal( ** (2) Never try to fetch the locking page */ if( pgno==PAGER_SJ_PGNO(pPager) ){ - rc = SQLITE_CORRUPT_BKPT; + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "try fetching the locking page(%u)", pgno); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPager->dbSize, pgno, CORRUPT_TYPE_UNKOWN, + -1, 0, zMsg, NULL); + rc = SQLITE_CORRUPT_REPORT(&context); goto pager_acquire_err; } @@ -61184,7 +61264,10 @@ static int getPageMMap( ** test in the previous statement, and avoid testing pgno==0 in the ** common case where pgno is large. */ if( pgno<=1 && pgno==0 ){ - return SQLITE_CORRUPT_BKPT; + const char *zMsg = "pgno should not be 0"; + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPager->dbSize, 0, CORRUPT_TYPE_UNKOWN, + -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_REPORT(&context); } assert( pPager->eState>=PAGER_READER ); assert( assert_pager_state(pPager) ); @@ -62767,7 +62850,11 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i if( pPgOld ){ if( NEVER(pPgOld->nRef>1) ){ sqlite3PagerUnrefNotNull(pPgOld); - return SQLITE_CORRUPT_BKPT; + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "page(%u) should be no references, ref cnt:%d", pgno, (int)pPgOld->nRef); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPager->dbSize, pgno, CORRUPT_TYPE_UNKOWN, + -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_REPORT(&context); } pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC); if( pPager->tempFile ){ @@ -64531,7 +64618,13 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){ /* Write the aPgno[] array entry and the hash-table slot. */ nCollide = idx; for(iKey=walHash(iPage); sLoc.aHash[iKey]; iKey=walNextHash(iKey)){ - if( (nCollide--)==0 ) return SQLITE_CORRUPT_BKPT; + if( (nCollide--)==0 ){ + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "no place for page(%u) to map into WAL, idx:%d", iPage, idx); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pWal->hdr.nPage, iPage, CORRUPT_TYPE_FRAME_WAL, + -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_REPORT(&context); + } } sLoc.aPgno[idx-1] = iPage; AtomicStore(&sLoc.aHash[iKey], (ht_slot)idx); @@ -65479,7 +65572,13 @@ static int walCheckpoint( ** database plus the amount of data in the wal file, plus the ** maximum size of the pending-byte page (65536 bytes), then ** must be corruption somewhere. */ - rc = SQLITE_CORRUPT_BKPT; + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, + "final db size unexpected,nSize=%lld,mxFrame=%u,pageSize=%d,nReq=%lld", + nSize, pWal->hdr.mxFrame, szPage, nReq); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(mxPage, 0, CORRUPT_TYPE_FRAME_WAL, + -1, 0, zMsg, NULL); + rc = SQLITE_CORRUPT_REPORT(&context); }else{ sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT,&nReq); } @@ -66571,7 +66670,11 @@ SQLITE_PRIVATE int sqlite3WalFindFrame( iRead = iFrame; } if( (nCollide--)==0 ){ - return SQLITE_CORRUPT_BKPT; + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "mis-match page(%u) to map into WAL", pgno); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pWal->hdr.nPage, pgno, CORRUPT_TYPE_FRAME_WAL, + -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_REPORT(&context); } iKey = walNextHash(iKey); } @@ -67304,7 +67407,12 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint( if( rc==SQLITE_OK ){ if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ - rc = SQLITE_CORRUPT_BKPT; + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "mis-match between pageSize=%d and bufferSize=%d, mxFrame=%u", + walPagesize(pWal),nBuf,pWal->hdr.mxFrame); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pWal->hdr.nPage, 0, CORRUPT_TYPE_FRAME_WAL, + -1, 0, zMsg, NULL); + rc = SQLITE_CORRUPT_REPORT(&context); }else{ rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); } @@ -68751,7 +68859,7 @@ static int checkDbHeaderValid(sqlite3 *db, int iDbpage, u8 *zBuf){ ** with the page number and filename associated with the (MemPage*). */ #ifdef SQLITE_DEBUG -int corruptPageError(int lineno, MemPage *p){ +int corruptPageError(int lineno, MemPage *p, sqlite3CorruptContext *context){ char *zMsg; sqlite3BeginBenignMalloc(); zMsg = sqlite3_mprintf("database corruption page %d of %s", @@ -68762,11 +68870,11 @@ int corruptPageError(int lineno, MemPage *p){ sqlite3ReportError(SQLITE_CORRUPT, lineno, zMsg); } sqlite3_free(zMsg); - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_REPORT(context); } -# define SQLITE_CORRUPT_PAGE(pMemPage) corruptPageError(__LINE__, pMemPage) +# define SQLITE_CORRUPT_PAGE(context,pMemPage) corruptPageError(__LINE__, (pMemPage),(context)) #else -# define SQLITE_CORRUPT_PAGE(pMemPage) SQLITE_CORRUPT_PGNO(pMemPage->pgno) +# define SQLITE_CORRUPT_PAGE(context,pMemPage) SQLITE_CORRUPT_PGNO((pMemPage)->pgno,(context)) #endif #ifndef SQLITE_OMIT_SHARED_CACHE @@ -69444,7 +69552,12 @@ static int btreeMoveto( if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT; sqlite3VdbeRecordUnpack(pKeyInfo, (int)nKey, pKey, pIdxKey); if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){ - rc = SQLITE_CORRUPT_BKPT; + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "unexpected fields in total:%u, should != 0 and < %u", + pIdxKey->nField,pKeyInfo->nAllField); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pCur->pBt->nPage, 0, CORRUPT_TYPE_PAGE_BTREE_LEAF, + -1, 0, zMsg, NULL); + rc = SQLITE_CORRUPT_REPORT(&context); }else{ rc = sqlite3BtreeIndexMoveto(pCur, pIdxKey, pRes); } @@ -69624,7 +69737,7 @@ static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){ assert( 0==PTRMAP_ISPAGE(pBt, PENDING_BYTE_PAGE(pBt)) ); assert( pBt->autoVacuum ); - if( key==0 ){ + if( key==0 ){ // The pgno of each entry on ptrmap page starts from 3, an unexpected pgno indicates data corrupted *pRC = SQLITE_CORRUPT_BKPT; return; } @@ -69638,12 +69751,24 @@ static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){ /* The first byte of the extra data is the MemPage.isInit byte. ** If that byte is set, it means this page is also being used ** as a btree page. */ - *pRC = SQLITE_CORRUPT_BKPT; + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; + (void)sqlite3base16Encode((unsigned char *)sqlite3PagerGetExtra(pDbPage), 8, xBuffer, sizeof(xBuffer)); + sqlite3_snprintf(sizeof(zMsg), zMsg, "page(%u) been initialized before as a btree page, base16:%s", + iPtrmap, xBuffer); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pBt->nPage, iPtrmap, CORRUPT_TYPE_PAGE_PTR_MAP, + -1, 0, zMsg, NULL); + *pRC = SQLITE_CORRUPT_REPORT(&context); goto ptrmap_exit; } offset = PTRMAP_PTROFFSET(iPtrmap, key); if( offset<0 ){ - *pRC = SQLITE_CORRUPT_BKPT; + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "unexpect offset in ptrmap page(%u), target:%u, page usableSize=%u", + iPtrmap, key, pBt->usableSize); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pBt->nPage, iPtrmap, CORRUPT_TYPE_PAGE_PTR_MAP, + -1, 0, zMsg, NULL); + *pRC = SQLITE_CORRUPT_REPORT(&context); goto ptrmap_exit; } assert( offset <= (int)pBt->usableSize-5 ); @@ -69688,7 +69813,12 @@ static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){ offset = PTRMAP_PTROFFSET(iPtrmap, key); if( offset<0 ){ sqlite3PagerUnref(pDbPage); - return SQLITE_CORRUPT_BKPT; + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "unexpect offset in ptrmap page(%d), target:%u, page usableSize=%u", + iPtrmap, key, pBt->usableSize); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pBt->nPage, iPtrmap, CORRUPT_TYPE_PAGE_PTR_MAP, + -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_REPORT(&context); } assert( offset <= (int)pBt->usableSize-5 ); assert( pEType!=0 ); @@ -69696,7 +69826,15 @@ static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){ if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]); sqlite3PagerUnref(pDbPage); - if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_PGNO(iPtrmap); + if( *pEType<1 || *pEType>5 ){ + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; // 5 bytes for each entry on ptrmap page + (void)sqlite3base16Encode(pPtrmap, 5, xBuffer, sizeof(xBuffer)); + sqlite3_snprintf(sizeof(zMsg), zMsg, "unexpect entry type:%d, base16:%s", (int)*pEType, xBuffer); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pBt->nPage, iPtrmap, CORRUPT_TYPE_PAGE_PTR_MAP, + offset, 5, zMsg, NULL); + return SQLITE_CORRUPT_REPORT_PGNO(&context); + } return SQLITE_OK; } @@ -70088,7 +70226,14 @@ static void ptrmapPutOvflPtr(MemPage *pPage, MemPage *pSrc, u8 *pCell,int *pRC){ Pgno ovfl; if( SQLITE_WITHIN(pSrc->aDataEnd, pCell, pCell+info.nLocal) ){ testcase( pSrc!=pPage ); - *pRC = SQLITE_CORRUPT_BKPT; + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; // Output cell header as much as possible, 4 bytes for overflow pgno + (void)sqlite3base16Encode(pCell, info.nSize - info.nLocal - 4, xBuffer, sizeof(xBuffer)); + sqlite3_snprintf(sizeof(zMsg), zMsg, "cell overflow, offset=%d, rest=%d, length=%u, base16:%s", + (int)(pCell - pPage->aData), (int)(pSrc->aDataEnd - pCell), info.nSize, xBuffer); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, + pCell - pPage->aData, info.nSize, zMsg, NULL); + *pRC = SQLITE_CORRUPT_REPORT(&context); return; } ovfl = get4byte(&pCell[info.nSize-4]); @@ -70146,10 +70291,29 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ ** reconstruct the entire page. */ if( (int)data[hdr+7]<=nMaxFrag ){ int iFree = get2byte(&data[hdr+1]); - if( iFree>usableSize-4 ) return SQLITE_CORRUPT_PAGE(pPage); + if( iFree>usableSize-4 ){ + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; + (void)sqlite3base16Encode(data, 8, xBuffer, sizeof(xBuffer)); // Output first 8 bytes as it's page header + sqlite3_snprintf(sizeof(zMsg), zMsg, "freeblock offset=%d overflow, usableSize=%d, base16:%s", + iFree, usableSize, xBuffer); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, + 0, 8, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); + } if( iFree ){ int iFree2 = get2byte(&data[iFree]); - if( iFree2>usableSize-4 ) return SQLITE_CORRUPT_PAGE(pPage); + if( iFree2>usableSize-4 ){ + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; + (void)sqlite3base16Encode(data, 4, xBuffer, sizeof(xBuffer)); // Output first freeblock's header 4 bytes + sqlite3_snprintf(sizeof(zMsg), zMsg, + "1st freeblock's next pointer overflow, point:%d, usableSize=%d, base16:%s", + iFree2, usableSize, xBuffer); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, + iFree, 4, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); + } if( 0==iFree2 || (data[iFree2]==0 && data[iFree2+1]==0) ){ u8 *pEnd = &data[cellOffset + nCell*2]; u8 *pAddr; @@ -70157,16 +70321,51 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ int sz = get2byte(&data[iFree+2]); int top = get2byte(&data[hdr+5]); if( top>=iFree ){ - return SQLITE_CORRUPT_PAGE(pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; + (void)sqlite3base16Encode(data, 8, xBuffer, sizeof(xBuffer)); // Print first 8 bytes which is page header + sqlite3_snprintf(sizeof(zMsg), zMsg, + "1st freeblock's offset:%d should > CellContentArea's offset:%d, base16:%s", + iFree, top, xBuffer); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, + iFree, 8, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); } if( iFree2 ){ - if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_PAGE(pPage); + if( iFree+sz>iFree2 ){ + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; + (void)sqlite3base16Encode(data, 8, xBuffer, sizeof(xBuffer)); // Print first 8 bytes which is page header + sqlite3_snprintf(sizeof(zMsg), zMsg, + "the 1st 2 freeblocks mis-order, 1st block offset:%d, size:%d, 2nd block offset:%d, base16:%s", + iFree, sz, iFree2, xBuffer); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, + iFree, 4, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); + } sz2 = get2byte(&data[iFree2+2]); - if( iFree2+sz2 > usableSize ) return SQLITE_CORRUPT_PAGE(pPage); + if( iFree2+sz2 > usableSize ){ + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; + (void)sqlite3base16Encode(data + iFree2, 4, xBuffer, sizeof(xBuffer)); // Print 4 bytes belong to 2nd block + sqlite3_snprintf(sizeof(zMsg), zMsg, + "the 2nd freeblock overflow, offset:%d, size:%d, usableSize:%d, base16:%s", + iFree2, sz2, usableSize, xBuffer); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, + iFree2, 4, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); + } memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz)); sz += sz2; }else if( iFree+sz>usableSize ){ - return SQLITE_CORRUPT_PAGE(pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; + (void)sqlite3base16Encode(data + iFree, 4, xBuffer, sizeof(xBuffer)); // Print 4 bytes belong to 1st block + sqlite3_snprintf(sizeof(zMsg), zMsg, + "the 1st freeblock overflow, offset:%d, size:%d, usableSize:%d, base16:%s", iFree, sz, usableSize, xBuffer); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, + iFree, 4, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); } cbrk = top+sz; @@ -70199,13 +70398,24 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ ** if PRAGMA cell_size_check=ON. */ if( pciCellLast ){ - return SQLITE_CORRUPT_PAGE(pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; // Print 4 bytes belong to 1st block + (void)sqlite3base16Encode(data + cellOffset + i*2, 2, xBuffer, sizeof(xBuffer)); + sqlite3_snprintf(sizeof(zMsg), zMsg, "%d-th cell pointer:%d out of range[%d, %d], base16:%s", + i, pc, iCellStart, iCellLast, xBuffer); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, + cellOffset + i*2, 2, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); } assert( pc>=iCellStart && pc<=iCellLast ); size = pPage->xCellSize(pPage, &src[pc]); cbrk -= size; if( cbrkusableSize ){ - return SQLITE_CORRUPT_PAGE(pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "move %d-th cell from %d using unexpected size:%d", i, pc, size); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, + -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); } assert( cbrk+size<=usableSize && cbrk>=iCellStart ); testcase( cbrk+size==usableSize ); @@ -70219,7 +70429,13 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ defragment_out: assert( pPage->nFree>=0 ); if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){ - return SQLITE_CORRUPT_PAGE(pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, + "after defragment, free bytes should not change, fragment bytes:%d, free space:%d, total:%d", + (int)data[hdr+7], cbrk-iCellFirst, pPage->nFree); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, + -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); } assert( cbrk>=iCellFirst ); put2byte(&data[hdr+5], cbrk); @@ -70244,7 +70460,7 @@ defragment_out: ** will be ignored if adding the extra space to the fragmentation count ** causes the fragmentation count to exceed 60. */ -static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ +static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ // search on B-tree page const int hdr = pPg->hdrOffset; /* Offset to page header */ u8 * const aData = pPg->aData; /* Page data */ int iAddr = hdr + 1; /* Address of ptr to pc */ @@ -70276,7 +70492,15 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ return &aData[pc]; }else if( x+pc > maxPC ){ /* This slot extends off the end of the usable part of the page */ - *pRc = SQLITE_CORRUPT_PAGE(pPg); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; + (void)sqlite3base16Encode(aData + pc, 4, xBuffer, sizeof(xBuffer)); // Print 4 bytes belong to free block + sqlite3_snprintf(sizeof(zMsg), zMsg, + "freeblock rest bytes:%d begin at %d which cost %d, still exceed usableSize:%u, base16:%s", + x, pc, nByte, pPg->pBt->usableSize, xBuffer); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPg->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, + pc, 4, zMsg, NULL); + *pRc = SQLITE_CORRUPT_PAGE(&context, pPg); return 0; }else{ /* The slot remains on the free-list. Reduce its size to account @@ -70291,14 +70515,25 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ if( pc<=iAddr ){ if( pc ){ /* The next slot in the chain comes before the current slot */ - *pRc = SQLITE_CORRUPT_PAGE(pPg); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; + (void)sqlite3base16Encode(pTmp, 2, xBuffer, sizeof(xBuffer)); // Print 4 bytes belong to free block + sqlite3_snprintf(sizeof(zMsg), zMsg, + "the next slot:%d in chain comes before current slot:%d, base16:%s", pc, iAddr, xBuffer); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPg->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, + iAddr, 2, zMsg, NULL); + *pRc = SQLITE_CORRUPT_PAGE(&context, pPg); } return 0; } } if( pc>maxPC+nByte-4 ){ /* The free slot chain extends off the end of the page */ - *pRc = SQLITE_CORRUPT_PAGE(pPg); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "free slot:%d overflow, end:%d", pc, maxPC+nByte-4); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPg->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, + -1, 0, zMsg, NULL); + *pRc = SQLITE_CORRUPT_PAGE(&context, pPg); } return 0; } @@ -70347,7 +70582,13 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ if( top==0 && pPage->pBt->usableSize==65536 ){ top = 65536; }else{ - return SQLITE_CORRUPT_PAGE(pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; + (void)sqlite3base16Encode(data, 8, xBuffer, sizeof(xBuffer)); // Print 8 bytes belong to page header + sqlite3_snprintf(sizeof(zMsg), zMsg, "unexpected cellContentArea offset:%d, base16:%s", top, xBuffer); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, + CORRUPT_TYPE_PAGE_BTREE_LEAF, 0, 8, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); } } @@ -70365,7 +70606,11 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ assert( pSpace+nByte<=data+pPage->pBt->usableSize ); *pIdx = g2 = (int)(pSpace-data); if( g2<=gap ){ - return SQLITE_CORRUPT_PAGE(pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "cellpointers(end:%d) overlap with freeblock(%d)", gap, g2); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, + CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); }else{ return SQLITE_OK; } @@ -70444,12 +70689,23 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ while( (iFreeBlk = get2byte(&data[iPtr]))pBt->nPage, pPage->pgno, + CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); } iPtr = iFreeBlk; } if( iFreeBlk>pPage->pBt->usableSize-4 ){ /* TH3: corrupt081.100 */ - return SQLITE_CORRUPT_PAGE(pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; + (void)sqlite3base16Encode(data + iPtr, 4, xBuffer, sizeof(xBuffer)); // Print 4 bytes belong to freeblock + sqlite3_snprintf(sizeof(zMsg), zMsg, "freeblock offset:%d overflow, base16:%s", (int)iFreeBlk, xBuffer); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, + CORRUPT_TYPE_PAGE_BTREE_LEAF, iPtr, 4, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); } assert( iFreeBlk>iPtr || iFreeBlk==0 || CORRUPT_DB ); @@ -70461,10 +70717,24 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ */ if( iFreeBlk && iEnd+3>=iFreeBlk ){ nFrag = iFreeBlk - iEnd; - if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_PAGE(pPage); + if( iEnd>iFreeBlk ){ + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "freeblock offset:%d overlaps with pre block's end:%u", + (int)iFreeBlk, iEnd); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, + CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); + } iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]); if( iEnd > pPage->pBt->usableSize ){ - return SQLITE_CORRUPT_PAGE(pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; + (void)sqlite3base16Encode(data + iFreeBlk, 4, xBuffer, sizeof(xBuffer)); // Print 4 bytes belong to freeblock + sqlite3_snprintf(sizeof(zMsg), zMsg, "freeblock offset:%d, end:%u overflow, usableSize:%u, base16:%s", + (int)iFreeBlk, iEnd, pPage->pBt->usableSize, xBuffer); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, + CORRUPT_TYPE_PAGE_BTREE_LEAF, iFreeBlk, 4, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); } iSize = iEnd - iStart; iFreeBlk = get2byte(&data[iFreeBlk]); @@ -70477,13 +70747,27 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ if( iPtr>hdr+1 ){ int iPtrEnd = iPtr + get2byte(&data[iPtr+2]); if( iPtrEnd+3>=iStart ){ - if( iPtrEnd>iStart ) return SQLITE_CORRUPT_PAGE(pPage); + if( iPtrEnd>iStart ){ + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "check pre freeblock end:%d overlaps with the pending free block:%d", + iPtrEnd, (int)iStart); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, + CORRUPT_TYPE_PAGE_BTREE_LEAF, iPtr, iPtrEnd - iPtr, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); + } nFrag += iStart - iPtrEnd; iSize = iEnd - iPtr; iStart = iPtr; } } - if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PAGE(pPage); + if( nFrag>data[hdr+7] ){ + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "fragment free bytes:%d increase unexpectly, should be %d", + (int)nFrag, (int)data[hdr+7]); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, + CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); + } data[hdr+7] -= nFrag; } pTmp = &data[hdr+5]; @@ -70492,8 +70776,21 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ /* The new freeblock is at the beginning of the cell content area, ** so just extend the cell content area rather than create another ** freelist entry */ - if( iStart= the beginning of the CellContentArea:%d", (int)x, (int)iStart); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, + CORRUPT_TYPE_PAGE_BTREE_LEAF, 0, 8, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); + } + if( iPtr!=hdr+1 ){ + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "1st freeblock's pos incorrect, hdr:%d, iPtr:%d", (int)hdr, (int)iPtr); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, + CORRUPT_TYPE_PAGE_BTREE_LEAF, 0, 8, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); + } put2byte(&data[hdr+1], iFreeBlk); put2byte(&data[hdr+5], iEnd); }else{ @@ -70589,7 +70886,13 @@ static int decodeFlags(MemPage *pPage, int flagByte){ pPage->maxLocal, g_lastCkptTime); #endif - return SQLITE_CORRUPT_PAGE(pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; + (void)sqlite3base16Encode(pPage->aData, 8, xBuffer, sizeof(xBuffer)); + sqlite3_snprintf(sizeof(zMsg), zMsg, "unrecognized flag:%d, base16:%s", flagByte, xBuffer); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, + CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); } pPage->max1bytePayload = pBt->max1bytePayload; return SQLITE_OK; @@ -70640,12 +70943,20 @@ static int btreeComputeFreeSpace(MemPage *pPage){ /* EVIDENCE-OF: R-55530-52930 In a well-formed b-tree page, there will ** always be at least one cell before the first freeblock. */ - return SQLITE_CORRUPT_PAGE(pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "the 1st freeblock:%d before all cells:%d", pc, top); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, + CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); } while( 1 ){ if( pc>iCellLast ){ /* Freeblock off the end of the page */ - return SQLITE_CORRUPT_PAGE(pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "freeblock end:%d out of page range:%d", pc, iCellLast); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, + CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); } next = get2byte(&data[pc]); size = get2byte(&data[pc+2]); @@ -70655,11 +70966,19 @@ static int btreeComputeFreeSpace(MemPage *pPage){ } if( next>0 ){ /* Freeblock not in ascending order */ - return SQLITE_CORRUPT_PAGE(pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "all freeblocks should order by asc, pre:%d, cur:%u", pc, next); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, + CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); } if( pc+size>(unsigned int)usableSize ){ /* Last freeblock extends past page end */ - return SQLITE_CORRUPT_PAGE(pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "last freeblock overflow, offset:%d, size:%u", pc, size); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, + CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); } } @@ -70671,7 +70990,13 @@ static int btreeComputeFreeSpace(MemPage *pPage){ ** area, according to the page header, lies within the page. */ if( nFree>usableSize || nFreepBt->nPage, pPage->pgno, + CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); } pPage->nFree = (u16)(nFree - iCellFirst); return SQLITE_OK; @@ -70702,12 +71027,20 @@ static SQLITE_NOINLINE int btreeCellSizeCheck(MemPage *pPage){ testcase( pc==iCellFirst ); testcase( pc==iCellLast ); if( pciCellLast ){ - return SQLITE_CORRUPT_PAGE(pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "cell pointer:%d indicate out of range:[%d, %d]", pc, iCellFirst, iCellLast); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, + CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); } sz = pPage->xCellSize(pPage, &data[pc]); testcase( pc+sz==usableSize ); if( pc+sz>usableSize ){ - return SQLITE_CORRUPT_PAGE(pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "unexpected cell size:%d,offset:%d, out of range:%d", sz, pc, usableSize); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, + CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); } } return SQLITE_OK; @@ -70739,7 +71072,7 @@ static int btreeInitPage(MemPage *pPage){ /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating ** the b-tree page type. */ if( decodeFlags(pPage, data[0]) ){ - return SQLITE_CORRUPT_PAGE(pPage); + return SQLITE_CORRUPT_PAGE(NULL, pPage); } assert( pBt->pageSize>=512 && pBt->pageSize<=65536 ); pPage->maskPage = (u16)(pBt->pageSize - 1); @@ -70753,7 +71086,12 @@ static int btreeInitPage(MemPage *pPage){ pPage->nCell = get2byte(&data[3]); if( pPage->nCell>MX_CELL(pBt) ){ /* To many cells for a single page. The page must be corrupt */ - return SQLITE_CORRUPT_PAGE(pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "too many cells(%d) for the page:%u, offset:%d, out of range:%u", + (int)pPage->nCell, pPage->pgno, (int)pPage->hdrOffset + 3, MX_CELL(pBt)); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, + -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); } testcase( pPage->nCell==MX_CELL(pBt) ); /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only @@ -70908,7 +71246,11 @@ static int getAndInitPage( assert( pCur==0 || pCur->iPage>0 ); if( pgno>btreePagecount(pBt) ){ - rc = SQLITE_CORRUPT_BKPT; + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "page number(%u) > db file size(%u)", pgno, btreePagecount(pBt)); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pBt->nPage, pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, + -1, 0, zMsg, NULL); + rc = SQLITE_CORRUPT_REPORT(&context); goto getAndInitPage_error1; } rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, bReadOnly); @@ -70929,7 +71271,12 @@ static int getAndInitPage( /* If obtaining a child page for a cursor, we must verify that the page is ** compatible with the root page. */ if( pCur && ((*ppPage)->nCell<1 || (*ppPage)->intKey!=pCur->curIntKey) ){ - rc = SQLITE_CORRUPT_PGNO(pgno); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "check btree page, nCell:%u, intKey:%u, cursor->curIntKey:%u", + (*ppPage)->nCell, (*ppPage)->intKey, pCur->curIntKey); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pBt->nPage, pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, + -1, 0, zMsg, NULL); + rc = SQLITE_CORRUPT_REPORT_PGNO(&context); goto getAndInitPage_error2; } return SQLITE_OK; @@ -72358,7 +72705,12 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ if( eType==PTRMAP_OVERFLOW2 ){ /* The pointer is always the first 4 bytes of the page in this case. */ if( get4byte(pPage->aData)!=iFrom ){ - return SQLITE_CORRUPT_PAGE(pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "1st 4 bytes of ovrflow page(%u) point to next(%u), should be %u", + pPage->pgno, get4byte(pPage->aData), iFrom); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPage->pgno, CORRUPT_TYPE_PAGE_PTR_MAP, + 0, 4, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); } put4byte(pPage->aData, iTo); }else{ @@ -72377,7 +72729,13 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ pPage->xParseCell(pPage, pCell, &info); if( info.nLocal pPage->aData+pPage->pBt->usableSize ){ - return SQLITE_CORRUPT_PAGE(pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, + "btree cell contain ovrflow pointer overflow, offset:%d, size:%u, usableSize:%u", + (int)(pCell - pPage->aData), info.nSize, pPage->pBt->usableSize); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, + CORRUPT_TYPE_PAGE_PTR_MAP, pCell - pPage->aData, info.nSize, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); } if( iFrom==get4byte(pCell+info.nSize-4) ){ put4byte(pCell+info.nSize-4, iTo); @@ -72386,7 +72744,13 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ } }else{ if( pCell+4 > pPage->aData+pPage->pBt->usableSize ){ - return SQLITE_CORRUPT_PAGE(pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, + "btree cell contain child pointer overflow, offset:%d, size:4, usableSize:%u", + (int)(pCell - pPage->aData), pPage->pBt->usableSize); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, + CORRUPT_TYPE_PAGE_PTR_MAP, pCell - pPage->aData, 4, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); } if( get4byte(pCell)==iFrom ){ put4byte(pCell, iTo); @@ -72398,7 +72762,11 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ if( i==nCell ){ if( eType!=PTRMAP_BTREE || get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){ - return SQLITE_CORRUPT_PAGE(pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "missing pointer point to overflow page on btree page(%u)", pPage->pgno); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, + CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); } put4byte(&pPage->aData[pPage->hdrOffset+8], iTo); } @@ -72531,7 +72899,11 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){ return rc; } if( eType==PTRMAP_ROOTPAGE ){ - return SQLITE_CORRUPT_BKPT; + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "try vacuum root page(%u), should not happened", nFin); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pBt->nPage, PTRMAP_PAGENO(pBt, iLastPg), + CORRUPT_TYPE_PAGE_PTR_MAP, -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_REPORT(&context); } if( eType==PTRMAP_FREEPAGE ){ @@ -73600,7 +73972,12 @@ static int accessPayload( assert( eOp==0 || eOp==1 ); assert( pCur->eState==CURSOR_VALID ); if( pCur->ix>=pPage->nCell ){ - return SQLITE_CORRUPT_PAGE(pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "cell index:%u exceed limit:%u on the page:%u", + pCur->ix, pPage->nCell, pPage->pgno); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pBt->nPage, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, + -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); } assert( cursorHoldsMutex(pCur) ); @@ -73615,7 +73992,12 @@ static int accessPayload( ** &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize] ** but is recast into its current form to avoid integer overflow problems */ - return SQLITE_CORRUPT_PAGE(pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "base on payload size:%u, the max offset(%d) should > %d", + pCur->info.nLocal, (int)(aPayload - pPage->aData), (int)(pBt->usableSize - pCur->info.nLocal)); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pBt->nPage, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, + 0, 8, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); } /* Check if data must be read/written to/from the btree page itself. */ @@ -73677,7 +74059,16 @@ static int accessPayload( assert( rc==SQLITE_OK && amt>0 ); while( nextPage ){ /* If required, populate the overflow page-list cache. */ - if( nextPage > pBt->nPage ) return SQLITE_CORRUPT_BKPT; + if( nextPage > pBt->nPage ){ + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; + (void)sqlite3base16Encode(aPayload + pCur->info.nLocal, 4, xBuffer, sizeof(xBuffer)); + sqlite3_snprintf(sizeof(zMsg), zMsg, "overflow page:%u should not exceed the size of database file, base16:%s", + nextPage, xBuffer); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pBt->nPage, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, + aPayload - pPage->aData + pCur->info.nLocal, 4, zMsg, NULL); + return SQLITE_CORRUPT_REPORT(&context); + } assert( pCur->aOverflow[iIdx]==0 || pCur->aOverflow[iIdx]==nextPage || CORRUPT_DB ); @@ -73762,7 +74153,11 @@ static int accessPayload( if( rc==SQLITE_OK && amt>0 ){ /* Overflow chain ends prematurely */ - return SQLITE_CORRUPT_PAGE(pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "overflow chain ends prematurely, rest:%d", amt); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pBt->nPage, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, + -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); } return rc; } @@ -74038,7 +74433,12 @@ static int moveToRoot(BtCursor *pCur){ ** (or the freelist). */ assert( pRoot->intKey==1 || pRoot->intKey==0 ); if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){ - return SQLITE_CORRUPT_PAGE(pCur->pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "the page(%u) state illegal, isInit:%u, pKeyInfo%s0, intKey:%u", + pRoot->pgno, pRoot->isInit, ((pCur->pKeyInfo==0)?"==":"!="), pRoot->intKey); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pCur->pBt->nPage, pRoot->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, + -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pCur->pPage); } skip_init: @@ -74292,7 +74692,11 @@ SQLITE_PRIVATE int sqlite3BtreeTableMoveto( if( pPage->intKeyLeaf ){ while( 0x80 <= *(pCell++) ){ if( pCell>=pPage->aDataEnd ){ - return SQLITE_CORRUPT_PAGE(pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "cell idx(%d) point to a cell should not out of page", idx); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, + CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); } } } @@ -74575,7 +74979,12 @@ bypass_moveto_root: testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */ testcase( nCell==2 ); /* Minimum legal index key size */ if( nCell<2 || nCell/pCur->pBt->usableSize>pCur->pBt->nPage ){ - rc = SQLITE_CORRUPT_PAGE(pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "nCell:%d illegal, usableSize:%u, nPage:%u", + nCell, pCur->pBt->usableSize, pCur->pBt->nPage); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, + CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); + rc = SQLITE_CORRUPT_PAGE(&context, pPage); goto moveto_index_finish; } pCellKey = sqlite3Malloc( nCell+nOverrun ); @@ -74903,7 +75312,13 @@ static int allocateBtreePage( n = get4byte(&pPage1->aData[36]); testcase( n==mxPage-1 ); if( n>=mxPage ){ - return SQLITE_CORRUPT_BKPT; + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + char xBuffer[SQLITE_PRINT_BUF_SIZE*3] = {0}; + (void)sqlite3base16Encode(pPage1->aData, 100, xBuffer, sizeof(xBuffer)); + sqlite3_snprintf(sizeof(zMsg), zMsg, + "total pages(%u) in freelist should not over the total size of db file(%u), base16:%s", n, mxPage, xBuffer); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(mxPage, 1, CORRUPT_TYPE_FILE_HEADER, 36, 4, zMsg, NULL); + return SQLITE_CORRUPT_REPORT(&context); } if( n>0 ){ /* There are pages on the freelist. Reuse one of those pages. */ @@ -74959,7 +75374,12 @@ static int allocateBtreePage( } testcase( iTrunk==mxPage ); if( iTrunk>mxPage || nSearch++ > n ){ - rc = SQLITE_CORRUPT_PGNO(pPrevTrunk ? pPrevTrunk->pgno : 1); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "freelist trunk page(%u) should <= the size of db(%u)", + iTrunk, mxPage); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(mxPage, (pPrevTrunk ? pPrevTrunk->pgno : 1), + CORRUPT_TYPE_PAGE_FREE_LIST, -1, 0, zMsg, NULL); + rc = SQLITE_CORRUPT_REPORT_PGNO(&context); }else{ rc = btreeGetUnusedPage(pBt, iTrunk, &pTrunk, 0); } @@ -74988,7 +75408,14 @@ static int allocateBtreePage( TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); }else if( k>(u32)(pBt->usableSize/4 - 2) ){ /* Value of k is out of range. Database corruption */ - rc = SQLITE_CORRUPT_PGNO(iTrunk); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; + (void)sqlite3base16Encode(pTrunk->aData, 8, xBuffer, sizeof(xBuffer)); + sqlite3_snprintf(sizeof(zMsg), zMsg, "total leaf pages(%u) on trunk page over limit(%u), base16:%s", + k, (u32)(pBt->usableSize/4 - 2), xBuffer); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(mxPage, iTrunk, CORRUPT_TYPE_PAGE_FREE_LIST, + 0, 8, zMsg, NULL); + rc = SQLITE_CORRUPT_REPORT_PGNO(&context); goto end_allocate_page; #ifndef SQLITE_OMIT_AUTOVACUUM }else if( searchList @@ -75022,7 +75449,14 @@ static int allocateBtreePage( MemPage *pNewTrunk; Pgno iNewTrunk = get4byte(&pTrunk->aData[8]); if( iNewTrunk>mxPage ){ - rc = SQLITE_CORRUPT_PGNO(iTrunk); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; + (void)sqlite3base16Encode(pTrunk->aData, 12, xBuffer, sizeof(xBuffer)); + sqlite3_snprintf(sizeof(zMsg), zMsg, + "leaf page's pgno(%u) on trunk page exceed db file size(%u), base16:%s", iNewTrunk, mxPage, xBuffer); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(mxPage, iTrunk, CORRUPT_TYPE_PAGE_FREE_LIST, + 8, 4, zMsg, NULL); + rc = SQLITE_CORRUPT_REPORT_PGNO(&context); goto end_allocate_page; } testcase( iNewTrunk==mxPage ); @@ -75087,7 +75521,14 @@ static int allocateBtreePage( iPage = get4byte(&aData[8+closest*4]); testcase( iPage==mxPage ); if( iPage>mxPage || iPage<2 ){ - rc = SQLITE_CORRUPT_PGNO(iTrunk); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; + (void)sqlite3base16Encode(aData+8+closest*4, 4, xBuffer, sizeof(xBuffer)); + sqlite3_snprintf(sizeof(zMsg), zMsg, "leaf page's pgno(%u) out of range:[3, %d], base16:%s", + iPage, mxPage, xBuffer); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(mxPage, iTrunk, CORRUPT_TYPE_PAGE_FREE_LIST, + 8+closest*4, 4, zMsg, NULL); + rc = SQLITE_CORRUPT_REPORT_PGNO(&context); goto end_allocate_page; } testcase( iPage==mxPage ); @@ -75272,7 +75713,14 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){ nLeaf = get4byte(&pTrunk->aData[4]); assert( pBt->usableSize>32 ); if( nLeaf > (u32)pBt->usableSize/4 - 2 ){ - rc = SQLITE_CORRUPT_BKPT; + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; + (void)sqlite3base16Encode(pTrunk->aData, 4, xBuffer, sizeof(xBuffer)); + sqlite3_snprintf(sizeof(zMsg), zMsg, "the number of leaf page(%u) on trunk page(%d) exceed limit, base16:%s", + nLeaf, iTrunk, xBuffer); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pBt->nPage, iTrunk, CORRUPT_TYPE_PAGE_FREE_LIST, + 0, 4, zMsg, NULL); + rc = SQLITE_CORRUPT_REPORT(&context); goto freepage_out; } if( nLeaf < (u32)pBt->usableSize/4 - 8 ){ @@ -75361,7 +75809,12 @@ static SQLITE_NOINLINE int clearCellOverflow( testcase( pCell + (pInfo->nSize-1) == pPage->aDataEnd ); if( pCell + pInfo->nSize > pPage->aDataEnd ){ /* Cell extends past end of page */ - return SQLITE_CORRUPT_PAGE(pPage); + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "overflow end of page, pgno:%u, offset:%d, size:%u, usableSize:%u", + pPage->pgno, (int)(pCell - pPage->aData), pInfo->nSize, pPage->pBt->usableSize); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(btreePagecount(pPage->pBt), pPage->pgno, + CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_PAGE(&context, pPage); } ovflPgno = get4byte(pCell + pInfo->nSize - 4); pBt = pPage->pBt; @@ -75378,7 +75831,14 @@ static SQLITE_NOINLINE int clearCellOverflow( /* 0 is not a legal page number and page 1 cannot be an ** overflow page. Therefore if ovflPgno<2 or past the end of the ** file the database must be corrupt. */ - return SQLITE_CORRUPT_BKPT; + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; + (void)sqlite3base16Encode(pCell + pInfo->nSize - 4, 4, xBuffer, sizeof(xBuffer)); + sqlite3_snprintf(sizeof(zMsg), zMsg, "overflow page's pgno(%u) illegal, out of range:[2, %u], base16:%s", + ovflPgno, btreePagecount(pBt), xBuffer); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(btreePagecount(pBt), pPage->pgno, + CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_REPORT(&context); } if( nOvfl ){ rc = getOverflowPage(pBt, ovflPgno, &pOvfl, &iNext); @@ -75651,7 +76111,12 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ testcase( pc==(u32)get2byte(&data[hdr+5]) ); testcase( pc+sz==pPage->pBt->usableSize ); if( pc+sz > pPage->pBt->usableSize ){ - *pRC = SQLITE_CORRUPT_BKPT; + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, "cell offset:%u size:%d, idx:%d overflow, usableSize:%u", + pc, sz, idx, pPage->pBt->usableSize); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, + -1, 0, zMsg, NULL); + *pRC = SQLITE_CORRUPT_REPORT(&context); return; } rc = freeSpace(pPage, pc, sz); @@ -77561,7 +78026,14 @@ static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){ if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd || pCur->info.pPayload < pPage->aData + pPage->cellOffset ){ - return SQLITE_CORRUPT_BKPT; + char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; + sqlite3_snprintf(sizeof(zMsg), zMsg, + "cell payload cursor point to(%d), size:%u overlaps with non-cell content area:[%u, %d]", + (int)(pCur->info.pPayload - pPage->aData), pCur->info.nLocal, pPage->cellOffset, + (int)(pPage->aDataEnd - pPage->aData)); + sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, + -1, 0, zMsg, NULL); + return SQLITE_CORRUPT_REPORT(&context); } /* Overwrite the local portion first */ rc = btreeOverwriteContent(pPage, pCur->info.pPayload, pX, @@ -82743,7 +83215,7 @@ static int growOpArray(Vdbe *v, int nOp){ ** ** Other useful labels for breakpoints include: ** test_trace_breakpoint(pc,pOp) -** sqlite3CorruptError(lineno) +** sqlite3CorruptError(lineno,context) ** sqlite3MisuseError(lineno) ** sqlite3CantopenError(lineno) */ @@ -90400,7 +90872,7 @@ SQLITE_API int sqlite3_found_count = 0; ** ** Other useful labels for breakpoints include: ** test_addop_breakpoint(pc,pOp) -** sqlite3CorruptError(lineno) +** sqlite3CorruptError(lineno,context) ** sqlite3MisuseError(lineno) ** sqlite3CantopenError(lineno) */ @@ -174133,6 +174605,12 @@ SQLITE_API int sqlite3_config(int op, ...){ break; } #endif /* SQLITE_OMIT_DESERIALIZE */ + case SQLITE_CONFIG_CORRUPTION: { + typedef void(*CORRUPTION_FUNC_t)(void*, const void*); + sqlite3GlobalConfig.xCorruption = va_arg(ap, CORRUPTION_FUNC_t); + sqlite3GlobalConfig.pCorruptionArg = va_arg(ap, void*); + break; + } default: { rc = SQLITE_ERROR; @@ -177197,9 +177675,21 @@ SQLITE_PRIVATE int sqlite3ReportError(int iErr, int lineno, const char *zType){ zType, lineno, 20+sqlite3_sourceid()); return iErr; } -SQLITE_PRIVATE int sqlite3CorruptError(int lineno){ +SQLITE_PRIVATE int sqlite3CorruptError(int lineno, sqlite3CorruptContext *context){ testcase( sqlite3GlobalConfig.xLog!=0 ); - return sqlite3ReportError(SQLITE_CORRUPT, lineno, "database corruption"); + if (context!=NULL && sqlite3GlobalConfig.xCorruption != 0) { + char zMsg[SQLITE_PRINT_BUF_SIZE] = {0}; /* Complete corruption log message */ + sqlite3_snprintf(sizeof(zMsg), zMsg, "pgno:%u,type:%d,range:{%d,%d},line:%d", + context->pgno, (int)context->type, (int)context->zoneRange.offset, (int)context->zoneRange.size, lineno); + sqlite3GlobalConfig.xCorruption(sqlite3GlobalConfig.pCorruptionArg, zMsg); + } + char zCorruptMsg[SQLITE_PRINT_BUF_SIZE * 10] = {0}; + if (context!=NULL && context->zMsg != NULL){ + sqlite3_snprintf(sizeof(zCorruptMsg), zCorruptMsg, "database corruption, %s", context->zMsg); + } else { + sqlite3_snprintf(sizeof(zCorruptMsg), zCorruptMsg, "database corruption"); + } + return sqlite3ReportError(SQLITE_CORRUPT, lineno, zCorruptMsg); } SQLITE_PRIVATE int sqlite3MisuseError(int lineno){ testcase( sqlite3GlobalConfig.xLog!=0 ); -- Gitee From f4b94632bea655224c9f083669ee2baa9694d67d Mon Sep 17 00:00:00 2001 From: oh_ci Date: Sat, 7 Dec 2024 06:02:14 +0000 Subject: [PATCH 4/4] =?UTF-8?q?=E5=9B=9E=E9=80=80=20'Pull=20Request=20!148?= =?UTF-8?q?=20:=20=E6=A3=80=E6=B5=8B=E5=88=B0=E6=8D=9F=E5=9D=8F=E6=97=B6?= =?UTF-8?q?=E5=B0=86=E6=8D=9F=E5=9D=8F=E7=8E=B0=E5=9C=BA=E4=BF=A1=E6=81=AF?= =?UTF-8?q?=E8=BF=94=E5=9B=9E'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/sqlite3.h | 16 -- src/sqlite3.c | 660 ++++++---------------------------------------- 2 files changed, 85 insertions(+), 591 deletions(-) diff --git a/include/sqlite3.h b/include/sqlite3.h index e383b92..445640f 100644 --- a/include/sqlite3.h +++ b/include/sqlite3.h @@ -2120,21 +2120,6 @@ struct sqlite3_mem_methods { ** configuration setting is never used, then the default maximum is determined ** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option. If that ** compile-time option is not set, then the default maximum is 1073741824. -** -** [[SQLITE_CONFIG_CORRUPTION]]
SQLITE_CONFIG_CORRUPTION
-**
The SQLITE_CONFIG_CORRUPTION option is used to configure the SQLite -** global [ corruption error]. -** (^The SQLITE_CONFIG_CORRUPTION option takes two arguments: a pointer to a -** function with a call signature of void(*)(void*,const void*), -** and a pointer to void. ^If the function pointer is not NULL, it is -** invoked to process each data corruption event. ^If the -** function pointer is NULL, no=op will do when corruption detect. -** ^The void pointer that is the second argument to SQLITE_CONFIG_CORRUPTION is -** passed through as the first parameter to the application-defined corruption -** function whenever that function is invoked. ^The second parameter to -** the corruption function is a corruption message after formatting via [sqlite3_snprintf()]. -** In a multi-threaded application, the application-defined corruption -** function must be threadsafe.
** */ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ @@ -2166,7 +2151,6 @@ struct sqlite3_mem_methods { #define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */ #define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */ #define SQLITE_CONFIG_MEMDB_MAXSIZE 29 /* sqlite3_int64 */ -#define SQLITE_CONFIG_CORRUPTION 30 /* xCorruption */ /* ** CAPI3REF: Database Connection Configuration Options diff --git a/src/sqlite3.c b/src/sqlite3.c index 4ff97d4..58ae20b 100644 --- a/src/sqlite3.c +++ b/src/sqlite3.c @@ -2431,21 +2431,6 @@ struct sqlite3_mem_methods { ** configuration setting is never used, then the default maximum is determined ** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option. If that ** compile-time option is not set, then the default maximum is 1073741824. -** -** [[SQLITE_CONFIG_CORRUPTION]]
SQLITE_CONFIG_CORRUPTION
-**
The SQLITE_CONFIG_CORRUPTION option is used to configure the SQLite -** global [ corruption error]. -** (^The SQLITE_CONFIG_CORRUPTION option takes two arguments: a pointer to a -** function with a call signature of void(*)(void*,const void*), -** and a pointer to void. ^If the function pointer is not NULL, it is -** invoked to process each data corruption event. ^If the -** function pointer is NULL, no=op will do when corruption detect. -** ^The void pointer that is the second argument to SQLITE_CONFIG_CORRUPTION is -** passed through as the first parameter to the application-defined corruption -** function whenever that function is invoked. ^The second parameter to -** the corruption function is a corruption message after formatting via [sqlite3_snprintf()]. -** In a multi-threaded application, the application-defined corruption -** function must be threadsafe.
** */ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ @@ -2477,7 +2462,6 @@ struct sqlite3_mem_methods { #define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */ #define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */ #define SQLITE_CONFIG_MEMDB_MAXSIZE 29 /* sqlite3_int64 */ -#define SQLITE_CONFIG_CORRUPTION 30 /* xCorruption */ /* ** CAPI3REF: Database Connection Configuration Options @@ -19558,8 +19542,6 @@ struct Sqlite3Config { int iOnceResetThreshold; /* When to reset OP_Once counters */ u32 szSorterRef; /* Min size in bytes to use sorter-refs */ unsigned int iPrngSeed; /* Alternative fixed seed for the PRNG */ - void (*xCorruption)(void *, const void *); - void *pCorruptionArg; /* vvvv--- must be last ---vvv */ #ifdef SQLITE_DEBUG sqlite3_int64 aTune[SQLITE_NTUNE]; /* Tuning parameters */ @@ -19811,57 +19793,6 @@ SQLITE_PRIVATE Window *sqlite3WindowAssemble(Parse*, Window*, ExprList*, ExprLis } \ } -#define SQLITE_PRINT_CORRUPT_SIZE (SQLITE_PRINT_BUF_SIZE * 2) - -#define SQLITE_CORRUPT_CONTEXT(N,P,T,O,S,M,R) \ - { .nPage=(N), .pgno=(P), .type=(T), \ - .zoneRange={(O),(S)}, .zMsg=(M), .reservedArgs=(R) } - -typedef struct { - int offset; - size_t size; -}sqlite3CorruptRange; - -typedef enum { - CORRUPT_TYPE_PAGE_BTREE_LEAF, - CORRUPT_TYPE_PAGE_BTREE_INTERIOR, - CORRUPT_TYPE_PAGE_INDEX_LEAF, - CORRUPT_TYPE_PAGE_INDEX_INTERIOR, - CORRUPT_TYPE_PAGE_OVERFLOW, - CORRUPT_TYPE_PAGE_PTR_MAP, - CORRUPT_TYPE_PAGE_FREE_LIST, - CORRUPT_TYPE_FRAME_WAL, - CORRUPT_TYPE_ENTRY_JOURNAL, - CORRUPT_TYPE_VDBE, - CORRUPT_TYPE_FILE_HEADER, - CORRUPT_TYPE_UNKOWN, -} CorruptType; - -typedef struct { - size_t nPage; /* Number of pages */ - unsigned int pgno; /* Page number for corrupted page */ - CorruptType type; - sqlite3CorruptRange zoneRange; - const char *zMsg; - void *reservedArgs; -}sqlite3CorruptContext; - -// Encode buffer with base16, return size after encode -static size_t sqlite3base16Encode(const unsigned char *buffer, size_t bufSize, char *encodeBuf, size_t encodeBufSize) -{ - if (buffer == NULL || bufSize == 0 || encodeBuf == NULL || encodeBufSize == 0) { - return 0; - } - static const char base16Code[] = "0123456789ABCDEF"; - size_t i = 0; - for (; i < bufSize && (i * 2 < encodeBufSize - 1); i++) { - *encodeBuf++ = base16Code[(buffer[i] >> 4) & 0x0F]; - *encodeBuf++ = base16Code[buffer[i] & 0x0F]; - } - *encodeBuf = '\0'; - return i * 2; -} - /* ** The SQLITE_*_BKPT macros are substitutes for the error codes with ** the same name but without the _BKPT suffix. These macros invoke @@ -19870,11 +19801,10 @@ static size_t sqlite3base16Encode(const unsigned char *buffer, size_t bufSize, c ** to set a debugger breakpoint. */ SQLITE_PRIVATE int sqlite3ReportError(int iErr, int lineno, const char *zType); -SQLITE_PRIVATE int sqlite3CorruptError(int lineno, sqlite3CorruptContext *context); +SQLITE_PRIVATE int sqlite3CorruptError(int); SQLITE_PRIVATE int sqlite3MisuseError(int); SQLITE_PRIVATE int sqlite3CantopenError(int); -#define SQLITE_CORRUPT_REPORT(context) sqlite3CorruptError(__LINE__,(context)) -#define SQLITE_CORRUPT_BKPT sqlite3CorruptError(__LINE__,NULL) +#define SQLITE_CORRUPT_BKPT sqlite3CorruptError(__LINE__) #define SQLITE_MISUSE_BKPT sqlite3MisuseError(__LINE__) #define SQLITE_CANTOPEN_BKPT sqlite3CantopenError(__LINE__) #ifdef SQLITE_DEBUG @@ -19888,11 +19818,10 @@ SQLITE_PRIVATE int sqlite3IoerrnomemError(int); #endif #if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_CORRUPT_PGNO) SQLITE_PRIVATE int sqlite3CorruptPgnoError(int,Pgno); -# define SQLITE_CORRUPT_PGNO(P,context) sqlite3CorruptPgnoError(__LINE__,(P),(context)) +# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptPgnoError(__LINE__,(P)) #else -# define SQLITE_CORRUPT_PGNO(P,context) sqlite3CorruptError(__LINE__,(context)) +# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptError(__LINE__) #endif -# define SQLITE_CORRUPT_REPORT_PGNO(context) SQLITE_CORRUPT_PGNO((context)->pgno,(context)) /* ** FTS3 and FTS4 both require virtual table support @@ -58682,7 +58611,7 @@ static int readDbPage(PgHdr *pPg){ assert( isOpen(pPager->fd) ); if( pagerUseWal(pPager) ){ - rc = sqlite3WalFindFrame(pPager->pWal, pPg->pgno, &iFrame); // find in wal-index + rc = sqlite3WalFindFrame(pPager->pWal, pPg->pgno, &iFrame); if( rc ) return rc; } if( iFrame ){ @@ -61219,12 +61148,7 @@ static int getPageNormal( assert( assert_pager_state(pPager) ); assert( pPager->hasHeldSharedLock==1 ); - if( pgno==0 ) { - const char *zMsg = "pgno should not be 0"; - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPager->dbSize, 0, CORRUPT_TYPE_UNKOWN, - -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_REPORT(&context); - } + if( pgno==0 ) return SQLITE_CORRUPT_BKPT; pBase = sqlite3PcacheFetch(pPager->pPCache, pgno, 3); if( pBase==0 ){ pPg = 0; @@ -61256,11 +61180,7 @@ static int getPageNormal( ** (2) Never try to fetch the locking page */ if( pgno==PAGER_SJ_PGNO(pPager) ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "try fetching the locking page(%u)", pgno); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPager->dbSize, pgno, CORRUPT_TYPE_UNKOWN, - -1, 0, zMsg, NULL); - rc = SQLITE_CORRUPT_REPORT(&context); + rc = SQLITE_CORRUPT_BKPT; goto pager_acquire_err; } @@ -61342,10 +61262,7 @@ static int getPageMMap( ** test in the previous statement, and avoid testing pgno==0 in the ** common case where pgno is large. */ if( pgno<=1 && pgno==0 ){ - const char *zMsg = "pgno should not be 0"; - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPager->dbSize, 0, CORRUPT_TYPE_UNKOWN, - -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_REPORT(&context); + return SQLITE_CORRUPT_BKPT; } assert( pPager->eState>=PAGER_READER ); assert( assert_pager_state(pPager) ); @@ -62932,11 +62849,7 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i if( pPgOld ){ if( NEVER(pPgOld->nRef>1) ){ sqlite3PagerUnrefNotNull(pPgOld); - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "page(%u) should be no references, ref cnt:%d", pgno, (int)pPgOld->nRef); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPager->dbSize, pgno, CORRUPT_TYPE_UNKOWN, - -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_REPORT(&context); + return SQLITE_CORRUPT_BKPT; } pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC); if( pPager->tempFile ){ @@ -64704,13 +64617,7 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){ /* Write the aPgno[] array entry and the hash-table slot. */ nCollide = idx; for(iKey=walHash(iPage); sLoc.aHash[iKey]; iKey=walNextHash(iKey)){ - if( (nCollide--)==0 ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "no place for page(%u) to map into WAL, idx:%d", iPage, idx); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pWal->hdr.nPage, iPage, CORRUPT_TYPE_FRAME_WAL, - -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_REPORT(&context); - } + if( (nCollide--)==0 ) return SQLITE_CORRUPT_BKPT; } sLoc.aPgno[idx-1] = iPage; AtomicStore(&sLoc.aHash[iKey], (ht_slot)idx); @@ -65660,13 +65567,7 @@ static int walCheckpoint( ** database plus the amount of data in the wal file, plus the ** maximum size of the pending-byte page (65536 bytes), then ** must be corruption somewhere. */ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, - "final db size unexpected,nSize=%lld,mxFrame=%u,pageSize=%d,nReq=%lld", - nSize, pWal->hdr.mxFrame, szPage, nReq); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(mxPage, 0, CORRUPT_TYPE_FRAME_WAL, - -1, 0, zMsg, NULL); - rc = SQLITE_CORRUPT_REPORT(&context); + rc = SQLITE_CORRUPT_BKPT; }else{ sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT,&nReq); } @@ -66774,11 +66675,7 @@ SQLITE_PRIVATE int sqlite3WalFindFrame( iRead = iFrame; } if( (nCollide--)==0 ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "mis-match page(%u) to map into WAL", pgno); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pWal->hdr.nPage, pgno, CORRUPT_TYPE_FRAME_WAL, - -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_REPORT(&context); + return SQLITE_CORRUPT_BKPT; } iKey = walNextHash(iKey); } @@ -67513,12 +67410,7 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint( if( rc==SQLITE_OK ){ if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "mis-match between pageSize=%d and bufferSize=%d, mxFrame=%u", - walPagesize(pWal),nBuf,pWal->hdr.mxFrame); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pWal->hdr.nPage, 0, CORRUPT_TYPE_FRAME_WAL, - -1, 0, zMsg, NULL); - rc = SQLITE_CORRUPT_REPORT(&context); + rc = SQLITE_CORRUPT_BKPT; }else{ rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); } @@ -68965,7 +68857,7 @@ static int checkDbHeaderValid(sqlite3 *db, int iDbpage, u8 *zBuf){ ** with the page number and filename associated with the (MemPage*). */ #ifdef SQLITE_DEBUG -int corruptPageError(int lineno, MemPage *p, sqlite3CorruptContext *context){ +int corruptPageError(int lineno, MemPage *p){ char *zMsg; sqlite3BeginBenignMalloc(); zMsg = sqlite3_mprintf("database corruption page %d of %s", @@ -68976,11 +68868,11 @@ int corruptPageError(int lineno, MemPage *p, sqlite3CorruptContext *context){ sqlite3ReportError(SQLITE_CORRUPT, lineno, zMsg); } sqlite3_free(zMsg); - return SQLITE_CORRUPT_REPORT(context); + return SQLITE_CORRUPT_BKPT; } -# define SQLITE_CORRUPT_PAGE(context,pMemPage) corruptPageError(__LINE__, (pMemPage),(context)) +# define SQLITE_CORRUPT_PAGE(pMemPage) corruptPageError(__LINE__, pMemPage) #else -# define SQLITE_CORRUPT_PAGE(context,pMemPage) SQLITE_CORRUPT_PGNO((pMemPage)->pgno,(context)) +# define SQLITE_CORRUPT_PAGE(pMemPage) SQLITE_CORRUPT_PGNO(pMemPage->pgno) #endif #ifndef SQLITE_OMIT_SHARED_CACHE @@ -69658,12 +69550,7 @@ static int btreeMoveto( if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT; sqlite3VdbeRecordUnpack(pKeyInfo, (int)nKey, pKey, pIdxKey); if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "unexpected fields in total:%u, should != 0 and < %u", - pIdxKey->nField,pKeyInfo->nAllField); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pCur->pBt->nPage, 0, CORRUPT_TYPE_PAGE_BTREE_LEAF, - -1, 0, zMsg, NULL); - rc = SQLITE_CORRUPT_REPORT(&context); + rc = SQLITE_CORRUPT_BKPT; }else{ rc = sqlite3BtreeIndexMoveto(pCur, pIdxKey, pRes); } @@ -69843,7 +69730,7 @@ static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){ assert( 0==PTRMAP_ISPAGE(pBt, PENDING_BYTE_PAGE(pBt)) ); assert( pBt->autoVacuum ); - if( key==0 ){ // The pgno of each entry on ptrmap page starts from 3, an unexpected pgno indicates data corrupted + if( key==0 ){ *pRC = SQLITE_CORRUPT_BKPT; return; } @@ -69857,24 +69744,12 @@ static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){ /* The first byte of the extra data is the MemPage.isInit byte. ** If that byte is set, it means this page is also being used ** as a btree page. */ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; - (void)sqlite3base16Encode((unsigned char *)sqlite3PagerGetExtra(pDbPage), 8, xBuffer, sizeof(xBuffer)); - sqlite3_snprintf(sizeof(zMsg), zMsg, "page(%u) been initialized before as a btree page, base16:%s", - iPtrmap, xBuffer); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pBt->nPage, iPtrmap, CORRUPT_TYPE_PAGE_PTR_MAP, - -1, 0, zMsg, NULL); - *pRC = SQLITE_CORRUPT_REPORT(&context); + *pRC = SQLITE_CORRUPT_BKPT; goto ptrmap_exit; } offset = PTRMAP_PTROFFSET(iPtrmap, key); if( offset<0 ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "unexpect offset in ptrmap page(%u), target:%u, page usableSize=%u", - iPtrmap, key, pBt->usableSize); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pBt->nPage, iPtrmap, CORRUPT_TYPE_PAGE_PTR_MAP, - -1, 0, zMsg, NULL); - *pRC = SQLITE_CORRUPT_REPORT(&context); + *pRC = SQLITE_CORRUPT_BKPT; goto ptrmap_exit; } assert( offset <= (int)pBt->usableSize-5 ); @@ -69919,12 +69794,7 @@ static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){ offset = PTRMAP_PTROFFSET(iPtrmap, key); if( offset<0 ){ sqlite3PagerUnref(pDbPage); - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "unexpect offset in ptrmap page(%d), target:%u, page usableSize=%u", - iPtrmap, key, pBt->usableSize); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pBt->nPage, iPtrmap, CORRUPT_TYPE_PAGE_PTR_MAP, - -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_REPORT(&context); + return SQLITE_CORRUPT_BKPT; } assert( offset <= (int)pBt->usableSize-5 ); assert( pEType!=0 ); @@ -69932,15 +69802,7 @@ static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){ if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]); sqlite3PagerUnref(pDbPage); - if( *pEType<1 || *pEType>5 ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; // 5 bytes for each entry on ptrmap page - (void)sqlite3base16Encode(pPtrmap, 5, xBuffer, sizeof(xBuffer)); - sqlite3_snprintf(sizeof(zMsg), zMsg, "unexpect entry type:%d, base16:%s", (int)*pEType, xBuffer); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pBt->nPage, iPtrmap, CORRUPT_TYPE_PAGE_PTR_MAP, - offset, 5, zMsg, NULL); - return SQLITE_CORRUPT_REPORT_PGNO(&context); - } + if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_PGNO(iPtrmap); return SQLITE_OK; } @@ -70332,14 +70194,7 @@ static void ptrmapPutOvflPtr(MemPage *pPage, MemPage *pSrc, u8 *pCell,int *pRC){ Pgno ovfl; if( SQLITE_WITHIN(pSrc->aDataEnd, pCell, pCell+info.nLocal) ){ testcase( pSrc!=pPage ); - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; // Output cell header as much as possible, 4 bytes for overflow pgno - (void)sqlite3base16Encode(pCell, info.nSize - info.nLocal - 4, xBuffer, sizeof(xBuffer)); - sqlite3_snprintf(sizeof(zMsg), zMsg, "cell overflow, offset=%d, rest=%d, length=%u, base16:%s", - (int)(pCell - pPage->aData), (int)(pSrc->aDataEnd - pCell), info.nSize, xBuffer); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, - pCell - pPage->aData, info.nSize, zMsg, NULL); - *pRC = SQLITE_CORRUPT_REPORT(&context); + *pRC = SQLITE_CORRUPT_BKPT; return; } ovfl = get4byte(&pCell[info.nSize-4]); @@ -70397,29 +70252,10 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ ** reconstruct the entire page. */ if( (int)data[hdr+7]<=nMaxFrag ){ int iFree = get2byte(&data[hdr+1]); - if( iFree>usableSize-4 ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; - (void)sqlite3base16Encode(data, 8, xBuffer, sizeof(xBuffer)); // Output first 8 bytes as it's page header - sqlite3_snprintf(sizeof(zMsg), zMsg, "freeblock offset=%d overflow, usableSize=%d, base16:%s", - iFree, usableSize, xBuffer); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, - 0, 8, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); - } + if( iFree>usableSize-4 ) return SQLITE_CORRUPT_PAGE(pPage); if( iFree ){ int iFree2 = get2byte(&data[iFree]); - if( iFree2>usableSize-4 ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; - (void)sqlite3base16Encode(data, 4, xBuffer, sizeof(xBuffer)); // Output first freeblock's header 4 bytes - sqlite3_snprintf(sizeof(zMsg), zMsg, - "1st freeblock's next pointer overflow, point:%d, usableSize=%d, base16:%s", - iFree2, usableSize, xBuffer); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, - iFree, 4, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); - } + if( iFree2>usableSize-4 ) return SQLITE_CORRUPT_PAGE(pPage); if( 0==iFree2 || (data[iFree2]==0 && data[iFree2+1]==0) ){ u8 *pEnd = &data[cellOffset + nCell*2]; u8 *pAddr; @@ -70427,51 +70263,16 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ int sz = get2byte(&data[iFree+2]); int top = get2byte(&data[hdr+5]); if( top>=iFree ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; - (void)sqlite3base16Encode(data, 8, xBuffer, sizeof(xBuffer)); // Print first 8 bytes which is page header - sqlite3_snprintf(sizeof(zMsg), zMsg, - "1st freeblock's offset:%d should > CellContentArea's offset:%d, base16:%s", - iFree, top, xBuffer); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, - iFree, 8, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } if( iFree2 ){ - if( iFree+sz>iFree2 ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; - (void)sqlite3base16Encode(data, 8, xBuffer, sizeof(xBuffer)); // Print first 8 bytes which is page header - sqlite3_snprintf(sizeof(zMsg), zMsg, - "the 1st 2 freeblocks mis-order, 1st block offset:%d, size:%d, 2nd block offset:%d, base16:%s", - iFree, sz, iFree2, xBuffer); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, - iFree, 4, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); - } + if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_PAGE(pPage); sz2 = get2byte(&data[iFree2+2]); - if( iFree2+sz2 > usableSize ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; - (void)sqlite3base16Encode(data + iFree2, 4, xBuffer, sizeof(xBuffer)); // Print 4 bytes belong to 2nd block - sqlite3_snprintf(sizeof(zMsg), zMsg, - "the 2nd freeblock overflow, offset:%d, size:%d, usableSize:%d, base16:%s", - iFree2, sz2, usableSize, xBuffer); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, - iFree2, 4, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); - } + if( iFree2+sz2 > usableSize ) return SQLITE_CORRUPT_PAGE(pPage); memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz)); sz += sz2; }else if( iFree+sz>usableSize ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; - (void)sqlite3base16Encode(data + iFree, 4, xBuffer, sizeof(xBuffer)); // Print 4 bytes belong to 1st block - sqlite3_snprintf(sizeof(zMsg), zMsg, - "the 1st freeblock overflow, offset:%d, size:%d, usableSize:%d, base16:%s", iFree, sz, usableSize, xBuffer); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, - iFree, 4, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } cbrk = top+sz; @@ -70504,24 +70305,13 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ ** if PRAGMA cell_size_check=ON. */ if( pciCellLast ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; // Print 4 bytes belong to 1st block - (void)sqlite3base16Encode(data + cellOffset + i*2, 2, xBuffer, sizeof(xBuffer)); - sqlite3_snprintf(sizeof(zMsg), zMsg, "%d-th cell pointer:%d out of range[%d, %d], base16:%s", - i, pc, iCellStart, iCellLast, xBuffer); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, - cellOffset + i*2, 2, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } assert( pc>=iCellStart && pc<=iCellLast ); size = pPage->xCellSize(pPage, &src[pc]); cbrk -= size; if( cbrkusableSize ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "move %d-th cell from %d using unexpected size:%d", i, pc, size); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, - -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } assert( cbrk+size<=usableSize && cbrk>=iCellStart ); testcase( cbrk+size==usableSize ); @@ -70535,13 +70325,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ defragment_out: assert( pPage->nFree>=0 ); if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, - "after defragment, free bytes should not change, fragment bytes:%d, free space:%d, total:%d", - (int)data[hdr+7], cbrk-iCellFirst, pPage->nFree); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, - -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } assert( cbrk>=iCellFirst ); put2byte(&data[hdr+5], cbrk); @@ -70566,7 +70350,7 @@ defragment_out: ** will be ignored if adding the extra space to the fragmentation count ** causes the fragmentation count to exceed 60. */ -static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ // search on B-tree page +static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ const int hdr = pPg->hdrOffset; /* Offset to page header */ u8 * const aData = pPg->aData; /* Page data */ int iAddr = hdr + 1; /* Address of ptr to pc */ @@ -70598,15 +70382,7 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ // search on B-tree return &aData[pc]; }else if( x+pc > maxPC ){ /* This slot extends off the end of the usable part of the page */ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; - (void)sqlite3base16Encode(aData + pc, 4, xBuffer, sizeof(xBuffer)); // Print 4 bytes belong to free block - sqlite3_snprintf(sizeof(zMsg), zMsg, - "freeblock rest bytes:%d begin at %d which cost %d, still exceed usableSize:%u, base16:%s", - x, pc, nByte, pPg->pBt->usableSize, xBuffer); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPg->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, - pc, 4, zMsg, NULL); - *pRc = SQLITE_CORRUPT_PAGE(&context, pPg); + *pRc = SQLITE_CORRUPT_PAGE(pPg); return 0; }else{ /* The slot remains on the free-list. Reduce its size to account @@ -70621,25 +70397,14 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ // search on B-tree if( pc<=iAddr ){ if( pc ){ /* The next slot in the chain comes before the current slot */ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; - (void)sqlite3base16Encode(pTmp, 2, xBuffer, sizeof(xBuffer)); // Print 4 bytes belong to free block - sqlite3_snprintf(sizeof(zMsg), zMsg, - "the next slot:%d in chain comes before current slot:%d, base16:%s", pc, iAddr, xBuffer); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPg->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, - iAddr, 2, zMsg, NULL); - *pRc = SQLITE_CORRUPT_PAGE(&context, pPg); + *pRc = SQLITE_CORRUPT_PAGE(pPg); } return 0; } } if( pc>maxPC+nByte-4 ){ /* The free slot chain extends off the end of the page */ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "free slot:%d overflow, end:%d", pc, maxPC+nByte-4); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPg->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, - -1, 0, zMsg, NULL); - *pRc = SQLITE_CORRUPT_PAGE(&context, pPg); + *pRc = SQLITE_CORRUPT_PAGE(pPg); } return 0; } @@ -70688,13 +70453,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ if( top==0 && pPage->pBt->usableSize==65536 ){ top = 65536; }else{ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; - (void)sqlite3base16Encode(data, 8, xBuffer, sizeof(xBuffer)); // Print 8 bytes belong to page header - sqlite3_snprintf(sizeof(zMsg), zMsg, "unexpected cellContentArea offset:%d, base16:%s", top, xBuffer); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, - CORRUPT_TYPE_PAGE_BTREE_LEAF, 0, 8, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } } @@ -70712,11 +70471,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ assert( pSpace+nByte<=data+pPage->pBt->usableSize ); *pIdx = g2 = (int)(pSpace-data); if( g2<=gap ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "cellpointers(end:%d) overlap with freeblock(%d)", gap, g2); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, - CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); }else{ return SQLITE_OK; } @@ -70795,23 +70550,12 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ while( (iFreeBlk = get2byte(&data[iPtr]))pBt->nPage, pPage->pgno, - CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } iPtr = iFreeBlk; } if( iFreeBlk>pPage->pBt->usableSize-4 ){ /* TH3: corrupt081.100 */ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; - (void)sqlite3base16Encode(data + iPtr, 4, xBuffer, sizeof(xBuffer)); // Print 4 bytes belong to freeblock - sqlite3_snprintf(sizeof(zMsg), zMsg, "freeblock offset:%d overflow, base16:%s", (int)iFreeBlk, xBuffer); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, - CORRUPT_TYPE_PAGE_BTREE_LEAF, iPtr, 4, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } assert( iFreeBlk>iPtr || iFreeBlk==0 || CORRUPT_DB ); @@ -70823,24 +70567,10 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ */ if( iFreeBlk && iEnd+3>=iFreeBlk ){ nFrag = iFreeBlk - iEnd; - if( iEnd>iFreeBlk ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "freeblock offset:%d overlaps with pre block's end:%u", - (int)iFreeBlk, iEnd); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, - CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); - } + if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_PAGE(pPage); iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]); if( iEnd > pPage->pBt->usableSize ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; - (void)sqlite3base16Encode(data + iFreeBlk, 4, xBuffer, sizeof(xBuffer)); // Print 4 bytes belong to freeblock - sqlite3_snprintf(sizeof(zMsg), zMsg, "freeblock offset:%d, end:%u overflow, usableSize:%u, base16:%s", - (int)iFreeBlk, iEnd, pPage->pBt->usableSize, xBuffer); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, - CORRUPT_TYPE_PAGE_BTREE_LEAF, iFreeBlk, 4, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } iSize = iEnd - iStart; iFreeBlk = get2byte(&data[iFreeBlk]); @@ -70853,27 +70583,13 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ if( iPtr>hdr+1 ){ int iPtrEnd = iPtr + get2byte(&data[iPtr+2]); if( iPtrEnd+3>=iStart ){ - if( iPtrEnd>iStart ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "check pre freeblock end:%d overlaps with the pending free block:%d", - iPtrEnd, (int)iStart); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, - CORRUPT_TYPE_PAGE_BTREE_LEAF, iPtr, iPtrEnd - iPtr, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); - } + if( iPtrEnd>iStart ) return SQLITE_CORRUPT_PAGE(pPage); nFrag += iStart - iPtrEnd; iSize = iEnd - iPtr; iStart = iPtr; } } - if( nFrag>data[hdr+7] ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "fragment free bytes:%d increase unexpectly, should be %d", - (int)nFrag, (int)data[hdr+7]); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, - CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); - } + if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PAGE(pPage); data[hdr+7] -= nFrag; } pTmp = &data[hdr+5]; @@ -70882,21 +70598,8 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ /* The new freeblock is at the beginning of the cell content area, ** so just extend the cell content area rather than create another ** freelist entry */ - if( iStart= the beginning of the CellContentArea:%d", (int)x, (int)iStart); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, - CORRUPT_TYPE_PAGE_BTREE_LEAF, 0, 8, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); - } - if( iPtr!=hdr+1 ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "1st freeblock's pos incorrect, hdr:%d, iPtr:%d", (int)hdr, (int)iPtr); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, - CORRUPT_TYPE_PAGE_BTREE_LEAF, 0, 8, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); - } + if( iStartmaxLocal, g_lastCkptTime); #endif - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; - (void)sqlite3base16Encode(pPage->aData, 8, xBuffer, sizeof(xBuffer)); - sqlite3_snprintf(sizeof(zMsg), zMsg, "unrecognized flag:%d, base16:%s", flagByte, xBuffer); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, - CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } pPage->max1bytePayload = pBt->max1bytePayload; return SQLITE_OK; @@ -71049,20 +70746,12 @@ static int btreeComputeFreeSpace(MemPage *pPage){ /* EVIDENCE-OF: R-55530-52930 In a well-formed b-tree page, there will ** always be at least one cell before the first freeblock. */ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "the 1st freeblock:%d before all cells:%d", pc, top); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, - CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } while( 1 ){ if( pc>iCellLast ){ /* Freeblock off the end of the page */ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "freeblock end:%d out of page range:%d", pc, iCellLast); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, - CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } next = get2byte(&data[pc]); size = get2byte(&data[pc+2]); @@ -71072,19 +70761,11 @@ static int btreeComputeFreeSpace(MemPage *pPage){ } if( next>0 ){ /* Freeblock not in ascending order */ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "all freeblocks should order by asc, pre:%d, cur:%u", pc, next); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, - CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } if( pc+size>(unsigned int)usableSize ){ /* Last freeblock extends past page end */ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "last freeblock overflow, offset:%d, size:%u", pc, size); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, - CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } } @@ -71096,13 +70777,7 @@ static int btreeComputeFreeSpace(MemPage *pPage){ ** area, according to the page header, lies within the page. */ if( nFree>usableSize || nFreepBt->nPage, pPage->pgno, - CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } pPage->nFree = (u16)(nFree - iCellFirst); return SQLITE_OK; @@ -71133,20 +70808,12 @@ static SQLITE_NOINLINE int btreeCellSizeCheck(MemPage *pPage){ testcase( pc==iCellFirst ); testcase( pc==iCellLast ); if( pciCellLast ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "cell pointer:%d indicate out of range:[%d, %d]", pc, iCellFirst, iCellLast); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, - CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } sz = pPage->xCellSize(pPage, &data[pc]); testcase( pc+sz==usableSize ); if( pc+sz>usableSize ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "unexpected cell size:%d,offset:%d, out of range:%d", sz, pc, usableSize); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, - CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } } return SQLITE_OK; @@ -71178,7 +70845,7 @@ static int btreeInitPage(MemPage *pPage){ /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating ** the b-tree page type. */ if( decodeFlags(pPage, data[0]) ){ - return SQLITE_CORRUPT_PAGE(NULL, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } assert( pBt->pageSize>=512 && pBt->pageSize<=65536 ); pPage->maskPage = (u16)(pBt->pageSize - 1); @@ -71192,12 +70859,7 @@ static int btreeInitPage(MemPage *pPage){ pPage->nCell = get2byte(&data[3]); if( pPage->nCell>MX_CELL(pBt) ){ /* To many cells for a single page. The page must be corrupt */ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "too many cells(%d) for the page:%u, offset:%d, out of range:%u", - (int)pPage->nCell, pPage->pgno, (int)pPage->hdrOffset + 3, MX_CELL(pBt)); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, - -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } testcase( pPage->nCell==MX_CELL(pBt) ); /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only @@ -71352,11 +71014,7 @@ static int getAndInitPage( assert( pCur==0 || pCur->iPage>0 ); if( pgno>btreePagecount(pBt) ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "page number(%u) > db file size(%u)", pgno, btreePagecount(pBt)); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pBt->nPage, pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, - -1, 0, zMsg, NULL); - rc = SQLITE_CORRUPT_REPORT(&context); + rc = SQLITE_CORRUPT_BKPT; goto getAndInitPage_error1; } rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, bReadOnly); @@ -71377,12 +71035,7 @@ static int getAndInitPage( /* If obtaining a child page for a cursor, we must verify that the page is ** compatible with the root page. */ if( pCur && ((*ppPage)->nCell<1 || (*ppPage)->intKey!=pCur->curIntKey) ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "check btree page, nCell:%u, intKey:%u, cursor->curIntKey:%u", - (*ppPage)->nCell, (*ppPage)->intKey, pCur->curIntKey); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pBt->nPage, pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, - -1, 0, zMsg, NULL); - rc = SQLITE_CORRUPT_REPORT_PGNO(&context); + rc = SQLITE_CORRUPT_PGNO(pgno); goto getAndInitPage_error2; } return SQLITE_OK; @@ -72811,12 +72464,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ if( eType==PTRMAP_OVERFLOW2 ){ /* The pointer is always the first 4 bytes of the page in this case. */ if( get4byte(pPage->aData)!=iFrom ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "1st 4 bytes of ovrflow page(%u) point to next(%u), should be %u", - pPage->pgno, get4byte(pPage->aData), iFrom); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPage->pgno, CORRUPT_TYPE_PAGE_PTR_MAP, - 0, 4, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } put4byte(pPage->aData, iTo); }else{ @@ -72835,13 +72483,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ pPage->xParseCell(pPage, pCell, &info); if( info.nLocal pPage->aData+pPage->pBt->usableSize ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, - "btree cell contain ovrflow pointer overflow, offset:%d, size:%u, usableSize:%u", - (int)(pCell - pPage->aData), info.nSize, pPage->pBt->usableSize); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, - CORRUPT_TYPE_PAGE_PTR_MAP, pCell - pPage->aData, info.nSize, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } if( iFrom==get4byte(pCell+info.nSize-4) ){ put4byte(pCell+info.nSize-4, iTo); @@ -72850,13 +72492,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ } }else{ if( pCell+4 > pPage->aData+pPage->pBt->usableSize ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, - "btree cell contain child pointer overflow, offset:%d, size:4, usableSize:%u", - (int)(pCell - pPage->aData), pPage->pBt->usableSize); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, - CORRUPT_TYPE_PAGE_PTR_MAP, pCell - pPage->aData, 4, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } if( get4byte(pCell)==iFrom ){ put4byte(pCell, iTo); @@ -72868,11 +72504,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ if( i==nCell ){ if( eType!=PTRMAP_BTREE || get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "missing pointer point to overflow page on btree page(%u)", pPage->pgno); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, - CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } put4byte(&pPage->aData[pPage->hdrOffset+8], iTo); } @@ -73005,11 +72637,7 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){ return rc; } if( eType==PTRMAP_ROOTPAGE ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "try vacuum root page(%u), should not happened", nFin); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pBt->nPage, PTRMAP_PAGENO(pBt, iLastPg), - CORRUPT_TYPE_PAGE_PTR_MAP, -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_REPORT(&context); + return SQLITE_CORRUPT_BKPT; } if( eType==PTRMAP_FREEPAGE ){ @@ -74078,12 +73706,7 @@ static int accessPayload( assert( eOp==0 || eOp==1 ); assert( pCur->eState==CURSOR_VALID ); if( pCur->ix>=pPage->nCell ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "cell index:%u exceed limit:%u on the page:%u", - pCur->ix, pPage->nCell, pPage->pgno); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pBt->nPage, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, - -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } assert( cursorHoldsMutex(pCur) ); @@ -74098,12 +73721,7 @@ static int accessPayload( ** &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize] ** but is recast into its current form to avoid integer overflow problems */ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "base on payload size:%u, the max offset(%d) should > %d", - pCur->info.nLocal, (int)(aPayload - pPage->aData), (int)(pBt->usableSize - pCur->info.nLocal)); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pBt->nPage, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, - 0, 8, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } /* Check if data must be read/written to/from the btree page itself. */ @@ -74165,16 +73783,7 @@ static int accessPayload( assert( rc==SQLITE_OK && amt>0 ); while( nextPage ){ /* If required, populate the overflow page-list cache. */ - if( nextPage > pBt->nPage ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; - (void)sqlite3base16Encode(aPayload + pCur->info.nLocal, 4, xBuffer, sizeof(xBuffer)); - sqlite3_snprintf(sizeof(zMsg), zMsg, "overflow page:%u should not exceed the size of database file, base16:%s", - nextPage, xBuffer); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pBt->nPage, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, - aPayload - pPage->aData + pCur->info.nLocal, 4, zMsg, NULL); - return SQLITE_CORRUPT_REPORT(&context); - } + if( nextPage > pBt->nPage ) return SQLITE_CORRUPT_BKPT; assert( pCur->aOverflow[iIdx]==0 || pCur->aOverflow[iIdx]==nextPage || CORRUPT_DB ); @@ -74259,11 +73868,7 @@ static int accessPayload( if( rc==SQLITE_OK && amt>0 ){ /* Overflow chain ends prematurely */ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "overflow chain ends prematurely, rest:%d", amt); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pBt->nPage, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, - -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } return rc; } @@ -74539,12 +74144,7 @@ static int moveToRoot(BtCursor *pCur){ ** (or the freelist). */ assert( pRoot->intKey==1 || pRoot->intKey==0 ); if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "the page(%u) state illegal, isInit:%u, pKeyInfo%s0, intKey:%u", - pRoot->pgno, pRoot->isInit, ((pCur->pKeyInfo==0)?"==":"!="), pRoot->intKey); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pCur->pBt->nPage, pRoot->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, - -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pCur->pPage); + return SQLITE_CORRUPT_PAGE(pCur->pPage); } skip_init: @@ -74798,11 +74398,7 @@ SQLITE_PRIVATE int sqlite3BtreeTableMoveto( if( pPage->intKeyLeaf ){ while( 0x80 <= *(pCell++) ){ if( pCell>=pPage->aDataEnd ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "cell idx(%d) point to a cell should not out of page", idx); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, - CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } } } @@ -75085,12 +74681,7 @@ bypass_moveto_root: testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */ testcase( nCell==2 ); /* Minimum legal index key size */ if( nCell<2 || nCell/pCur->pBt->usableSize>pCur->pBt->nPage ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "nCell:%d illegal, usableSize:%u, nPage:%u", - nCell, pCur->pBt->usableSize, pCur->pBt->nPage); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, - CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); - rc = SQLITE_CORRUPT_PAGE(&context, pPage); + rc = SQLITE_CORRUPT_PAGE(pPage); goto moveto_index_finish; } pCellKey = sqlite3Malloc( nCell+nOverrun ); @@ -75418,13 +75009,7 @@ static int allocateBtreePage( n = get4byte(&pPage1->aData[36]); testcase( n==mxPage-1 ); if( n>=mxPage ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - char xBuffer[SQLITE_PRINT_BUF_SIZE*3] = {0}; - (void)sqlite3base16Encode(pPage1->aData, 100, xBuffer, sizeof(xBuffer)); - sqlite3_snprintf(sizeof(zMsg), zMsg, - "total pages(%u) in freelist should not over the total size of db file(%u), base16:%s", n, mxPage, xBuffer); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(mxPage, 1, CORRUPT_TYPE_FILE_HEADER, 36, 4, zMsg, NULL); - return SQLITE_CORRUPT_REPORT(&context); + return SQLITE_CORRUPT_BKPT; } if( n>0 ){ /* There are pages on the freelist. Reuse one of those pages. */ @@ -75480,12 +75065,7 @@ static int allocateBtreePage( } testcase( iTrunk==mxPage ); if( iTrunk>mxPage || nSearch++ > n ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "freelist trunk page(%u) should <= the size of db(%u)", - iTrunk, mxPage); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(mxPage, (pPrevTrunk ? pPrevTrunk->pgno : 1), - CORRUPT_TYPE_PAGE_FREE_LIST, -1, 0, zMsg, NULL); - rc = SQLITE_CORRUPT_REPORT_PGNO(&context); + rc = SQLITE_CORRUPT_PGNO(pPrevTrunk ? pPrevTrunk->pgno : 1); }else{ rc = btreeGetUnusedPage(pBt, iTrunk, &pTrunk, 0); } @@ -75514,14 +75094,7 @@ static int allocateBtreePage( TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); }else if( k>(u32)(pBt->usableSize/4 - 2) ){ /* Value of k is out of range. Database corruption */ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; - (void)sqlite3base16Encode(pTrunk->aData, 8, xBuffer, sizeof(xBuffer)); - sqlite3_snprintf(sizeof(zMsg), zMsg, "total leaf pages(%u) on trunk page over limit(%u), base16:%s", - k, (u32)(pBt->usableSize/4 - 2), xBuffer); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(mxPage, iTrunk, CORRUPT_TYPE_PAGE_FREE_LIST, - 0, 8, zMsg, NULL); - rc = SQLITE_CORRUPT_REPORT_PGNO(&context); + rc = SQLITE_CORRUPT_PGNO(iTrunk); goto end_allocate_page; #ifndef SQLITE_OMIT_AUTOVACUUM }else if( searchList @@ -75555,14 +75128,7 @@ static int allocateBtreePage( MemPage *pNewTrunk; Pgno iNewTrunk = get4byte(&pTrunk->aData[8]); if( iNewTrunk>mxPage ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; - (void)sqlite3base16Encode(pTrunk->aData, 12, xBuffer, sizeof(xBuffer)); - sqlite3_snprintf(sizeof(zMsg), zMsg, - "leaf page's pgno(%u) on trunk page exceed db file size(%u), base16:%s", iNewTrunk, mxPage, xBuffer); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(mxPage, iTrunk, CORRUPT_TYPE_PAGE_FREE_LIST, - 8, 4, zMsg, NULL); - rc = SQLITE_CORRUPT_REPORT_PGNO(&context); + rc = SQLITE_CORRUPT_PGNO(iTrunk); goto end_allocate_page; } testcase( iNewTrunk==mxPage ); @@ -75627,14 +75193,7 @@ static int allocateBtreePage( iPage = get4byte(&aData[8+closest*4]); testcase( iPage==mxPage ); if( iPage>mxPage || iPage<2 ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; - (void)sqlite3base16Encode(aData+8+closest*4, 4, xBuffer, sizeof(xBuffer)); - sqlite3_snprintf(sizeof(zMsg), zMsg, "leaf page's pgno(%u) out of range:[3, %d], base16:%s", - iPage, mxPage, xBuffer); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(mxPage, iTrunk, CORRUPT_TYPE_PAGE_FREE_LIST, - 8+closest*4, 4, zMsg, NULL); - rc = SQLITE_CORRUPT_REPORT_PGNO(&context); + rc = SQLITE_CORRUPT_PGNO(iTrunk); goto end_allocate_page; } testcase( iPage==mxPage ); @@ -75819,14 +75378,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){ nLeaf = get4byte(&pTrunk->aData[4]); assert( pBt->usableSize>32 ); if( nLeaf > (u32)pBt->usableSize/4 - 2 ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; - (void)sqlite3base16Encode(pTrunk->aData, 4, xBuffer, sizeof(xBuffer)); - sqlite3_snprintf(sizeof(zMsg), zMsg, "the number of leaf page(%u) on trunk page(%d) exceed limit, base16:%s", - nLeaf, iTrunk, xBuffer); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pBt->nPage, iTrunk, CORRUPT_TYPE_PAGE_FREE_LIST, - 0, 4, zMsg, NULL); - rc = SQLITE_CORRUPT_REPORT(&context); + rc = SQLITE_CORRUPT_BKPT; goto freepage_out; } if( nLeaf < (u32)pBt->usableSize/4 - 8 ){ @@ -75915,12 +75467,7 @@ static SQLITE_NOINLINE int clearCellOverflow( testcase( pCell + (pInfo->nSize-1) == pPage->aDataEnd ); if( pCell + pInfo->nSize > pPage->aDataEnd ){ /* Cell extends past end of page */ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "overflow end of page, pgno:%u, offset:%d, size:%u, usableSize:%u", - pPage->pgno, (int)(pCell - pPage->aData), pInfo->nSize, pPage->pBt->usableSize); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(btreePagecount(pPage->pBt), pPage->pgno, - CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_PAGE(&context, pPage); + return SQLITE_CORRUPT_PAGE(pPage); } ovflPgno = get4byte(pCell + pInfo->nSize - 4); pBt = pPage->pBt; @@ -75937,14 +75484,7 @@ static SQLITE_NOINLINE int clearCellOverflow( /* 0 is not a legal page number and page 1 cannot be an ** overflow page. Therefore if ovflPgno<2 or past the end of the ** file the database must be corrupt. */ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - char xBuffer[SQLITE_PRINT_BUF_SIZE] = {0}; - (void)sqlite3base16Encode(pCell + pInfo->nSize - 4, 4, xBuffer, sizeof(xBuffer)); - sqlite3_snprintf(sizeof(zMsg), zMsg, "overflow page's pgno(%u) illegal, out of range:[2, %u], base16:%s", - ovflPgno, btreePagecount(pBt), xBuffer); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(btreePagecount(pBt), pPage->pgno, - CORRUPT_TYPE_PAGE_BTREE_LEAF, -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_REPORT(&context); + return SQLITE_CORRUPT_BKPT; } if( nOvfl ){ rc = getOverflowPage(pBt, ovflPgno, &pOvfl, &iNext); @@ -76217,12 +75757,7 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ testcase( pc==(u32)get2byte(&data[hdr+5]) ); testcase( pc+sz==pPage->pBt->usableSize ); if( pc+sz > pPage->pBt->usableSize ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, "cell offset:%u size:%d, idx:%d overflow, usableSize:%u", - pc, sz, idx, pPage->pBt->usableSize); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(pPage->pBt->nPage, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, - -1, 0, zMsg, NULL); - *pRC = SQLITE_CORRUPT_REPORT(&context); + *pRC = SQLITE_CORRUPT_BKPT; return; } rc = freeSpace(pPage, pc, sz); @@ -78132,14 +77667,7 @@ static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){ if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd || pCur->info.pPayload < pPage->aData + pPage->cellOffset ){ - char zMsg[SQLITE_PRINT_CORRUPT_SIZE] = {0}; - sqlite3_snprintf(sizeof(zMsg), zMsg, - "cell payload cursor point to(%d), size:%u overlaps with non-cell content area:[%u, %d]", - (int)(pCur->info.pPayload - pPage->aData), pCur->info.nLocal, pPage->cellOffset, - (int)(pPage->aDataEnd - pPage->aData)); - sqlite3CorruptContext context = SQLITE_CORRUPT_CONTEXT(0, pPage->pgno, CORRUPT_TYPE_PAGE_BTREE_LEAF, - -1, 0, zMsg, NULL); - return SQLITE_CORRUPT_REPORT(&context); + return SQLITE_CORRUPT_BKPT; } /* Overwrite the local portion first */ rc = btreeOverwriteContent(pPage, pCur->info.pPayload, pX, @@ -83322,7 +82850,7 @@ static int growOpArray(Vdbe *v, int nOp){ ** ** Other useful labels for breakpoints include: ** test_trace_breakpoint(pc,pOp) -** sqlite3CorruptError(lineno,context) +** sqlite3CorruptError(lineno) ** sqlite3MisuseError(lineno) ** sqlite3CantopenError(lineno) */ @@ -90980,7 +90508,7 @@ SQLITE_API int sqlite3_found_count = 0; ** ** Other useful labels for breakpoints include: ** test_addop_breakpoint(pc,pOp) -** sqlite3CorruptError(lineno,context) +** sqlite3CorruptError(lineno) ** sqlite3MisuseError(lineno) ** sqlite3CantopenError(lineno) */ @@ -174713,12 +174241,6 @@ SQLITE_API int sqlite3_config(int op, ...){ break; } #endif /* SQLITE_OMIT_DESERIALIZE */ - case SQLITE_CONFIG_CORRUPTION: { - typedef void(*CORRUPTION_FUNC_t)(void*, const void*); - sqlite3GlobalConfig.xCorruption = va_arg(ap, CORRUPTION_FUNC_t); - sqlite3GlobalConfig.pCorruptionArg = va_arg(ap, void*); - break; - } default: { rc = SQLITE_ERROR; @@ -177789,21 +177311,9 @@ SQLITE_PRIVATE int sqlite3ReportError(int iErr, int lineno, const char *zType){ zType, lineno, 20+sqlite3_sourceid()); return iErr; } -SQLITE_PRIVATE int sqlite3CorruptError(int lineno, sqlite3CorruptContext *context){ +SQLITE_PRIVATE int sqlite3CorruptError(int lineno){ testcase( sqlite3GlobalConfig.xLog!=0 ); - if (context!=NULL && sqlite3GlobalConfig.xCorruption != 0) { - char zMsg[SQLITE_PRINT_BUF_SIZE] = {0}; /* Complete corruption log message */ - sqlite3_snprintf(sizeof(zMsg), zMsg, "pgno:%u,type:%d,range:{%d,%d},line:%d", - context->pgno, (int)context->type, (int)context->zoneRange.offset, (int)context->zoneRange.size, lineno); - sqlite3GlobalConfig.xCorruption(sqlite3GlobalConfig.pCorruptionArg, zMsg); - } - char zCorruptMsg[SQLITE_PRINT_BUF_SIZE * 10] = {0}; - if (context!=NULL && context->zMsg != NULL){ - sqlite3_snprintf(sizeof(zCorruptMsg), zCorruptMsg, "database corruption, %s", context->zMsg); - } else { - sqlite3_snprintf(sizeof(zCorruptMsg), zCorruptMsg, "database corruption"); - } - return sqlite3ReportError(SQLITE_CORRUPT, lineno, zCorruptMsg); + return sqlite3ReportError(SQLITE_CORRUPT, lineno, "database corruption"); } SQLITE_PRIVATE int sqlite3MisuseError(int lineno){ testcase( sqlite3GlobalConfig.xLog!=0 ); -- Gitee