diff --git a/BUILD.gn b/BUILD.gn index aba0de39e3aee571ac91fb765cc82142cba2fd3e..ff13f50f96c042d6935836f836d6a5736c10b1e4 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -63,6 +63,9 @@ ohos_shared_library("sqlite") { "SQLITE_CODEC_ATTACH_CHANGED", "SQLITE_ENABLE_DROPTABLE_CALLBACK", "OPENSSL_SUPPRESS_DEPRECATED", + "LOG_DUMP", + "FDSAN_ENABLE", + "HARMONY_OS", ] cflags_c = [ "-fvisibility=hidden", @@ -123,6 +126,9 @@ ohos_executable("sqlite3") { "SQLITE_DIRECT_OVERFLOW_READ", "SQLITE_SHARED_BLOCK_OPTIMIZATION", "OPENSSL_SUPPRESS_DEPRECATED", + "LOG_DUMP", + "FDSAN_ENABLE", + "HARMONY_OS", ] cflags = [ diff --git a/src/shell.c b/src/shell.c index a951b2701958f58356f45d149251243a32d88fc0..a962c96d1becbf80f6a5d913c7cdfd29cb322f37 100644 --- a/src/shell.c +++ b/src/shell.c @@ -35,7 +35,8 @@ #define _CRT_SECURE_NO_WARNINGS #endif typedef unsigned int u32; -typedef unsigned short int u16; + +typedef unsigned short int u16; /* ** Optionally #include a user-defined header, whereby compilation options @@ -81,6 +82,7 @@ typedef unsigned short int u16; #pragma warning(disable : 4210) #pragma warning(disable : 4232) #pragma warning(disable : 4244) + #pragma warning(disable : 4305) #pragma warning(disable : 4306) #pragma warning(disable : 4702) @@ -90,8 +92,9 @@ typedef unsigned short int u16; /* ** No support for loadable extensions in VxWorks. */ -#if (defined(__RTP__) || defined(_WRS_KERNEL)) && !SQLITE_OMIT_LOAD_EXTENSION -# define SQLITE_OMIT_LOAD_EXTENSION 1 +#if (defined(__RTP__) || defined(_WRS_KERNEL)) && !SQLITE_OMIT_LOAD_EXTENSION +# define SQLITE_OMIT_LOAD_EXTENSION 1 + #endif /* @@ -101,14 +104,15 @@ typedef unsigned short int u16; # define _LARGE_FILE 1 # ifndef _FILE_OFFSET_BITS # define _FILE_OFFSET_BITS 64 + # endif # define _LARGEFILE_SOURCE 1 #endif #if defined(SQLITE_SHELL_FIDDLE) && !defined(_POSIX_SOURCE) /* -** emcc requires _POSIX_SOURCE (or one of several similar defines) -** to expose strdup(). +** emcc requires _POSIX_SOURCE (or one of several similar defines) +**to expose strdup(). */ # define _POSIX_SOURCE #endif diff --git a/src/sqlite3.c b/src/sqlite3.c index 9988125638de38fb65a6969c6295dfe4761d82a2..91862dfae22a92a6e3e38b4425a7b00707ba0100 100644 --- a/src/sqlite3.c +++ b/src/sqlite3.c @@ -21179,6 +21179,10 @@ SQLITE_API extern int sqlite3_open_file_count; #define OpenCounter(X) #endif /* defined(SQLITE_TEST) */ +#ifdef FDSAN_ENABLE +#define SQLITE_FDSAN_TAG 5351 +#endif + #endif /* !defined(_OS_COMMON_H_) */ /************** End of os_common.h *******************************************/ @@ -37124,6 +37128,30 @@ static pid_t randomnessPid = 0; #define F2FS_FEATURE_ATOMIC_WRITE 0x0004 #endif /* __linux__ */ +#ifdef HARMONY_OS +#define HMFS_MONITOR_FL 0x00000002 +#define HMFS_IOCTL_HW_GET_FLAGS _IOR(0xf5, 70, unsigned int) +#define HMFS_IOCTL_HW_SET_FLAGS _IOR(0xf5, 71, unsigned int) + +static void enableDbFileDelMonitor(int32_t fd) +{ + unsigned int flags = 0; + int ret = ioctl(fd, HMFS_IOCTL_HW_GET_FLAGS, &flags); + if (ret < 0) { + sqlite3_log(SQLITE_WARNING, "Not support fd %d enable del monitor errno = %d", fd, errno); + return; + } + if (flags & HMFS_MONITOR_FL) { + return; + } + flags |= HMFS_MONITOR_FL; + ret = ioctl(fd, HMFS_IOCTL_HW_SET_FLAGS, &flags); + if (ret < 0) { + sqlite3_log(SQLITE_WARNING, "Fd %d enable del monitor go wrong, errno = %d", fd, errno); + } +} + +#endif /* __HARMONY_OS__ */ /* ** Different Unix systems declare open() in different ways. Same use @@ -37134,7 +37162,27 @@ static pid_t randomnessPid = 0; ** which always has the same well-defined interface. */ static int posixOpen(const char *zFile, int flags, int mode){ - return open(zFile, flags, mode); + int fd = open(zFile, flags, mode); +#ifdef FDSAN_ENABLE + if ( fd > 0 && fdsan_get_owner_tag(fd) == 0 ) { + fdsan_exchange_owner_tag(fd, 0, fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, SQLITE_FDSAN_TAG)); + } +#endif +#ifdef HARMONY_OS + enableDbFileDelMonitor(fd); +#endif + return fd; +} + +/* +** Change close to posixClose, use fdsan_close_with_tag when fdsan enable. +*/ +static int posixClose(int fd) { +#ifdef FDSAN_ENABLE + return fdsan_close_with_tag(fd, fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, SQLITE_FDSAN_TAG)); +#else + return close(fd); +#endif } /* Forward reference */ @@ -37155,7 +37203,7 @@ static struct unix_syscall { { "open", (sqlite3_syscall_ptr)posixOpen, 0 }, #define osOpen ((int(*)(const char*,int,int))aSyscall[0].pCurrent) - { "close", (sqlite3_syscall_ptr)close, 0 }, + { "close", (sqlite3_syscall_ptr)posixClose, 0 }, #define osClose ((int(*)(int))aSyscall[1].pCurrent) { "access", (sqlite3_syscall_ptr)access, 0 }, @@ -38148,6 +38196,9 @@ static int findInodeInfo( storeLastErrno(pFile, errno); #if defined(EOVERFLOW) && defined(SQLITE_DISABLE_LFS) if( pFile->lastErrno==EOVERFLOW ) return SQLITE_NOLFS; +#endif +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR, "findInodeInfo-osFstat, fd[%d], errno[%d], osFstat[%d]", fd, errno, rc); #endif return SQLITE_IOERR; } @@ -38167,11 +38218,17 @@ static int findInodeInfo( do{ rc = osWrite(fd, "S", 1); }while( rc<0 && errno==EINTR ); if( rc!=1 ){ storeLastErrno(pFile, errno); +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR, "findInodeInfo-osWrite, fd[%d], errno[%d], osFstat[%d]", fd, errno, rc); +#endif return SQLITE_IOERR; } rc = osFstat(fd, &statbuf); if( rc!=0 ){ storeLastErrno(pFile, errno); +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR, "findInodeInfo-msdos-osFstat, fd[%d], errno[%d], osFstat[%d]", fd, errno, rc); +#endif return SQLITE_IOERR; } } @@ -39333,6 +39390,9 @@ static int flockUnlock(sqlite3_file *id, int eFileLock) { #ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS return SQLITE_OK; #endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */ +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_UNLOCK, "IOERR_UNLOCK fd[%d], eFileLock[%d]", pFile->h, eFileLock); +#endif return SQLITE_IOERR_UNLOCK; }else{ pFile->eFileLock = NO_LOCK; @@ -40159,9 +40219,15 @@ static int unixRead( #endif #ifdef EDEVERR case EDEVERR: +#endif +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_CORRUPTFS, "unixRead-EDEVERR, fd:[%d], amt[%d], got[%d], offset[%lld]", pFile->h, amt, got, offset); #endif return SQLITE_IOERR_CORRUPTFS; } +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_READ, "unixRead-got<0, fd: [%d], amt[%d], got[%d], offset[%lld]", pFile->h, amt, got, offset); +#endif return SQLITE_IOERR_READ; }else{ storeLastErrno(pFile, 0); /* not a system error */ @@ -40303,9 +40369,27 @@ static int unixWrite( if( amt>wrote ){ if( wrote<0 && pFile->lastErrno!=ENOSPC ){ /* lastErrno set by seekAndWrite */ +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_WRITE, + "unixWrite, lastErrno set by seekAndWrite, fd[%d], offset[%lld], wrote[%d], amt[%d], lastErrno[%d]", + pFile->h, + offset, + wrote, + amt, + pFile->lastErrno); +#endif return SQLITE_IOERR_WRITE; }else{ storeLastErrno(pFile, 0); /* not a system error */ +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_WRITE, + "unixWrite, not a system error, fd[%d], offset[%lld], wrote[%d], amt[%d], lastErrno[%d]", + pFile->h, + offset, + wrote, + amt, + pFile->lastErrno); +#endif return SQLITE_FULL; } } @@ -40659,7 +40743,17 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){ do{ err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size); }while( err==EINTR ); - if( err && err!=EINVAL ) return SQLITE_IOERR_WRITE; + if( err && err!=EINVAL ){ +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_WRITE, + "fcntlSizeHint-fallocate, fd[%d], bufSize[%lld], nSize[%lld] err[%d]", + pFile->h, + buf.st_size, + nSize, + err); +#endif + return SQLITE_IOERR_WRITE; + } #else /* If the OS does not have posix_fallocate(), fake it. Write a ** single byte to the last byte in each block that falls entirely @@ -40678,7 +40772,18 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){ for(/*no-op*/; iWrite=nSize ) iWrite = nSize - 1; nWrite = seekAndWrite(pFile, iWrite, "", 1); - if( nWrite!=1 ) return SQLITE_IOERR_WRITE; + if( nWrite!=1 ){ +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_WRITE, + "fcntlSizeHint-seekAndWrite, fd[%d], nWrite[%d], nSize[%d], nBlk[%d], iWrite[%lld]", + pFile->h, + nWrite, + nSize, + nBlk, + iWrite); +#endif + return SQLITE_IOERR_WRITE; + } } #endif } @@ -40733,14 +40838,29 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ #if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) case SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: { int rc = osIoctl(pFile->h, F2FS_IOC_START_ATOMIC_WRITE); +#ifdef LOG_DUMP + if( rc ){ + sqlite3_log(SQLITE_IOERR_BEGIN_ATOMIC, "unixFileControl-begin, fd[%d], op[%d]", pFile->h, op); + } +#endif return rc ? SQLITE_IOERR_BEGIN_ATOMIC : SQLITE_OK; } case SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: { int rc = osIoctl(pFile->h, F2FS_IOC_COMMIT_ATOMIC_WRITE); +#ifdef LOG_DUMP + if( rc ){ + sqlite3_log(SQLITE_IOERR_COMMIT_ATOMIC, "unixFileControl-commit, fd[%d], op[%d]", pFile->h, op); + } +#endif return rc ? SQLITE_IOERR_COMMIT_ATOMIC : SQLITE_OK; } case SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: { int rc = osIoctl(pFile->h, F2FS_IOC_ABORT_VOLATILE_WRITE); +#ifdef LOG_DUMP + if( rc ){ + sqlite3_log(SQLITE_IOERR_ROLLBACK_ATOMIC, "unixFileControl-rollback, fd[%d], op[%d]", pFile->h, op); + } +#endif return rc ? SQLITE_IOERR_ROLLBACK_ATOMIC : SQLITE_OK; } #endif /* __linux__ && SQLITE_ENABLE_BATCH_ATOMIC_WRITE */ @@ -41686,9 +41806,19 @@ static int unixShmLock( int *aLock; p = pDbFd->pShm; - if( p==0 ) return SQLITE_IOERR_SHMLOCK; + if( p==0 ){ +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_SHMLOCK, "unixShmLock-pShm, fd[%d], ofst[%d], n[%d], flags[%d]", ofst, n, flags); +#endif + return SQLITE_IOERR_SHMLOCK; + } pShmNode = p->pShmNode; - if( NEVER(pShmNode==0) ) return SQLITE_IOERR_SHMLOCK; + if( NEVER(pShmNode==0) ){ +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_SHMLOCK, "unixShmLock-pShmNode, fd[%d], ofst[%d], n[%d], flags[%d]", ofst, n, flags); +#endif + return SQLITE_IOERR_SHMLOCK; + } aLock = pShmNode->aLock; assert( pShmNode==pDbFd->pInode->pShmNode ); @@ -43060,6 +43190,9 @@ static int unixOpen( if( fstatfs(fd, &fsInfo) == -1 ){ storeLastErrno(p, errno); robust_close(p, fd, __LINE__); +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_ACCESS, "unixOpen, fd[%d], flags[%d], errno[%d]", fd, errno, flags); +#endif return SQLITE_IOERR_ACCESS; } if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) { @@ -43782,6 +43915,9 @@ static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){ if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){ OSTRACE(("GETLOCKPATH failed %s errno=%d pid=%d\n", lPath, errno, osGetpid(0))); +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_LOCK, "proxyGetLockPath len[%d], dbLen[%d], i[%d]", len, dbLen, i); +#endif return SQLITE_IOERR_LOCK; } len = strlcat(lPath, "sqliteplocks", maxLen); @@ -43900,6 +44036,7 @@ static int proxyCreateUnixFile( case EACCES: return SQLITE_PERM; case EIO: + sqlite3_log(SQLITE_IOERR_LOCK, "proxyCreateUnixFile-EIO, fd[%d]", fd); return SQLITE_IOERR_LOCK; /* even though it is the conch */ default: return SQLITE_CANTOPEN_BKPT; @@ -44068,6 +44205,9 @@ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){ struct stat buf; if( osFstat(conchFile->h, &buf) ){ storeLastErrno(pFile, errno); +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_LOCK, "proxyConchLock pFile fd[%d], conchFile fd[%d], lastErrno[%d]", pFile->h, conchFile->h, errno); +#endif return SQLITE_IOERR_LOCK; } @@ -44088,6 +44228,9 @@ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){ int len = osPread(conchFile->h, tBuf, PROXY_MAXCONCHLEN, 0); if( len<0 ){ storeLastErrno(pFile, errno); +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_LOCK, "proxyConchLock tries 2, pFile fd[%d], conchFile fd[%d], lastErrno[%d]", pFile->h, conchFile->h, errno); +#endif return SQLITE_IOERR_LOCK; } if( len>PROXY_PATHINDEX && tBuf[0]==(char)PROXY_CONCHVERSION){ @@ -44162,6 +44305,9 @@ static int proxyTakeConch(unixFile *pFile){ if( readLen<0 ){ /* I/O error: lastErrno set by seekAndRead */ storeLastErrno(pFile, conchFile->lastErrno); +#ifdef LOG_DUMP + sqlite3_log(SQLITE_IOERR_READ, "proxyTakeConch pFile fd[%d], conchFile fd[%d], lastErrno[%d]", pFile->h, conchFile->h, conchFile->lastErrno); +#endif rc = SQLITE_IOERR_READ; goto end_takeconch; }else if( readLen<=(PROXY_HEADERLEN+PROXY_HOSTIDLEN) || @@ -65214,7 +65360,9 @@ static void walRestartHdr(Wal *pWal, u32 salt1){ for(i=2; iaReadMark[i] = READMARK_NOT_USED; assert( pInfo->aReadMark[0]==0 ); } +static int checkHeaderValid(Pager *pager, u8 *zBuf, const char *logStr); +static int checkDbHeaderValid(sqlite3 *db, int iDbpage, u8 *zBuf); /* ** Copy as much content as we can from the WAL back into the database file ** in response to an sqlite3_wal_checkpoint() request or the equivalent. @@ -65355,6 +65503,8 @@ static int walCheckpoint( if( rc!=SQLITE_OK ) break; iOffset = (iDbpage-1)*(i64)szPage; testcase( IS_BIG_INT(iOffset) ); + rc = checkDbHeaderValid(db, iDbpage, zBuf); + if( rc!=SQLITE_OK ) break; rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset); if( rc!=SQLITE_OK ) break; } @@ -66749,6 +66899,10 @@ static int walWriteOneFrame( int rc; /* Result code from subfunctions */ void *pData; /* Data actually written */ u8 aFrame[WAL_FRAME_HDRSIZE]; /* Buffer to assemble frame-header in */ + if( pPage->pgno==1 ){ + rc = checkHeaderValid(pPage->pPager, pPage->pData, "walWrite"); + if( rc!=SQLITE_OK ) return rc; + } #if defined(SQLITE_HAS_CODEC) if( (pData = sqlite3PagerCodec(pPage))==0 ) return SQLITE_NOMEM_BKPT; #else @@ -67051,6 +67205,8 @@ SQLITE_PRIVATE int sqlite3WalFrames( return rc; } +static sqlite3_int64 g_lastCkptTime = 0; + /* ** This routine is called to implement sqlite3_wal_checkpoint() and ** related interfaces. @@ -67174,6 +67330,12 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint( walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1); pWal->ckptLock = 0; } +#ifdef LOG_DUMP + if( rc ){ + sqlite3_log(SQLITE_NOTICE, "ckpt rc[%d]", rc); + } + sqlite3OsCurrentTimeInt64(db->pVfs, &g_lastCkptTime); +#endif WALTRACE(("WAL%p: checkpoint %s\n", pWal, rc ? "failed" : "ok")); #ifdef SQLITE_ENABLE_SETLK_TIMEOUT if( rc==SQLITE_BUSY_TIMEOUT ) rc = SQLITE_BUSY; @@ -68550,6 +68712,30 @@ SQLITE_PRIVATE sqlite3_uint64 sqlite3BtreeSeekCount(Btree *pBt){ } #endif +static int checkHeaderValid(Pager *pager, u8 *zBuf, const char *logStr){ +#ifdef SQLITE_HAS_CODEC + if( pager==NULL || pager->pCodec ){ + return SQLITE_OK; + } +#endif + if( zBuf && strncmp((const char *)zBuf, zMagicHeader, 16)!=0 ){ + sqlite3_log(SQLITE_NOTADB, "[%s]wrong header format, memory might be overwritten!", logStr); + return SQLITE_NOTADB; + } + return SQLITE_OK; +} + +static int checkDbHeaderValid(sqlite3 *db, int iDbpage, u8 *zBuf){ + if( iDbpage==1 && db->aDb ){ + Btree *p = db->aDb[0].pBt; + if( p && p->pBt ){ + Pager *pager = sqlite3BtreePager(p); + return checkHeaderValid(pager, zBuf, "ckpt"); + } + } + return SQLITE_OK; +} + /* ** Implementation of the SQLITE_CORRUPT_PAGE() macro. Takes a single ** (MemPage*) as an argument. The (MemPage*) must not be NULL. @@ -70380,6 +70566,24 @@ static int decodeFlags(MemPage *pPage, int flagByte){ pPage->intKeyLeaf = 0; pPage->xCellSize = cellSizePtr; pPage->xParseCell = btreeParseCellPtrIndex; +#ifdef LOG_DUMP + sqlite3_log(SQLITE_CORRUPT, + "database corruption at page[%u], flagByte[%x], isInit[%u], intKey[%u], intKeyLeaf[%u], leaf[%u], " + "childPtrSize[%u], cellOffset[%u], nCell[%u], hdrOffset[%u], minLocal[%u], maxLocal[%u], last ckpt time[%lld]", + pPage->pgno, + flagByte, + pPage->isInit, + pPage->intKey, + pPage->intKeyLeaf, + pPage->leaf, + pPage->childPtrSize, + pPage->cellOffset, + pPage->nCell, + pPage->hdrOffset, + pPage->minLocal, + pPage->maxLocal, + g_lastCkptTime); +#endif return SQLITE_CORRUPT_PAGE(pPage); } pPage->max1bytePayload = pBt->max1bytePayload; @@ -104621,7 +104825,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ sqlite3WalkExprList(pWalker, pList); if( is_agg ){ #ifndef SQLITE_OMIT_WINDOWFUNC - if( pWin ){ + if( pWin && pParse->nErr==0 ){ Select *pSel = pNC->pWinSelect; assert( pWin==0 || (ExprUseYWin(pExpr) && pWin==pExpr->y.pWin) ); if( IN_RENAME_OBJECT==0 ){