Compare commits

...

11 Commits

Author SHA1 Message Date
dan f505fda498 Remove two incorrect assert() statements from the logic used to derive
column names and types from subqueries. This allows the SQL associated with CVE-2020-13871 (ticket [c8d3b9f0a750a529]) to be tested.

FossilOrigin-Name: d2e672203704aa18fdc652e9567eb29b71dae32e871f514308478a7a96025f29
2021-07-13 15:30:48 +00:00
dan 79410ac8ef Fix a defect in the query-flattener optimization identified by
ticket [8f157e8010b22af0]. This fix is associated with CVE-2020-15358.

FossilOrigin-Name: 9e001b635f3cff672e591204ab90deefe01baaefe64ff121bd2c32edd2d03675
2021-07-12 14:38:35 +00:00
drh 9539a09634 Provide the SQLITE_DEFAULT_LEGACY_ALTER_TABLE compile-time option.
FossilOrigin-Name: b2325a6e1cfa19e9fd533c1f7dacfc8e5aa4f2e111fa066a5c7d3040418fc8ad
2020-05-06 18:46:38 +00:00
drh 39ca0d51e5 More restrictions on changes to shadow tables when in defensive mode.
FossilOrigin-Name: b302b260ca9a4ca3d84771d9157fb1fc0b0e1ba175638f0c006cdf94f92a19c9
2020-01-17 15:33:47 +00:00
drh 3b96ec9d07 Validate the type, name, and tbl_name fields of the sqlite_master table when
loading the schema, unless writable_schema is engaged.

FossilOrigin-Name: 3d13fbf248e6bcb997c301530ee834c6f1fc21add7f46b673d0f63e986c60680
2020-01-17 15:24:13 +00:00
drh 6e3609ae82 Do not allow shadow tables to be dropped in defensive mode.
FossilOrigin-Name: ad1f760f164c819eac24597dd621586933c8ca77f79efd2e4773f5599e089c5e
2020-01-17 14:56:11 +00:00
drh c19133d316 Import the 3.31.0-beta FTS3/4 code directly into the 3.28 branch, thus
providing 3.28 with all the latest 3.31 fixes.  FTS3 has not been enhanced
to use any core functionality that was not already available in 3.23, so
no modifications were made to FTS3 sources for this import.

FossilOrigin-Name: be4269c624b30dd744f80448558b650b505e04c7748386bb461158f5b1823680
2020-01-17 14:30:29 +00:00
mistachkin 49ab77f0ce Fix a problem where self-joins on views that are aggregate queries may return the wrong result. Cherrypick of [74ef97bf51dd531a].
FossilOrigin-Name: 2f0a564f6ef148e4f63b11ccfc9d1e65cb2755cf923e22f2ffef83b1f176943b
2019-07-18 20:55:07 +00:00
mistachkin ca2f21ac7f Fix harmless compiler warning in lemon.
FossilOrigin-Name: 3a0524295371d7b19d260c60fcbad96d60fcf098580a69959c13c7fcd7d41389
2019-06-03 15:10:24 +00:00
mistachkin c4c1a518e5 Fix the count-of-view optimization so that it is (correctly) disabled for a query that includes a WHERE clause or a GROUP BY clause. Cherrypick of [05897ca48a40c6771].
FossilOrigin-Name: 583e5a0ab6bdf3ce3d76852089160a8d11df4c3dd151050a70997b3720c3d538
2019-06-03 13:53:29 +00:00
mistachkin 100ab2480d Minor simplification of NULL value handling for STAT4. Cherrypick of [69bad9257f8db6a2] from trunk.
FossilOrigin-Name: 442c177dc444d614e8a665cfb62c4576cbf1002ed147dc272cea4e80cd9b92b4
2019-04-23 15:21:00 +00:00
29 changed files with 778 additions and 251 deletions
+105 -46
View File
@@ -352,12 +352,7 @@ int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){
v = (*ptr++); \
if( (v & mask2)==0 ){ var = v; return ret; }
/*
** Read a 64-bit variable-length integer from memory starting at p[0].
** Return the number of bytes read, or 0 on error.
** The value is stored in *v.
*/
int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
int sqlite3Fts3GetVarintU(const char *pBuf, sqlite_uint64 *v){
const unsigned char *p = (const unsigned char*)pBuf;
const unsigned char *pStart = p;
u32 a;
@@ -379,6 +374,41 @@ int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
return (int)(p - pStart);
}
/*
** Read a 64-bit variable-length integer from memory starting at p[0].
** Return the number of bytes read, or 0 on error.
** The value is stored in *v.
*/
int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
return sqlite3Fts3GetVarintU(pBuf, (sqlite3_uint64*)v);
}
/*
** Read a 64-bit variable-length integer from memory starting at p[0] and
** not extending past pEnd[-1].
** Return the number of bytes read, or 0 on error.
** The value is stored in *v.
*/
int sqlite3Fts3GetVarintBounded(
const char *pBuf,
const char *pEnd,
sqlite_int64 *v
){
const unsigned char *p = (const unsigned char*)pBuf;
const unsigned char *pStart = p;
const unsigned char *pX = (const unsigned char*)pEnd;
u64 b = 0;
int shift;
for(shift=0; shift<=63; shift+=7){
u64 c = p<pX ? *p : 0;
p++;
b += (c&0x7F) << shift;
if( (c & 0x80)==0 ) break;
}
*v = b;
return (int)(p - pStart);
}
/*
** Similar to sqlite3Fts3GetVarint(), except that the output is truncated to
** a non-negative 32-bit integer before it is returned.
@@ -1474,6 +1504,10 @@ static int fts3InitVtab(
fts3DatabasePageSize(&rc, p);
p->nNodeSize = p->nPgsz-35;
#if defined(SQLITE_DEBUG)||defined(SQLITE_TEST)
p->nMergeCount = FTS3_MERGE_COUNT;
#endif
/* Declare the table schema to SQLite. */
fts3DeclareVtab(&rc, p);
@@ -1569,6 +1603,10 @@ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
int iDocidLe = -1; /* Index of docid<=x constraint, if present */
int iIdx;
if( p->bLock ){
return SQLITE_ERROR;
}
/* By default use a full table scan. This is an expensive option,
** so search through the constraints to see if a more efficient
** strategy is possible.
@@ -1767,7 +1805,11 @@ static int fts3CursorSeekStmt(Fts3Cursor *pCsr){
}else{
zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist);
if( !zSql ) return SQLITE_NOMEM;
rc = sqlite3_prepare_v3(p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0);
p->bLock++;
rc = sqlite3_prepare_v3(
p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0
);
p->bLock--;
sqlite3_free(zSql);
}
if( rc==SQLITE_OK ) pCsr->bSeekStmt = 1;
@@ -1785,11 +1827,15 @@ static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
if( pCsr->isRequireSeek ){
rc = fts3CursorSeekStmt(pCsr);
if( rc==SQLITE_OK ){
Fts3Table *pTab = (Fts3Table*)pCsr->base.pVtab;
pTab->bLock++;
sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId);
pCsr->isRequireSeek = 0;
if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){
pTab->bLock--;
return SQLITE_OK;
}else{
pTab->bLock--;
rc = sqlite3_reset(pCsr->pStmt);
if( rc==SQLITE_OK && ((Fts3Table *)pCsr->base.pVtab)->zContentTbl==0 ){
/* If no row was found and no error has occurred, then the %_content
@@ -1961,7 +2007,7 @@ static int fts3SelectLeaf(
fts3GetVarint32(zNode, &iHeight);
rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2);
assert( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) );
assert_fts3_nc( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) );
if( rc==SQLITE_OK && iHeight>1 ){
char *zBlob = 0; /* Blob read from %_segments table */
@@ -1981,7 +2027,13 @@ static int fts3SelectLeaf(
rc = sqlite3Fts3ReadBlock(p, piLeaf?*piLeaf:*piLeaf2, &zBlob, &nBlob, 0);
}
if( rc==SQLITE_OK ){
rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, piLeaf2);
int iNewHeight = 0;
fts3GetVarint32(zBlob, &iNewHeight);
if( iNewHeight>=iHeight ){
rc = FTS_CORRUPT_VTAB;
}else{
rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, piLeaf2);
}
}
sqlite3_free(zBlob);
}
@@ -2086,10 +2138,11 @@ static void fts3ColumnlistCopy(char **pp, char **ppPoslist){
}
/*
** Value used to signify the end of an position-list. This is safe because
** it is not possible to have a document with 2^31 terms.
** Value used to signify the end of an position-list. This must be
** as large or larger than any value that might appear on the
** position-list, even a position list that has been corrupted.
*/
#define POSITION_LIST_END 0x7fffffff
#define POSITION_LIST_END LARGEST_INT64
/*
** This function is used to help parse position-lists. When this function is
@@ -2165,14 +2218,14 @@ static int fts3PoslistMerge(
fts3GetVarint32(&p1[1], &iCol1);
if( iCol1==0 ) return FTS_CORRUPT_VTAB;
}
else if( *p1==POS_END ) iCol1 = POSITION_LIST_END;
else if( *p1==POS_END ) iCol1 = 0x7fffffff;
else iCol1 = 0;
if( *p2==POS_COLUMN ){
fts3GetVarint32(&p2[1], &iCol2);
if( iCol2==0 ) return FTS_CORRUPT_VTAB;
}
else if( *p2==POS_END ) iCol2 = POSITION_LIST_END;
else if( *p2==POS_END ) iCol2 = 0x7fffffff;
else iCol2 = 0;
if( iCol1==iCol2 ){
@@ -2435,12 +2488,12 @@ static void fts3GetDeltaVarint3(
if( *pp>=pEnd ){
*pp = 0;
}else{
sqlite3_int64 iVal;
*pp += sqlite3Fts3GetVarint(*pp, &iVal);
u64 iVal;
*pp += sqlite3Fts3GetVarintU(*pp, &iVal);
if( bDescIdx ){
*pVal -= iVal;
*pVal = (i64)((u64)*pVal - iVal);
}else{
*pVal += iVal;
*pVal = (i64)((u64)*pVal + iVal);
}
}
}
@@ -2467,14 +2520,16 @@ static void fts3PutDeltaVarint3(
int *pbFirst, /* IN/OUT: True after first int written */
sqlite3_int64 iVal /* Write this value to the list */
){
sqlite3_int64 iWrite;
sqlite3_uint64 iWrite;
if( bDescIdx==0 || *pbFirst==0 ){
iWrite = iVal - *piPrev;
assert_fts3_nc( *pbFirst==0 || iVal>=*piPrev );
iWrite = (u64)iVal - (u64)*piPrev;
}else{
iWrite = *piPrev - iVal;
assert_fts3_nc( *piPrev>=iVal );
iWrite = (u64)*piPrev - (u64)iVal;
}
assert( *pbFirst || *piPrev==0 );
assert( *pbFirst==0 || iWrite>0 );
assert_fts3_nc( *pbFirst==0 || iWrite>0 );
*pp += sqlite3Fts3PutVarint(*pp, iWrite);
*piPrev = iVal;
*pbFirst = 1;
@@ -2490,7 +2545,8 @@ static void fts3PutDeltaVarint3(
** Using this makes it easier to write code that can merge doclists that are
** sorted in either ascending or descending order.
*/
#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1-i2))
/* #define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i64)((u64)i1-i2)) */
#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1>i2?1:((i1==i2)?0:-1)))
/*
** This function does an "OR" merge of two doclists (output contains all
@@ -2580,6 +2636,8 @@ static int fts3DoclistOrMerge(
fts3PoslistCopy(&p, &p2);
fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
}
assert( (p-aOut)<=((p1?(p1-a1):n1)+(p2?(p2-a2):n2)+FTS3_VARINT_MAX-1) );
}
if( rc!=SQLITE_OK ){
@@ -2902,7 +2960,7 @@ static int fts3SegReaderCursor(
** Fts3SegReaderPending might segfault, as the data structures used by
** fts4aux are not completely populated. So it's easiest to filter these
** calls out here. */
if( iLevel<0 && p->aIndex ){
if( iLevel<0 && p->aIndex && p->iPrevLangid==iLangid ){
Fts3SegReader *pSeg = 0;
rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix||isScan, &pSeg);
if( rc==SQLITE_OK && pSeg ){
@@ -3165,6 +3223,8 @@ static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
int rc;
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
if( pCsr->eSearch==FTS3_DOCID_SEARCH || pCsr->eSearch==FTS3_FULLSCAN_SEARCH ){
Fts3Table *pTab = (Fts3Table*)pCursor->pVtab;
pTab->bLock++;
if( SQLITE_ROW!=sqlite3_step(pCsr->pStmt) ){
pCsr->isEof = 1;
rc = sqlite3_reset(pCsr->pStmt);
@@ -3172,6 +3232,7 @@ static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0);
rc = SQLITE_OK;
}
pTab->bLock--;
}else{
rc = fts3EvalNext((Fts3Cursor *)pCursor);
}
@@ -3179,18 +3240,6 @@ static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
return rc;
}
/*
** The following are copied from sqliteInt.h.
**
** Constants for the largest and smallest possible 64-bit signed integers.
** These macros are designed to work correctly on both 32-bit and 64-bit
** compilers.
*/
#ifndef SQLITE_AMALGAMATION
# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
#endif
/*
** If the numeric type of argument pVal is "integer", then return it
** converted to a 64-bit signed integer. Otherwise, return a copy of
@@ -3244,6 +3293,10 @@ static int fts3FilterMethod(
UNUSED_PARAMETER(idxStr);
UNUSED_PARAMETER(nVal);
if( p->bLock ){
return SQLITE_ERROR;
}
eSearch = (idxNum & 0x0000FFFF);
assert( eSearch>=0 && eSearch<=(FTS3_FULLTEXT_SEARCH+p->nColumn) );
assert( p->pSegments==0 );
@@ -3315,7 +3368,11 @@ static int fts3FilterMethod(
);
}
if( zSql ){
rc = sqlite3_prepare_v3(p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0);
p->bLock++;
rc = sqlite3_prepare_v3(
p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0
);
p->bLock--;
sqlite3_free(zSql);
}else{
rc = SQLITE_NOMEM;
@@ -4332,7 +4389,7 @@ static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
int bIncrOk = (bOptOk
&& pCsr->bDesc==pTab->bDescIdx
&& p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0
#ifdef SQLITE_TEST
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
&& pTab->bNoIncrDoclist==0
#endif
);
@@ -4474,15 +4531,16 @@ static void fts3EvalDlPhraseNext(
u8 *pbEof
){
char *pIter; /* Used to iterate through aAll */
char *pEnd = &pDL->aAll[pDL->nAll]; /* 1 byte past end of aAll */
char *pEnd; /* 1 byte past end of aAll */
if( pDL->pNextDocid ){
pIter = pDL->pNextDocid;
assert( pDL->aAll!=0 || pIter==0 );
}else{
pIter = pDL->aAll;
}
if( pIter>=pEnd ){
if( pIter==0 || pIter>=(pEnd = pDL->aAll + pDL->nAll) ){
/* We have already reached the end of this doclist. EOF. */
*pbEof = 1;
}else{
@@ -4854,12 +4912,13 @@ static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
rc = sqlite3Fts3SelectDoctotal(p, &pStmt);
if( rc!=SQLITE_OK ) return rc;
a = sqlite3_column_blob(pStmt, 0);
assert( a );
pEnd = &a[sqlite3_column_bytes(pStmt, 0)];
a += sqlite3Fts3GetVarint(a, &nDoc);
while( a<pEnd ){
a += sqlite3Fts3GetVarint(a, &nByte);
testcase( a==0 ); /* If %_stat.value set to X'' */
if( a ){
pEnd = &a[sqlite3_column_bytes(pStmt, 0)];
a += sqlite3Fts3GetVarintBounded(a, pEnd, &nDoc);
while( a<pEnd ){
a += sqlite3Fts3GetVarintBounded(a, pEnd, &nByte);
}
}
if( nDoc==0 || nByte==0 ){
sqlite3_reset(pStmt);
+17 -1
View File
@@ -196,6 +196,9 @@ typedef sqlite3_int64 i64; /* 8-byte signed integer */
# define TESTONLY(X)
#endif
#define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32))
#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
#endif /* SQLITE_AMALGAMATION */
#ifdef SQLITE_DEBUG
@@ -239,6 +242,7 @@ struct Fts3Table {
char *zLanguageid; /* languageid=xxx option, or NULL */
int nAutoincrmerge; /* Value configured by 'automerge' */
u32 nLeafAdd; /* Number of leaf blocks added this trans */
int bLock; /* Used to prevent recursive content= tbls */
/* Precompiled statements used by the implementation. Each of these
** statements is run and reset within a single virtual table API call.
@@ -297,13 +301,23 @@ struct Fts3Table {
int mxSavepoint; /* Largest valid xSavepoint integer */
#endif
#ifdef SQLITE_TEST
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
/* True to disable the incremental doclist optimization. This is controled
** by special insert command 'test-no-incr-doclist'. */
int bNoIncrDoclist;
/* Number of segments in a level */
int nMergeCount;
#endif
};
/* Macro to find the number of segments to merge */
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
# define MergeCount(P) ((P)->nMergeCount)
#else
# define MergeCount(P) FTS3_MERGE_COUNT
#endif
/*
** When the core wants to read from the virtual table, it creates a
** virtual table cursor (an instance of the following structure) using
@@ -567,6 +581,8 @@ int sqlite3Fts3Incrmerge(Fts3Table*,int,int);
void sqlite3Fts3ErrMsg(char**,const char*,...);
int sqlite3Fts3PutVarint(char *, sqlite3_int64);
int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
int sqlite3Fts3GetVarintU(const char *, sqlite_uint64 *);
int sqlite3Fts3GetVarintBounded(const char*,const char*,sqlite3_int64*);
int sqlite3Fts3GetVarint32(const char *, int *);
int sqlite3Fts3VarintLen(sqlite3_uint64);
void sqlite3Fts3Dequote(char *);
+33 -11
View File
@@ -433,10 +433,10 @@ static void fts3SnippetDetails(
while( iCsr<(iStart+pIter->nSnippet) && iCsr>=iStart ){
int j;
u64 mPhrase = (u64)1 << i;
u64 mPhrase = (u64)1 << (i%64);
u64 mPos = (u64)1 << (iCsr - iStart);
assert( iCsr>=iStart && (iCsr - iStart)<=64 );
assert( i>=0 && i<=64 );
assert( i>=0 );
if( (mCover|mCovered)&mPhrase ){
iScore++;
}else{
@@ -560,7 +560,7 @@ static int fts3BestSnippet(
/* Set the *pmSeen output variable. */
for(i=0; i<nList; i++){
if( sIter.aPhrase[i].pHead ){
*pmSeen |= (u64)1 << i;
*pmSeen |= (u64)1 << (i%64);
}
}
@@ -1038,11 +1038,15 @@ static int fts3MatchinfoSelectDoctotal(
Fts3Table *pTab,
sqlite3_stmt **ppStmt,
sqlite3_int64 *pnDoc,
const char **paLen
const char **paLen,
const char **ppEnd
){
sqlite3_stmt *pStmt;
const char *a;
const char *pEnd;
sqlite3_int64 nDoc;
int n;
if( !*ppStmt ){
int rc = sqlite3Fts3SelectDoctotal(pTab, ppStmt);
@@ -1051,12 +1055,20 @@ static int fts3MatchinfoSelectDoctotal(
pStmt = *ppStmt;
assert( sqlite3_data_count(pStmt)==1 );
n = sqlite3_column_bytes(pStmt, 0);
a = sqlite3_column_blob(pStmt, 0);
a += sqlite3Fts3GetVarint(a, &nDoc);
if( nDoc==0 ) return FTS_CORRUPT_VTAB;
*pnDoc = (u32)nDoc;
if( a==0 ){
return FTS_CORRUPT_VTAB;
}
pEnd = a + n;
a += sqlite3Fts3GetVarintBounded(a, pEnd, &nDoc);
if( nDoc<=0 || a>pEnd ){
return FTS_CORRUPT_VTAB;
}
*pnDoc = nDoc;
if( paLen ) *paLen = a;
if( ppEnd ) *ppEnd = pEnd;
return SQLITE_OK;
}
@@ -1237,7 +1249,7 @@ static int fts3MatchinfoValues(
case FTS3_MATCHINFO_NDOC:
if( bGlobal ){
sqlite3_int64 nDoc = 0;
rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, 0);
rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, 0, 0);
pInfo->aMatchinfo[0] = (u32)nDoc;
}
break;
@@ -1246,14 +1258,19 @@ static int fts3MatchinfoValues(
if( bGlobal ){
sqlite3_int64 nDoc; /* Number of rows in table */
const char *a; /* Aggregate column length array */
const char *pEnd; /* First byte past end of length array */
rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, &a);
rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, &a, &pEnd);
if( rc==SQLITE_OK ){
int iCol;
for(iCol=0; iCol<pInfo->nCol; iCol++){
u32 iVal;
sqlite3_int64 nToken;
a += sqlite3Fts3GetVarint(a, &nToken);
if( a>pEnd ){
rc = SQLITE_CORRUPT_VTAB;
break;
}
iVal = (u32)(((u32)(nToken&0xffffffff)+nDoc/2)/nDoc);
pInfo->aMatchinfo[iCol] = iVal;
}
@@ -1267,9 +1284,14 @@ static int fts3MatchinfoValues(
if( rc==SQLITE_OK ){
int iCol;
const char *a = sqlite3_column_blob(pSelectDocsize, 0);
const char *pEnd = a + sqlite3_column_bytes(pSelectDocsize, 0);
for(iCol=0; iCol<pInfo->nCol; iCol++){
sqlite3_int64 nToken;
a += sqlite3Fts3GetVarint(a, &nToken);
a += sqlite3Fts3GetVarintBounded(a, pEnd, &nToken);
if( a>pEnd ){
rc = SQLITE_CORRUPT_VTAB;
break;
}
pInfo->aMatchinfo[iCol] = (u32)nToken;
}
}
@@ -1300,7 +1322,7 @@ static int fts3MatchinfoValues(
if( rc!=SQLITE_OK ) break;
if( bGlobal ){
if( pCsr->pDeferred ){
rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &pInfo->nDoc, 0);
rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &pInfo->nDoc,0,0);
if( rc!=SQLITE_OK ) break;
}
rc = fts3ExprIterate(pExpr, fts3ExprGlobalHitsCb,(void*)pInfo);
+4 -2
View File
@@ -390,7 +390,9 @@ int queryTokenizer(
sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
if( SQLITE_ROW==sqlite3_step(pStmt) ){
if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){
if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB
&& sqlite3_column_bytes(pStmt, 0)==sizeof(*pp)
){
memcpy((void *)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp));
}
}
@@ -479,7 +481,7 @@ int sqlite3Fts3InitHashTable(
){
int rc = SQLITE_OK;
void *p = (void *)pHash;
const int any = SQLITE_ANY;
const int any = SQLITE_UTF8|SQLITE_DIRECTONLY;
#ifdef SQLITE_TEST
char *zTest = 0;
+140 -79
View File
@@ -23,7 +23,7 @@
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#define FTS_MAX_APPENDABLE_HEIGHT 16
@@ -67,7 +67,7 @@ int test_fts3_node_chunk_threshold = (4*1024)*4;
#endif
/*
** The two values that may be meaningfully bound to the :1 parameter in
** The values that may be meaningfully bound to the :1 parameter in
** statements SQL_REPLACE_STAT and SQL_SELECT_STAT.
*/
#define FTS_STAT_DOCTOTAL 0
@@ -335,7 +335,7 @@ static int fts3SqlStmt(
** returns zero rows. */
/* 28 */ "SELECT level, count(*) AS cnt FROM %Q.'%q_segdir' "
" GROUP BY level HAVING cnt>=?"
" ORDER BY (level %% 1024) ASC LIMIT 1",
" ORDER BY (level %% 1024) ASC, 2 DESC LIMIT 1",
/* Estimate the upper limit on the number of leaf nodes in a new segment
** created by merging the oldest :2 segments from absolute level :1. See
@@ -696,7 +696,7 @@ static int fts3PendingListAppend(
assert( !p || p->iLastDocid<=iDocid );
if( !p || p->iLastDocid!=iDocid ){
sqlite3_int64 iDelta = iDocid - (p ? p->iLastDocid : 0);
u64 iDelta = (u64)iDocid - (u64)(p ? p->iLastDocid : 0);
if( p ){
assert( p->nData<p->nSpace );
assert( p->aData[p->nData]==0 );
@@ -1153,7 +1153,7 @@ static int fts3AllocateSegdirIdx(
** segment and allocate (newly freed) index 0 at level iLevel. Otherwise,
** if iNext is less than FTS3_MERGE_COUNT, allocate index iNext.
*/
if( iNext>=FTS3_MERGE_COUNT ){
if( iNext>=MergeCount(p) ){
fts3LogMerge(16, getAbsoluteLevel(p, iLangid, iIndex, iLevel));
rc = fts3SegmentMerge(p, iLangid, iIndex, iLevel);
*piIdx = 0;
@@ -1237,6 +1237,8 @@ int sqlite3Fts3ReadBlock(
}
*paBlob = aByte;
}
}else if( rc==SQLITE_ERROR ){
rc = FTS_CORRUPT_VTAB;
}
return rc;
@@ -1379,7 +1381,7 @@ static int fts3SegReaderNext(
pNext += fts3GetVarint32(pNext, &nSuffix);
if( nSuffix<=0
|| (&pReader->aNode[pReader->nNode] - pNext)<nSuffix
|| nPrefix>pReader->nTermAlloc
|| nPrefix>pReader->nTerm
){
return FTS_CORRUPT_VTAB;
}
@@ -1529,18 +1531,18 @@ static int fts3SegReaderNextDocid(
}else{
rc = fts3SegReaderRequire(pReader, p, FTS3_VARINT_MAX);
if( rc==SQLITE_OK ){
sqlite3_int64 iDelta;
pReader->pOffsetList = p + sqlite3Fts3GetVarint(p, &iDelta);
u64 iDelta;
pReader->pOffsetList = p + sqlite3Fts3GetVarintU(p, &iDelta);
if( pTab->bDescIdx ){
pReader->iDocid -= iDelta;
pReader->iDocid = (i64)((u64)pReader->iDocid - iDelta);
}else{
pReader->iDocid += iDelta;
pReader->iDocid = (i64)((u64)pReader->iDocid + iDelta);
}
}
}
}
return SQLITE_OK;
return rc;
}
@@ -2030,6 +2032,11 @@ static int fts3NodeAddTerm(
nPrefix = fts3PrefixCompress(pTree->zTerm, pTree->nTerm, zTerm, nTerm);
nSuffix = nTerm-nPrefix;
/* If nSuffix is zero or less, then zTerm/nTerm must be a prefix of
** pWriter->zTerm/pWriter->nTerm. i.e. must be equal to or less than when
** compared with BINARY collation. This indicates corruption. */
if( nSuffix<=0 ) return FTS_CORRUPT_VTAB;
nReq += sqlite3Fts3VarintLen(nPrefix)+sqlite3Fts3VarintLen(nSuffix)+nSuffix;
if( nReq<=p->nNodeSize || !pTree->zTerm ){
@@ -2274,6 +2281,7 @@ static int fts3SegWriterAdd(
int rc;
/* The current leaf node is full. Write it out to the database. */
if( pWriter->iFree==LARGEST_INT64 ) return FTS_CORRUPT_VTAB;
rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, nData);
if( rc!=SQLITE_OK ) return rc;
p->nLeafAdd++;
@@ -2323,9 +2331,11 @@ static int fts3SegWriterAdd(
/* Append the prefix-compressed term and doclist to the buffer. */
nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nPrefix);
nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nSuffix);
assert( nSuffix>0 );
memcpy(&pWriter->aData[nData], &zTerm[nPrefix], nSuffix);
nData += nSuffix;
nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nDoclist);
assert( nDoclist>0 );
memcpy(&pWriter->aData[nData], aDoclist, nDoclist);
pWriter->nData = nData + nDoclist;
@@ -2345,6 +2355,7 @@ static int fts3SegWriterAdd(
pWriter->zTerm = zNew;
}
assert( pWriter->zTerm==pWriter->zMalloc );
assert( nTerm>0 );
memcpy(pWriter->zTerm, zTerm, nTerm);
}else{
pWriter->zTerm = (char *)zTerm;
@@ -2619,14 +2630,14 @@ static void fts3ColumnFilter(
nList -= (int)(p - pList);
pList = p;
if( nList==0 ){
if( nList<=0 ){
break;
}
p = &pList[1];
p += fts3GetVarint32(p, &iCurrent);
}
if( bZero && &pList[nList]!=pEnd ){
if( bZero && (pEnd - &pList[nList])>0){
memset(&pList[nList], 0, pEnd - &pList[nList]);
}
*ppList = pList;
@@ -2653,6 +2664,7 @@ static int fts3MsrBufferData(
pMsr->aBuffer = pNew;
}
assert( nList>0 );
memcpy(pMsr->aBuffer, pList, nList);
return SQLITE_OK;
}
@@ -2966,14 +2978,12 @@ int sqlite3Fts3SegReaderStep(
** doclist. */
sqlite3_int64 iDelta;
if( p->bDescIdx && nDoclist>0 ){
iDelta = iPrev - iDocid;
if( iPrev<=iDocid ) return FTS_CORRUPT_VTAB;
iDelta = (i64)((u64)iPrev - (u64)iDocid);
}else{
iDelta = iDocid - iPrev;
if( nDoclist>0 && iPrev>=iDocid ) return FTS_CORRUPT_VTAB;
iDelta = (i64)((u64)iDocid - (u64)iPrev);
}
if( iDelta<=0 && (nDoclist>0 || iDelta!=iDocid) ){
return FTS_CORRUPT_VTAB;
}
assert( nDoclist>0 || iDelta==iDocid );
nByte = sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0);
if( nDoclist+nByte>pCsr->nBuffer ){
@@ -3255,7 +3265,7 @@ static int fts3SegmentMerge(
csr.zTerm, csr.nTerm, csr.aDoclist, csr.nDoclist);
}
if( rc!=SQLITE_OK ) goto finished;
assert( pWriter || bIgnoreEmpty );
assert_fts3_nc( pWriter || bIgnoreEmpty );
if( iLevel!=FTS3_SEGCURSOR_PENDING ){
rc = fts3DeleteSegdir(
@@ -3482,7 +3492,10 @@ static int fts3DoOptimize(Fts3Table *p, int bReturnDone){
int rc;
sqlite3_stmt *pAllLangid = 0;
rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
rc = sqlite3Fts3PendingTermsFlush(p);
if( rc==SQLITE_OK ){
rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
}
if( rc==SQLITE_OK ){
int rc2;
sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid);
@@ -3503,7 +3516,6 @@ static int fts3DoOptimize(Fts3Table *p, int bReturnDone){
}
sqlite3Fts3SegmentsClose(p);
sqlite3Fts3PendingTermsClear(p);
return (rc==SQLITE_OK && bReturnDone && bSeenDone) ? SQLITE_DONE : rc;
}
@@ -3754,7 +3766,7 @@ static int nodeReaderNext(NodeReader *p){
}
p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nSuffix);
if( nPrefix>p->iOff || nSuffix>p->nNode-p->iOff ){
if( nPrefix>p->term.n || nSuffix>p->nNode-p->iOff || nSuffix==0 ){
return FTS_CORRUPT_VTAB;
}
blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc);
@@ -3773,7 +3785,7 @@ static int nodeReaderNext(NodeReader *p){
}
}
assert( p->iOff<=p->nNode );
assert_fts3_nc( p->iOff<=p->nNode );
return rc;
}
@@ -3797,14 +3809,14 @@ static int nodeReaderInit(NodeReader *p, const char *aNode, int nNode){
p->nNode = nNode;
/* Figure out if this is a leaf or an internal node. */
if( p->aNode[0] ){
if( aNode && aNode[0] ){
/* An internal node. */
p->iOff = 1 + sqlite3Fts3GetVarint(&p->aNode[1], &p->iChild);
}else{
p->iOff = 1;
}
return nodeReaderNext(p);
return aNode ? nodeReaderNext(p) : SQLITE_OK;
}
/*
@@ -3841,6 +3853,7 @@ static int fts3IncrmergePush(
** be added to. */
nPrefix = fts3PrefixCompress(pNode->key.a, pNode->key.n, zTerm, nTerm);
nSuffix = nTerm - nPrefix;
if(nSuffix<=0 ) return FTS_CORRUPT_VTAB;
nSpace = sqlite3Fts3VarintLen(nPrefix);
nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix;
@@ -3934,13 +3947,14 @@ static int fts3AppendToNode(
/* Node must have already been started. There must be a doclist for a
** leaf node, and there must not be a doclist for an internal node. */
assert( pNode->n>0 );
assert( (pNode->a[0]=='\0')==(aDoclist!=0) );
assert_fts3_nc( (pNode->a[0]=='\0')==(aDoclist!=0) );
blobGrowBuffer(pPrev, nTerm, &rc);
if( rc!=SQLITE_OK ) return rc;
nPrefix = fts3PrefixCompress(pPrev->a, pPrev->n, zTerm, nTerm);
nSuffix = nTerm - nPrefix;
if( nSuffix<=0 ) return FTS_CORRUPT_VTAB;
memcpy(pPrev->a, zTerm, nTerm);
pPrev->n = nTerm;
@@ -4150,7 +4164,7 @@ static int fts3TermCmp(
int nCmp = MIN(nLhs, nRhs);
int res;
res = memcmp(zLhs, zRhs, nCmp);
res = (nCmp ? memcmp(zLhs, zRhs, nCmp) : 0);
if( res==0 ) res = nLhs - nRhs;
return res;
@@ -4234,6 +4248,10 @@ static int fts3IncrmergeLoad(
pWriter->bNoLeafData = (pWriter->nLeafData==0);
nRoot = sqlite3_column_bytes(pSelect, 4);
aRoot = sqlite3_column_blob(pSelect, 4);
if( aRoot==0 ){
sqlite3_reset(pSelect);
return nRoot ? SQLITE_NOMEM : FTS_CORRUPT_VTAB;
}
}else{
return sqlite3_reset(pSelect);
}
@@ -4269,6 +4287,10 @@ static int fts3IncrmergeLoad(
int i;
int nHeight = (int)aRoot[0];
NodeWriter *pNode;
if( nHeight<1 || nHeight>FTS_MAX_APPENDABLE_HEIGHT ){
sqlite3_reset(pSelect);
return FTS_CORRUPT_VTAB;
}
pWriter->nLeafEst = (int)((iEnd - iStart) + 1)/FTS_MAX_APPENDABLE_HEIGHT;
pWriter->iStart = iStart;
@@ -4282,34 +4304,42 @@ static int fts3IncrmergeLoad(
pNode = &pWriter->aNodeWriter[nHeight];
pNode->iBlock = pWriter->iStart + pWriter->nLeafEst*nHeight;
blobGrowBuffer(&pNode->block, MAX(nRoot, p->nNodeSize), &rc);
blobGrowBuffer(&pNode->block,
MAX(nRoot, p->nNodeSize)+FTS3_NODE_PADDING, &rc
);
if( rc==SQLITE_OK ){
memcpy(pNode->block.a, aRoot, nRoot);
pNode->block.n = nRoot;
memset(&pNode->block.a[nRoot], 0, FTS3_NODE_PADDING);
}
for(i=nHeight; i>=0 && rc==SQLITE_OK; i--){
NodeReader reader;
pNode = &pWriter->aNodeWriter[i];
rc = nodeReaderInit(&reader, pNode->block.a, pNode->block.n);
while( reader.aNode && rc==SQLITE_OK ) rc = nodeReaderNext(&reader);
blobGrowBuffer(&pNode->key, reader.term.n, &rc);
if( rc==SQLITE_OK ){
memcpy(pNode->key.a, reader.term.a, reader.term.n);
pNode->key.n = reader.term.n;
if( i>0 ){
char *aBlock = 0;
int nBlock = 0;
pNode = &pWriter->aNodeWriter[i-1];
pNode->iBlock = reader.iChild;
rc = sqlite3Fts3ReadBlock(p, reader.iChild, &aBlock, &nBlock, 0);
blobGrowBuffer(&pNode->block, MAX(nBlock, p->nNodeSize), &rc);
if( rc==SQLITE_OK ){
memcpy(pNode->block.a, aBlock, nBlock);
pNode->block.n = nBlock;
if( pNode->block.a){
rc = nodeReaderInit(&reader, pNode->block.a, pNode->block.n);
while( reader.aNode && rc==SQLITE_OK ) rc = nodeReaderNext(&reader);
blobGrowBuffer(&pNode->key, reader.term.n, &rc);
if( rc==SQLITE_OK ){
memcpy(pNode->key.a, reader.term.a, reader.term.n);
pNode->key.n = reader.term.n;
if( i>0 ){
char *aBlock = 0;
int nBlock = 0;
pNode = &pWriter->aNodeWriter[i-1];
pNode->iBlock = reader.iChild;
rc = sqlite3Fts3ReadBlock(p, reader.iChild, &aBlock, &nBlock, 0);
blobGrowBuffer(&pNode->block,
MAX(nBlock, p->nNodeSize)+FTS3_NODE_PADDING, &rc
);
if( rc==SQLITE_OK ){
memcpy(pNode->block.a, aBlock, nBlock);
pNode->block.n = nBlock;
memset(&pNode->block.a[nBlock], 0, FTS3_NODE_PADDING);
}
sqlite3_free(aBlock);
}
sqlite3_free(aBlock);
}
}
nodeReaderRelease(&reader);
@@ -4552,7 +4582,10 @@ static int fts3TruncateNode(
NodeReader reader; /* Reader object */
Blob prev = {0, 0, 0}; /* Previous term written to new node */
int rc = SQLITE_OK; /* Return code */
int bLeaf = aNode[0]=='\0'; /* True for a leaf node */
int bLeaf; /* True for a leaf node */
if( nNode<1 ) return FTS_CORRUPT_VTAB;
bLeaf = aNode[0]=='\0';
/* Allocate required output space */
blobGrowBuffer(pNew, nNode, &rc);
@@ -4818,13 +4851,17 @@ static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){
const int nHint = pHint->n;
int i;
i = pHint->n-2;
i = pHint->n-1;
if( (pHint->a[i] & 0x80) ) return FTS_CORRUPT_VTAB;
while( i>0 && (pHint->a[i-1] & 0x80) ) i--;
if( i==0 ) return FTS_CORRUPT_VTAB;
i--;
while( i>0 && (pHint->a[i-1] & 0x80) ) i--;
pHint->n = i;
i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel);
i += fts3GetVarint32(&pHint->a[i], pnInput);
assert( i<=nHint );
if( i!=nHint ) return FTS_CORRUPT_VTAB;
return SQLITE_OK;
@@ -4894,8 +4931,14 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
rc = fts3IncrmergeHintPop(&hint, &iHintAbsLevel, &nHintSeg);
if( nSeg<0 || (iAbsLevel % nMod) >= (iHintAbsLevel % nMod) ){
/* Based on the scan in the block above, it is known that there
** are no levels with a relative level smaller than that of
** iAbsLevel with more than nSeg segments, or if nSeg is -1,
** no levels with more than nMin segments. Use this to limit the
** value of nHintSeg to avoid a large memory allocation in case the
** merge-hint is corrupt*/
iAbsLevel = iHintAbsLevel;
nSeg = nHintSeg;
nSeg = MIN(MAX(nMin,nSeg), nHintSeg);
bUseHint = 1;
bDirtyHint = 1;
}else{
@@ -4908,7 +4951,7 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
/* If nSeg is less that zero, then there is no level with at least
** nMin segments and no hint in the %_stat table. No work to do.
** Exit early in this case. */
if( nSeg<0 ) break;
if( nSeg<=0 ) break;
/* Open a cursor to iterate through the contents of the oldest nSeg
** indexes of absolute level iAbsLevel. If this cursor is opened using
@@ -4936,8 +4979,15 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
}
if( SQLITE_OK==rc && pCsr->nSegment==nSeg
&& SQLITE_OK==(rc = sqlite3Fts3SegReaderStart(p, pCsr, pFilter))
&& SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pCsr))
){
int bEmpty = 0;
rc = sqlite3Fts3SegReaderStep(p, pCsr);
if( rc==SQLITE_OK ){
bEmpty = 1;
}else if( rc!=SQLITE_ROW ){
sqlite3Fts3SegReaderFinish(pCsr);
break;
}
if( bUseHint && iIdx>0 ){
const char *zKey = pCsr->zTerm;
int nKey = pCsr->nTerm;
@@ -4948,11 +4998,13 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
if( rc==SQLITE_OK && pWriter->nLeafEst ){
fts3LogMerge(nSeg, iAbsLevel);
do {
rc = fts3IncrmergeAppend(p, pWriter, pCsr);
if( rc==SQLITE_OK ) rc = sqlite3Fts3SegReaderStep(p, pCsr);
if( pWriter->nWork>=nRem && rc==SQLITE_ROW ) rc = SQLITE_OK;
}while( rc==SQLITE_ROW );
if( bEmpty==0 ){
do {
rc = fts3IncrmergeAppend(p, pWriter, pCsr);
if( rc==SQLITE_OK ) rc = sqlite3Fts3SegReaderStep(p, pCsr);
if( pWriter->nWork>=nRem && rc==SQLITE_ROW ) rc = SQLITE_OK;
}while( rc==SQLITE_ROW );
}
/* Update or delete the input segments */
if( rc==SQLITE_OK ){
@@ -5017,7 +5069,7 @@ static int fts3DoIncrmerge(
const char *zParam /* Nul-terminated string containing "A,B" */
){
int rc;
int nMin = (FTS3_MERGE_COUNT / 2);
int nMin = (MergeCount(p) / 2);
int nMerge = 0;
const char *z = zParam;
@@ -5062,7 +5114,7 @@ static int fts3DoAutoincrmerge(
int rc = SQLITE_OK;
sqlite3_stmt *pStmt = 0;
p->nAutoincrmerge = fts3Getint(&zParam);
if( p->nAutoincrmerge==1 || p->nAutoincrmerge>FTS3_MERGE_COUNT ){
if( p->nAutoincrmerge==1 || p->nAutoincrmerge>MergeCount(p) ){
p->nAutoincrmerge = 8;
}
if( !p->bHasStat ){
@@ -5145,12 +5197,12 @@ static u64 fts3ChecksumIndex(
i64 iDocid = 0;
i64 iCol = 0;
i64 iPos = 0;
u64 iPos = 0;
pCsr += sqlite3Fts3GetVarint(pCsr, &iDocid);
while( pCsr<pEnd ){
i64 iVal = 0;
pCsr += sqlite3Fts3GetVarint(pCsr, &iVal);
u64 iVal = 0;
pCsr += sqlite3Fts3GetVarintU(pCsr, &iVal);
if( pCsr<pEnd ){
if( iVal==0 || iVal==1 ){
iCol = 0;
@@ -5158,8 +5210,12 @@ static u64 fts3ChecksumIndex(
if( iVal ){
pCsr += sqlite3Fts3GetVarint(pCsr, &iCol);
}else{
pCsr += sqlite3Fts3GetVarint(pCsr, &iVal);
iDocid += iVal;
pCsr += sqlite3Fts3GetVarintU(pCsr, &iVal);
if( p->bDescIdx ){
iDocid = (i64)((u64)iDocid - iVal);
}else{
iDocid = (i64)((u64)iDocid + iVal);
}
}
}else{
iPos += (iVal - 2);
@@ -5232,10 +5288,9 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
if( p->abNotindexed[iCol]==0 ){
const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1);
int nText = sqlite3_column_bytes(pStmt, iCol+1);
sqlite3_tokenizer_cursor *pT = 0;
rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText,&pT);
rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, -1, &pT);
while( rc==SQLITE_OK ){
char const *zToken; /* Buffer containing token */
int nToken = 0; /* Number of bytes in token */
@@ -5320,7 +5375,7 @@ static int fts3DoIntegrityCheck(
** meaningful value to insert is the text 'optimize'.
*/
static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){
int rc; /* Return Code */
int rc = SQLITE_ERROR; /* Return Code */
const char *zVal = (const char *)sqlite3_value_text(pVal);
int nVal = sqlite3_value_bytes(pVal);
@@ -5336,21 +5391,27 @@ static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){
rc = fts3DoIncrmerge(p, &zVal[6]);
}else if( nVal>10 && 0==sqlite3_strnicmp(zVal, "automerge=", 10) ){
rc = fts3DoAutoincrmerge(p, &zVal[10]);
#ifdef SQLITE_TEST
}else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
p->nNodeSize = atoi(&zVal[9]);
rc = SQLITE_OK;
}else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
p->nMaxPendingData = atoi(&zVal[11]);
rc = SQLITE_OK;
}else if( nVal>21 && 0==sqlite3_strnicmp(zVal, "test-no-incr-doclist=", 21) ){
p->bNoIncrDoclist = atoi(&zVal[21]);
rc = SQLITE_OK;
#endif
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
}else{
rc = SQLITE_ERROR;
int v;
if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
v = atoi(&zVal[9]);
if( v>=24 && v<=p->nPgsz-35 ) p->nNodeSize = v;
rc = SQLITE_OK;
}else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
v = atoi(&zVal[11]);
if( v>=64 && v<=FTS3_MAX_PENDING_DATA ) p->nMaxPendingData = v;
rc = SQLITE_OK;
}else if( nVal>21 && 0==sqlite3_strnicmp(zVal,"test-no-incr-doclist=",21) ){
p->bNoIncrDoclist = atoi(&zVal[21]);
rc = SQLITE_OK;
}else if( nVal>11 && 0==sqlite3_strnicmp(zVal,"mergecount=",11) ){
v = atoi(&zVal[11]);
if( v>=4 && v<=FTS3_MERGE_COUNT && (v&1)==0 ) p->nMergeCount = v;
rc = SQLITE_OK;
}
#endif
}
return rc;
}
+34 -35
View File
@@ -1,5 +1,5 @@
C Version\s3.28.0
D 2019-04-16T19:49:53.412
C Remove\stwo\sincorrect\sassert()\sstatements\sfrom\sthe\slogic\sused\sto\sderive\ncolumn\snames\sand\stypes\sfrom\ssubqueries.\sThis\sallows\sthe\sSQL\sassociated\swith\sCVE-2020-13871\s(ticket\s[c8d3b9f0a750a529])\sto\sbe\stested.
D 2021-07-13T15:30:48.284
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -81,25 +81,25 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers b92bdeb8b46503f0dd301d364efc5ef59ef9fa8e2758b8e742f39fa93a2e422d
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
F ext/fts3/fts3.c 33958a8c05a6c22bf559fedb1176ad1f313a7b42ccf5f0c0bcc8a88609e58d60
F ext/fts3/fts3.c 52c09f459364732b5df73eff0373f991fd6af8f0f60fcdbb4b649205e88a7568
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h 74384e28b778a057f1467529715668b98f3f12f52eeb564fd6ae1e894125c00c
F ext/fts3/fts3Int.h f091030b976045e7df91af2337935952b477cdbd9f48058c44c965684484cb50
F ext/fts3/fts3_aux.c 96708c8b3a7d9b8ca1b68ea2b7e503e283f20e95f145becadedfad096dbd0f34
F ext/fts3/fts3_expr.c b132af223e90e35b9f9efa9fe63d6ae737d34153a3b6066736086df8abc78a1f
F ext/fts3/fts3_hash.c 8b6e31bfb0844c27dc6092c2620bdb1fca17ed613072db057d96952c6bdb48b7
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
F ext/fts3/fts3_icu.c 305ce7fb6036484085b5556a9c8e62acdc7763f0f4cdf5fd538212a9f3720116
F ext/fts3/fts3_porter.c 3565faf04b626cddf85f03825e86056a4562c009
F ext/fts3/fts3_snippet.c 2f3a78b990f1c8658225618c8a0fa06ab60046688d6fb627a548e8ada9011150
F ext/fts3/fts3_snippet.c 052b35ad746349ffb53820379bacdb23ff3ac60d3cc13d986e56d42822ef5a9a
F ext/fts3/fts3_term.c f45a1e7c6ef464abb1231245d123dae12266b69e05cc56e14045b76591ae92d1
F ext/fts3/fts3_test.c 73b16e229e517c1b1f0fb8e1046182a4e5dbc8dbe6eea8a5d4353fcce7dbbf39
F ext/fts3/fts3_tokenize_vtab.c 1de9a61acfa2a0445ed989310c31839c57f6b6086dd9d5c97177ae734a17fd8b
F ext/fts3/fts3_tokenizer.c 8034a5604c31559493fef0fed432cb251a566c46043c0b2c11b92c740e6f036f
F ext/fts3/fts3_tokenizer.c 6d8fc150c48238955d5182bf661498db0dd473c8a2a80e00c16994a646fa96e7
F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
F ext/fts3/fts3_unicode.c 4b9af6151c29b35ed09574937083cece7c31e911f69615e168a39677569b684d
F ext/fts3/fts3_unicode2.c 416eb7e1e81142703520d284b768ca2751d40e31fa912cae24ba74860532bf0f
F ext/fts3/fts3_write.c 1d814248a42ddecc6ebd8d9e09673228de2ff5ae1410b8b7f1b22e04b7299fdf
F ext/fts3/fts3_write.c 6f9dd5d774003ea81b8b32daa7d0819f9aaf01bf2b5f33498a69aab096094ed3
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
F ext/fts3/tool/fts3cov.sh c331d006359456cf6f8f953e37f2b9c7d568f3863f00bb5f7eb87fea4ac01b73
@@ -452,7 +452,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 25f54387121a0c5fd0f49b299f4070c81af8f26a84edaae6de679c4e4b71b1ff
F src/alter.c d8f927946f25d6a39a344e18db52d1ca492ce561e9b8c4b985fc580bc050bb93
F src/analyze.c 58db66344a5c58dcabb57f26696f6f2993956c830446da40b444051d2fdaf644
F src/attach.c 78e986baee90cb7b83fb9eafa79c22581a8ada14030fd633b0683c95cf11213c
F src/auth.c 0fac71038875693a937e506bceb492c5f136dd7b1249fbd4ae70b4e8da14f9df
@@ -462,14 +462,14 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
F src/btree.c 958939f608e351a36756e3749596472baa0e5aae54eebd14e6beffe7a68aafc7
F src/btree.h c11446f07ec0e9dc85af8041cb0855c52f5359c8b2a43e47e02a685282504d89
F src/btreeInt.h 6111c15868b90669f79081039d19e7ea8674013f907710baa3c814dc3f8bfd3f
F src/build.c 61655dad911a967a69fb49df57268fd15ce8f1af3fe0a1bd90c128ef2cacfb7a
F src/build.c 04bc5a6b6331a30348e59222ab132ecde7cf5dc04c0915a2182b0609d1ab3df0
F src/callback.c 25dda5e1c2334a367b94a64077b1d06b2553369f616261ca6783c48bcb6bda73
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 109e58d00f62e8e71ee1eb5944ac18b90171c928ab2e082e058056e1137cc20b
F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957
F src/dbpage.c 135eb3b5e74f9ef74bde5cec2571192c90c86984fa534c88bf4a055076fa19b7
F src/dbstat.c c12833de69cb655751487d2c5a59607e36be1c58ba1f4bd536609909ad47b319
F src/delete.c d08c9e01a2664afd12edcfa3a9c6578517e8ff8735f35509582693adbe0edeaf
F src/delete.c e12b572e82eb8127627f09acd5ff2b5f180d983922e2782f7c09ad455e7a547e
F src/expr.c e100212835d20498780e7c6d2bdb16c677ecc04350fb75db3bf192a86ba48c92
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c bd0138acdc008c1845ccf92f8e73787880562de649471804801c06fed814c765
@@ -482,7 +482,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c fc3cf5c371f9a400144e8c2f148ab29cd3f67f7da7eaf47e6a6959f8255fd92c
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 22afc33c3a61b4fd80a60a54f1882688371e6bc64685df2696b008fce65a999c
F src/main.c 16eea1ab004331312da0538dafb497cc0ed82fd9bb2e67f7684b40bf2797b666
F src/main.c 49657b103545c36b743d1384dbd03c26d49c69cba954a4abab320d5c1fe060b7
F src/malloc.c 0f9da2a66b230a5785af94b9672126845099b57b70a32c987d04ac28c69da990
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
@@ -513,17 +513,17 @@ F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
F src/pcache1.c be64b2f3908a7f97c56c963676eb12f0d6254c95b28cdc1d73a186eff213219d
F src/pragma.c af67dedaad8bafe9a5f9adcec32a0da6dd118617dd8220ad1d118f5a6bf83a02
F src/pragma.h a776bb9c915207e9d1117b5754743ddf1bf6a39cc092a4a44e74e6cb5fab1177
F src/prepare.c 78027c6231fbb19ca186a5f5f0c0a1375d9c2cec0655273f9bd90d9ff74a34b3
F src/prepare.c f739feb4cf0dfe22b5729c3610c80e2261c816731c7884641552e12aa9f7346d
F src/printf.c 67f79227273a9009d86a017619717c3f554f50b371294526da59faa6014ed2cd
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c 567888ee3faec14dae06519b4306201771058364a37560186a3e0e755ebc4cb8
F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
F src/select.c 9263f5c30dd44c7ac2eb29f40a7ec64322a96885b71c00de6bc30b756c2e1c49
F src/select.c a75028a3d35a4e56f7428fd716d6340f0ca6666a98cd48af246ad450c093a5b1
F src/shell.c.in c1986496062f9dba4ed5b70db06b5e0f32e1954cdcfab0b30372c6c186796810
F src/sqlite.h.in 38390767acc1914d58930e03149595ee4710afa4e3c43ab6c3a8aea3f1a6b8cd
F src/sqlite.h.in 59f5e145b8d7a915ca29c6bf4a1f00e3112c1605c9ac5c627c45060110332ba2
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 9ecc93b8493bd20c0c07d52e2ac0ed8bab9b549c7f7955b59869597b650dd8b5
F src/sqliteInt.h d229b6a5f70fe6c57d2f91f0edc60a9c4437397b4a5b59fd72fe9eb3b94d3437
F src/sqliteInt.h 59e2f279aef255764d0778ee2741b05d6978167d8115135c26dfe3170a876937
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
@@ -584,19 +584,19 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c d3615f0cbe4db5949503bf5916f3cd4fa5de855d5b4ef560f3b6dd5629423a1e
F src/treeview.c 56724725c62a0d0f408f7c257475dc33309198afee36a1d18be1bc268b09055e
F src/trigger.c bb034c08eca111e66a19cda045903a12547c1be2294b5570d794b869d9c44a73
F src/trigger.c 132009e29dc8099e2cbabc67b5608f03487e61d5dc4b1c5c98187ef703326e2c
F src/update.c 0b973357d88092140531e07ff641139c26fb4380b0b9f5ed98c5f7691b4604d1
F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4
F src/utf.c 2f0fac345c7660d5c5bd3df9e9d8d33d4c27f366bcfb09e07443064d751a0507
F src/util.c e12939405e77906d06ab0b78c5f513dcd2b7cec2fbb553877b0abfece6067141
F src/vacuum.c 72690ccb6877a88f8473a893cf9f6d7592236f3eebfebfa840b19c708acde574
F src/vdbe.c 711ef421b3bb3db3b2476067b2dc3c71ef5844d9b1a723026578f89f6da621e8
F src/vdbe.c 63db3831dfa1ddcfe1c9ed4e88561427cb78614f1883593d9abb30d715229dd6
F src/vdbe.h 712bca562eaed1c25506b9faf9680bdc75fc42e2f4a1cd518d883fa79c7a4237
F src/vdbeInt.h 2c12704db9740c8e899786ecfc7a5797a9d067563496eb1b6ed03c592d7b8d90
F src/vdbeapi.c 2ddd60f4a351f15ee98d841e346af16111ad59dfa4d25d2dd4012e9875bf7d92
F src/vdbeaux.c f873b5c2efcf8a4d6ecfc5b1a5b06fd810419198f3bd882175d371cc03801873
F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
F src/vdbemem.c 8e6889761e344babdb8a56dd1ac8911501fa648396544d1644f1cd6a87c80dc0
F src/vdbemem.c dd2ee49255c4c5450f2b0887ef44cea8faa1cd7a46501b39a1a82b113ae418e3
F src/vdbesort.c 66592d478dbb46f19aed0b42222325eadb84deb40a90eebe25c6e7c1d8468f47
F src/vdbetrace.c 79d6dbbc479267b255a7de8080eee6e729928a0ef93ed9b0bfa5618875b48392
F src/vtab.c 4c5959e00b7a142198d178e3a822f4e05f36f2d1a3c57657373f9487154fc06b
@@ -626,7 +626,7 @@ F test/altercol.test 54374d2ba18af25bb24e23acf18a60270d4ec120b7ec0558078b59d5aa1
F test/alterlegacy.test 82022721ce0de29cedc9a7af63bc9fcc078b0ee000f8283b4b6ea9c3eab2f44b
F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9
F test/altermalloc2.test fa7b1c1139ea39b8dec407cf1feb032ca8e0076bd429574969b619175ad0174b
F test/altertab.test 6e13f13d8c30708f16187908c31dadb1bfff9e3cb2a07a7392a7a5e076f58f4a
F test/altertab.test 784e2afcff47b32cb828f8255eda9af7209fb780de9be6663d9db2343e90e966
F test/altertab2.test 5d423a2d1006085b05cc1b788863d5a860ea2da21c4f892d15e2f2a34c78348a
F test/altertab3.test 40f2ce9be675e354d3e55c72f8baf38813be975ff4dd9e6b3144493c3c5bc033
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
@@ -737,7 +737,7 @@ F test/collate9.test 3adcc799229545940df2f25308dd1ad65869145a
F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6
F test/collateB.test 1e68906951b846570f29f20102ed91d29e634854ee47454d725f2151ecac0b95
F test/colmeta.test 2c765ea61ee37bc43bbe6d6047f89004e6508eb1
F test/colname.test fb28b3687e03625425bc216edf8b186ce974aa71008e2aa1f426a7dcb75a601d
F test/colname.test 87ad5458bb8709312dac0d6755fd30e8e4ca83298d0a9ef6e5c24277a3c3390e
F test/conflict.test c7cc007e2af151516ddf38f7412fe10d473a694f55e3df437e2c7b31c2590e8d
F test/conflict2.test bb0b94cf7196c64a3cbd815c66d3ee98c2fecd9c
F test/conflict3.test a83db76a6c3503b2fa057c7bfb08c318d8a422202d8bc5b86226e078e5b49ff9
@@ -762,10 +762,11 @@ F test/corruptH.test 79801d97ec5c2f9f3c87739aa1ec2eb786f96454
F test/corruptI.test a17bbf54fdde78d43cf3cc34b0057719fd4a173a3d824285b67dc5257c064c7b
F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4
F test/corruptK.test 5b4212fe346699831c5ad559a62c54e11c0611bdde1ea8423a091f9c01aa32af
F test/corruptL.test a569f3cece872a1f21568bd5378f55ce5c365c50845a06fae65a2721cce62264
F test/corruptL.test 18e62c39f41bd2ad861ab031728503409fec16213b13c3cb60ad39fd4c0b43b5
F test/corruptM.test 04a4061b1979283851953217e411187be79e50f5e5e3ef340c3f8e564173aae1
F test/cost.test 51f4fcaae6e78ad5a57096831259ed6c760e2ac6876836e91c00030fad385b34
F test/count.test cb2e0f934c6eb33670044520748d2ecccd46259c
F test/countofview.test e3d4cd6900e4e4f074968ab24b8b87d3671cd624961bef40fd3a6b8f574343cf
F test/countofview.test e17d6e6688cf74f22783c9ec6e788c0790ee4fbbaee713affd00b1ac0bb39b86
F test/coveridxscan.test 5ec98719a2e2914e8908dc75f7247d9b54a26df04625f846ac7900d5483f7296
F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f
F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651
@@ -787,7 +788,7 @@ F test/dataversion1.test 6e5e86ac681f0782e766ebcb56c019ae001522d114e0e111e5ebf68
F test/date.test 9b73bbeb1b82d9c1f44dec5cf563bf7da58d2373
F test/date2.test 74c234bece1b016e94dd4ef9c8cc7a199a8806c0e2291cab7ba64bace6350b10
F test/dbfuzz.c 73047c920d6210e5912c87cdffd9a1c281d4252e
F test/dbfuzz001.test e32d14465f1c77712896fda6a1ccc0f037b481c191c1696a9c44f6c9e4964faf
F test/dbfuzz001.test 42aad1dcef6219fbee86a9b7d08832c9bbb2e41508f6f128ae91745927276292
F test/dbfuzz2-seed1.db e6225c6f3d7b63f9c5b6867146a5f329d997ab105bee64644dc2b3a2f2aebaee
F test/dbfuzz2.c 6c355cf70c4a308b1b84a11a65282bcac5b4038db77de5cfc8ad080ef371f109
F test/dbpage.test 650234ba683b9d82b899c6c51439819787e7609f17a0cc40e0080a7b6443bc38
@@ -923,7 +924,7 @@ F test/fts3conf.test c84bbaec81281c1788aa545ac6e78a6bd6cde2bdbbce2da261690e3659f
F test/fts3corrupt.test 46b9ddda7f6588fd5a5b1f4bb4fc0618dc45010e7dddb8a3a188baf3197177ae
F test/fts3corrupt2.test bf55c3fa0b0dc8ea1c0fe5543623bd27714585da6a129038fd6999fe3b0d25f3
F test/fts3corrupt3.test 0d5b69a0998b4adf868cc301fc78f3d0707745f1d984ce044c205cdb764b491f
F test/fts3corrupt4.test af68ede153cbeff7309f7da2f9d8fd12a01f7e1debb03eb748c302079ac5ae05
F test/fts3corrupt4.test 926564a11038db245539a9a158085b2b7ca157694d050937aa5cf2d46979c6e2
F test/fts3cov.test cb932743da52a1c79a1ab8983e26c8121cf02263d6ff16e1f642e6f9b8348338
F test/fts3d.test 2bd8c97bcb9975f2334147173b4872505b6a41359a4f9068960a36afe07a679f
F test/fts3defer.test f4c20e4c7153d20a98ee49ee5f3faef624fefc9a067f8d8d629db380c4d9f1de
@@ -1275,7 +1276,7 @@ F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0
F test/select7.test f659f231489349e8c5734e610803d7654207318f
F test/select8.test 8c8f5ae43894c891efc5755ed905467d1d67ad5d
F test/select9.test aebc2bb0c3bc44606125033cbcaac2c8d1f33a95
F test/selectA.test b8a590f6493cad5b0bb4dfe1709bf7dcda0b6c40bb4caf32d1e36a89eebc8fc5
F test/selectA.test 68de52409e45a3313d00b8461b48bef4fb729faf36ade9067a994eae55cc86f4
F test/selectB.test 954e4e49cf1f896d61794e440669e03a27ceea25
F test/selectC.test e25243f8ca503e06f252eb0218976d07cfeceac3
F test/selectD.test fc20452847a01775710090383cfb4423275d2f745fed61f34fbf37573ac0d214
@@ -1593,7 +1594,7 @@ F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2
F test/vacuummem.test 7b42abb3208bd82dd23a7536588396f295a314f2
F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
F test/view.test 71e1bf4c0e2e0d37c84d7db5b33cd47eb4a7662c19d93ede4112b350b186f61f
F test/view.test ee9262cee79c7f4002fd2869887d3e8eccf70d9a4e1016f847242851edb18964
F test/vtab1.test 60b4f70aafa6078d6fdfc11417af3bd216d7ef5eafce16707a6ca3dae5166d20
F test/vtab2.test 14d4ab26cee13ba6cf5c5601b158e4f57552d3b055cdd9406cf7f711e9c84082
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
@@ -1683,7 +1684,7 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
F test/window1.test 8d453bfaa3f8f0873ba16ca1270c7368f18445065a0003a1b5954ac4e95797b4
F test/window1.test 2a692388f8919bbe70676136e4c969ab8aa6af83bbd327b46cb58a7f6fb23202
F test/window2.tcl 9bfa842d8a62b0d36dc8c1b5972206393c43847433c6d75940b87fec93ce3143
F test/window2.test 8e6d2a1b9f54dfebee1cde961c8590cd87b4db45c50f44947a211e1b63c2a05e
F test/window3.tcl acea6e86a4324a210fd608d06741010ca83ded9fde438341cb978c49928faf03
@@ -1737,7 +1738,7 @@ F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/index_usage.c 9ec344d29cbeb03fdc0fce668eedfb7495792170de933adf95cf8d6904a166ad
F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
F tool/lemon.c 900a15b9efba9890d10e7959914db94c4ad5162912127f061c4328add122d6fb
F tool/lemon.c bb64133868108d318dd8ee93ed9cb2bb65d109fb4a689911e33157b342b85435
F tool/lempar.c 61af95b8fac2bfd59c09d55330e78f3f5e352d7aa80bf37404b96ef795be3fdc
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
@@ -1818,10 +1819,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P af61a2fc45a0fa1277d7453779238b77de4c298a9f60714b7dc62ddca5874f80
R 53d48b50e3fea254b204992be6aac766
T +bgcolor * #d0c0ff
T +sym-release *
T +sym-version-3.28.0 *
U drh
Z 50f60d1cc2f388d0c03013011d963653
P 9e001b635f3cff672e591204ab90deefe01baaefe64ff121bd2c32edd2d03675
Q +712e47714863a8ed7ff73324d9fec569633e8b901c436c633b0220d16a7a9302
R 483f02b37ec5a253e775cb238ab2131a
U dan
Z 5d42ba6fb517de1ce0283fb5c64c9b26
+1 -1
View File
@@ -1 +1 @@
884b4b7e502b4e991677b53971277adfaf0a04a284f8e483e2553d0f83156b50
d2e672203704aa18fdc652e9567eb29b71dae32e871f514308478a7a96025f29
+4 -5
View File
@@ -31,9 +31,8 @@
static int isAlterableTable(Parse *pParse, Table *pTab){
if( 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7)
#ifndef SQLITE_OMIT_VIRTUALTABLE
|| ( (pTab->tabFlags & TF_Shadow)
&& (pParse->db->flags & SQLITE_Defensive)
&& pParse->db->nVdbeExec==0
|| ( (pTab->tabFlags & TF_Shadow)!=0
&& sqlite3ReadOnlyShadowTables(pParse->db)
)
#endif
){
@@ -136,8 +135,8 @@ void sqlite3AlterRenameTable(
if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){
goto exit_rename_table;
}
if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto
exit_rename_table;
if( SQLITE_OK!=sqlite3CheckObjectName(pParse,zName,"table",zName) ){
goto exit_rename_table;
}
#ifndef SQLITE_OMIT_VIEW
+68 -14
View File
@@ -825,13 +825,39 @@ int sqlite3WritableSchema(sqlite3 *db){
** trigger). All names are legal except those that begin with the string
** "sqlite_" (in upper, lower or mixed case). This portion of the namespace
** is reserved for internal use.
**
** When parsing the sqlite_master table, this routine also checks to
** make sure the "type", "name", and "tbl_name" columns are consistent
** with the SQL.
*/
int sqlite3CheckObjectName(Parse *pParse, const char *zName){
if( !pParse->db->init.busy && pParse->nested==0
&& sqlite3WritableSchema(pParse->db)==0
&& 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName);
return SQLITE_ERROR;
int sqlite3CheckObjectName(
Parse *pParse, /* Parsing context */
const char *zName, /* Name of the object to check */
const char *zType, /* Type of this object */
const char *zTblName /* Parent table name for triggers and indexes */
){
sqlite3 *db = pParse->db;
if( sqlite3WritableSchema(db) || db->init.imposterTable ){
/* Skip these error checks for writable_schema=ON */
return SQLITE_OK;
}
if( db->init.busy ){
if( sqlite3_stricmp(zType, db->init.azInit[0])
|| sqlite3_stricmp(zName, db->init.azInit[1])
|| sqlite3_stricmp(zTblName, db->init.azInit[2])
){
sqlite3ErrorMsg(pParse, ""); /* corruptSchema() will supply the error */
return SQLITE_ERROR;
}
}else{
if( (pParse->nested==0 && 0==sqlite3StrNICmp(zName, "sqlite_", 7))
|| (sqlite3ReadOnlyShadowTables(db) && sqlite3ShadowTableName(db, zName))
){
sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s",
zName);
return SQLITE_ERROR;
}
}
return SQLITE_OK;
}
@@ -912,7 +938,7 @@ void sqlite3StartTable(
}
pParse->sNameToken = *pName;
if( zName==0 ) return;
if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
if( sqlite3CheckObjectName(pParse, zName, isView?"view":"table", zName) ){
goto begin_table_error;
}
if( db->init.iDb==1 ) isTemp = 1;
@@ -1914,7 +1940,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
** zName is temporarily modified while this routine is running, but is
** restored to its original value prior to this routine returning.
*/
static int isShadowTableName(sqlite3 *db, char *zName){
int sqlite3ShadowTableName(sqlite3 *db, const char *zName){
char *zTail; /* Pointer to the last "_" in zName */
Table *pTab; /* Table that zName is a shadow of */
Module *pMod; /* Module for the virtual table */
@@ -1932,8 +1958,6 @@ static int isShadowTableName(sqlite3 *db, char *zName){
if( pMod->pModule->xShadowName==0 ) return 0;
return pMod->pModule->xShadowName(zTail+1);
}
#else
# define isShadowTableName(x,y) 0
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
/*
@@ -1975,7 +1999,7 @@ void sqlite3EndTable(
p = pParse->pNewTable;
if( p==0 ) return;
if( pSelect==0 && isShadowTableName(db, p->zName) ){
if( pSelect==0 && sqlite3ShadowTableName(db, p->zName) ){
p->tabFlags |= TF_Shadow;
}
@@ -2657,6 +2681,37 @@ void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, int isView){
sqliteViewResetAll(db, iDb);
}
/*
** Return TRUE if shadow tables should be read-only in the current
** context.
*/
int sqlite3ReadOnlyShadowTables(sqlite3 *db){
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( (db->flags & SQLITE_Defensive)!=0
&& db->pVtabCtx==0
&& db->nVdbeExec==0
){
return 1;
}
#endif
return 0;
}
/*
** Return true if it is not allowed to drop the given table
*/
static int tableMayNotBeDropped(sqlite3 *db, Table *pTab){
if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
if( sqlite3StrNICmp(pTab->zName+7, "stat", 4)==0 ) return 0;
if( sqlite3StrNICmp(pTab->zName+7, "parameters", 10)==0 ) return 0;
return 1;
}
if( (pTab->tabFlags & TF_Shadow)!=0 && sqlite3ReadOnlyShadowTables(db) ){
return 1;
}
return 0;
}
/*
** This routine is called to do the work of a DROP TABLE statement.
** pName is the name of the table to be dropped.
@@ -2726,8 +2781,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
}
}
#endif
if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
&& sqlite3StrNICmp(pTab->zName, "sqlite_stat", 11)!=0 ){
if( tableMayNotBeDropped(db, pTab) ){
sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName);
goto exit_drop_table;
}
@@ -3196,7 +3250,7 @@ void sqlite3CreateIndex(
zName = sqlite3NameFromToken(db, pName);
if( zName==0 ) goto exit_create_index;
assert( pName->z!=0 );
if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName,"index",pTab->zName) ){
goto exit_create_index;
}
if( !IN_RENAME_OBJECT ){
+1 -5
View File
@@ -70,11 +70,7 @@ static int tabIsReadOnly(Parse *pParse, Table *pTab){
return sqlite3WritableSchema(db)==0 && pParse->nested==0;
}
assert( pTab->tabFlags & TF_Shadow );
return (db->flags & SQLITE_Defensive)!=0
#ifndef SQLITE_OMIT_VIRTUALTABLE
&& db->pVtabCtx==0
#endif
&& db->nVdbeExec==0;
return sqlite3ReadOnlyShadowTables(db);
}
/*
+3
View File
@@ -3110,6 +3110,9 @@ static int openDatabase(
#endif
#if defined(SQLITE_DEFAULT_DEFENSIVE)
| SQLITE_Defensive
#endif
#if defined(SQLITE_DEFAULT_LEGACY_ALTER_TABLE)
| SQLITE_LegacyAlter
#endif
;
sqlite3HashInit(&db->aCollSeq);
+28 -23
View File
@@ -64,9 +64,11 @@ int sqlite3IndexHasDuplicateRootPage(Index *pIndex){
**
** Each callback contains the following information:
**
** argv[0] = name of thing being created
** argv[1] = root page number for table or index. 0 for trigger or view.
** argv[2] = SQL text for the CREATE statement.
** argv[0] = type of object: "table", "index", "trigger", or "view".
** argv[1] = name of thing being created
** argv[2] = associated table if an index or trigger
** argv[3] = root page number for table or index. 0 for trigger or view.
** argv[4] = SQL text for the CREATE statement.
**
*/
int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
@@ -74,21 +76,21 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
sqlite3 *db = pData->db;
int iDb = pData->iDb;
assert( argc==3 );
assert( argc==5 );
UNUSED_PARAMETER2(NotUsed, argc);
assert( sqlite3_mutex_held(db->mutex) );
DbClearProperty(db, iDb, DB_Empty);
pData->nInitRow++;
if( db->mallocFailed ){
corruptSchema(pData, argv[0], 0);
corruptSchema(pData, argv[1], 0);
return 1;
}
assert( iDb>=0 && iDb<db->nDb );
if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
if( argv[1]==0 ){
corruptSchema(pData, argv[0], 0);
}else if( sqlite3_strnicmp(argv[2],"create ",7)==0 ){
if( argv[3]==0 ){
corruptSchema(pData, argv[1], 0);
}else if( sqlite3_strnicmp(argv[4],"create ",7)==0 ){
/* Call the parser to process a CREATE TABLE, INDEX or VIEW.
** But because db->init.busy is set to 1, no VDBE code is generated
** or executed. All the parser does is build the internal data
@@ -101,9 +103,10 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
assert( db->init.busy );
db->init.iDb = iDb;
db->init.newTnum = sqlite3Atoi(argv[1]);
db->init.newTnum = sqlite3Atoi(argv[3]);
db->init.orphanTrigger = 0;
TESTONLY(rcp = ) sqlite3_prepare(db, argv[2], -1, &pStmt, 0);
db->init.azInit = argv;
TESTONLY(rcp = ) sqlite3_prepare(db, argv[4], -1, &pStmt, 0);
rc = db->errCode;
assert( (rc&0xFF)==(rcp&0xFF) );
db->init.iDb = saved_iDb;
@@ -116,13 +119,13 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
if( rc==SQLITE_NOMEM ){
sqlite3OomFault(db);
}else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){
corruptSchema(pData, argv[0], sqlite3_errmsg(db));
corruptSchema(pData, argv[1], sqlite3_errmsg(db));
}
}
}
sqlite3_finalize(pStmt);
}else if( argv[0]==0 || (argv[2]!=0 && argv[2][0]!=0) ){
corruptSchema(pData, argv[0], 0);
}else if( argv[1]==0 || (argv[4]!=0 && argv[4][0]!=0) ){
corruptSchema(pData, argv[1], 0);
}else{
/* If the SQL column is blank it means this is an index that
** was created to be the PRIMARY KEY or to fulfill a UNIQUE
@@ -131,13 +134,13 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
** to do here is record the root page number for that index.
*/
Index *pIndex;
pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zDbSName);
pIndex = sqlite3FindIndex(db, argv[1], db->aDb[iDb].zDbSName);
if( pIndex==0
|| sqlite3GetInt32(argv[1],&pIndex->tnum)==0
|| sqlite3GetInt32(argv[3],&pIndex->tnum)==0
|| pIndex->tnum<2
|| sqlite3IndexHasDuplicateRootPage(pIndex)
){
corruptSchema(pData, argv[0], pIndex?"invalid rootpage":"orphan index");
corruptSchema(pData, argv[1], pIndex?"invalid rootpage":"orphan index");
}
}
return 0;
@@ -158,7 +161,7 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
int size;
#endif
Db *pDb;
char const *azArg[4];
char const *azArg[6];
int meta[5];
InitData initData;
const char *zMasterName;
@@ -177,18 +180,20 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
** table name will be inserted automatically by the parser so we can just
** use the abbreviation "x" here. The parser will also automatically tag
** the schema table as read-only. */
azArg[0] = zMasterName = SCHEMA_TABLE(iDb);
azArg[1] = "1";
azArg[2] = "CREATE TABLE x(type text,name text,tbl_name text,"
azArg[0] = "table";
azArg[1] = zMasterName = SCHEMA_TABLE(iDb);
azArg[2] = azArg[1];
azArg[3] = "1";
azArg[4] = "CREATE TABLE x(type text,name text,tbl_name text,"
"rootpage int,sql text)";
azArg[3] = 0;
azArg[5] = 0;
initData.db = db;
initData.iDb = iDb;
initData.rc = SQLITE_OK;
initData.pzErrMsg = pzErrMsg;
initData.mInitFlags = mFlags;
initData.nInitRow = 0;
sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
sqlite3InitCallback(&initData, 5, (char **)azArg, 0);
if( initData.rc ){
rc = initData.rc;
goto error_out;
@@ -314,7 +319,7 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
{
char *zSql;
zSql = sqlite3MPrintf(db,
"SELECT name, rootpage, sql FROM \"%w\".%s ORDER BY rowid",
"SELECT*FROM\"%w\".%s ORDER BY rowid",
db->aDb[iDb].zDbSName, zMasterName);
#ifndef SQLITE_OMIT_AUTHORIZATION
{
+10 -9
View File
@@ -1643,8 +1643,6 @@ static const char *columnTypeImpl(
assert( pExpr!=0 );
assert( pNC->pSrcList!=0 );
assert( pExpr->op!=TK_AGG_COLUMN ); /* This routine runes before aggregates
** are processed */
switch( pExpr->op ){
case TK_COLUMN: {
/* The expression is a column. Locate the table the column is being
@@ -1966,7 +1964,6 @@ int sqlite3ColumnsFromExprList(
pColExpr = pColExpr->pRight;
assert( pColExpr!=0 );
}
assert( pColExpr->op!=TK_AGG_COLUMN );
if( pColExpr->op==TK_COLUMN ){
/* For columns use the column name name */
int iCol = pColExpr->iColumn;
@@ -2692,9 +2689,7 @@ static int multiSelect(
selectOpName(p->op)));
rc = sqlite3Select(pParse, p, &uniondest);
testcase( rc!=SQLITE_OK );
/* Query flattening in sqlite3Select() might refill p->pOrderBy.
** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */
sqlite3ExprListDelete(db, p->pOrderBy);
assert( p->pOrderBy==0 );
pDelete = p->pPrior;
p->pPrior = pPrior;
p->pOrderBy = 0;
@@ -4010,7 +4005,7 @@ static int flattenSubquery(
** We look at every expression in the outer query and every place we see
** "a" we substitute "x*3" and every place we see "b" we substitute "y+10".
*/
if( pSub->pOrderBy ){
if( pSub->pOrderBy && (pParent->selFlags & SF_NoopOrderBy)==0 ){
/* At this point, any non-zero iOrderByCol values indicate that the
** ORDER BY column expression is identical to the iOrderByCol'th
** expression returned by SELECT statement pSub. Since these values
@@ -5481,7 +5476,9 @@ static struct SrcList_item *isSelfJoinView(
** names in the same FROM clause. */
continue;
}
if( sqlite3ExprCompare(0, pThis->pSelect->pWhere, pS1->pWhere, -1) ){
if( sqlite3ExprCompare(0, pThis->pSelect->pWhere, pS1->pWhere, -1)
|| sqlite3ExprCompare(0, pThis->pSelect->pHaving, pS1->pHaving, -1)
){
/* The view was modified by some other optimization such as
** pushDownWhereTerms() */
continue;
@@ -5506,7 +5503,8 @@ static struct SrcList_item *isSelfJoinView(
** * The subquery is a UNION ALL of two or more terms
** * The subquery does not have a LIMIT clause
** * There is no WHERE or GROUP BY or HAVING clauses on the subqueries
** * The outer query is a simple count(*)
** * The outer query is a simple count(*) with no WHERE clause or other
** extraneous syntax.
**
** Return TRUE if the optimization is undertaken.
*/
@@ -5517,6 +5515,8 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
sqlite3 *db;
if( (p->selFlags & SF_Aggregate)==0 ) return 0; /* This is an aggregate */
if( p->pEList->nExpr!=1 ) return 0; /* Single result column */
if( p->pWhere ) return 0;
if( p->pGroupBy ) return 0;
pExpr = p->pEList->a[0].pExpr;
if( pExpr->op!=TK_AGG_FUNCTION ) return 0; /* Result is an aggregate */
if( sqlite3_stricmp(pExpr->u.zToken,"count") ) return 0; /* Is count() */
@@ -5639,6 +5639,7 @@ int sqlite3Select(
sqlite3ExprListDelete(db, p->pOrderBy);
p->pOrderBy = 0;
p->selFlags &= ~SF_Distinct;
p->selFlags |= SF_NoopOrderBy;
}
sqlite3SelectPrep(pParse, p, 0);
if( pParse->nErr || db->mallocFailed ){
+2 -1
View File
@@ -4928,7 +4928,8 @@ int sqlite3_create_window_function(
** to [sqlite3_create_function()], [sqlite3_create_function16()], or
** [sqlite3_create_function_v2()].
*/
#define SQLITE_DETERMINISTIC 0x800
#define SQLITE_DETERMINISTIC 0x000000800
#define SQLITE_DIRECTONLY 0x000080000
/*
** CAPI3REF: Deprecated Functions
+9 -1
View File
@@ -1411,6 +1411,7 @@ struct sqlite3 {
unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */
unsigned imposterTable : 1; /* Building an imposter table */
unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */
char **azInit; /* "type", "name", and "tbl_name" columns */
} init;
int nVdbeActive; /* Number of VDBEs currently running */
int nVdbeRead; /* Number of active VDBEs that read or write */
@@ -2887,6 +2888,7 @@ struct Select {
#define SF_Converted 0x10000 /* By convertCompoundSelectToSubquery() */
#define SF_IncludeHidden 0x20000 /* Include hidden columns in output */
#define SF_ComplexResult 0x40000 /* Result contains subquery or function */
#define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */
/*
** The results of a SELECT can be distributed in several ways, as defined
@@ -4248,7 +4250,7 @@ Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
Expr *sqlite3ExprSkipCollate(Expr*);
int sqlite3CheckCollSeq(Parse *, CollSeq *);
int sqlite3WritableSchema(sqlite3*);
int sqlite3CheckObjectName(Parse *, const char *);
int sqlite3CheckObjectName(Parse*, const char*,const char*,const char*);
void sqlite3VdbeSetChanges(sqlite3 *, int);
int sqlite3AddInt64(i64*,i64);
int sqlite3SubInt64(i64*,i64);
@@ -4436,6 +4438,12 @@ void sqlite3AutoLoadExtensions(sqlite3*);
);
# define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
#endif
int sqlite3ReadOnlyShadowTables(sqlite3 *db);
#ifndef SQLITE_OMIT_VIRTUALTABLE
int sqlite3ShadowTableName(sqlite3 *db, const char *zName);
#else
# define sqlite3ShadowTableName(A,B) 0
#endif
int sqlite3VtabEponymousTableInit(Parse*,Module*);
void sqlite3VtabEponymousTableClear(sqlite3*,Module*);
void sqlite3VtabMakeWritable(Parse*,Table*);
+5 -1
View File
@@ -177,7 +177,11 @@ void sqlite3BeginTrigger(
/* Check that the trigger name is not reserved and that no trigger of the
** specified name exists */
zName = sqlite3NameFromToken(db, pName);
if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
if( zName==0 ){
assert( db->mallocFailed );
goto trigger_cleanup;
}
if( sqlite3CheckObjectName(pParse, zName, "trigger", pTab->zName) ){
goto trigger_cleanup;
}
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+1 -1
View File
@@ -5787,7 +5787,7 @@ case OP_ParseSchema: {
initData.pzErrMsg = &p->zErrMsg;
initData.mInitFlags = 0;
zSql = sqlite3MPrintf(db,
"SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
"SELECT*FROM\"%w\".%s WHERE %s ORDER BY rowid",
db->aDb[iDb].zDbSName, zMaster, pOp->p4.z);
if( zSql==0 ){
rc = SQLITE_NOMEM_BKPT;
+1 -1
View File
@@ -1511,7 +1511,7 @@ static int valueFromExpr(
}else if( op==TK_NULL ){
pVal = valueNew(db, pCtx);
if( pVal==0 ) goto no_mem;
sqlite3VdbeMemNumerify(pVal);
sqlite3VdbeMemSetNull(pVal);
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
else if( op==TK_BLOB ){
+24 -4
View File
@@ -542,19 +542,39 @@ ifcapable fts3 {
CREATE VIRTUAL TABLE y1 USING fts3;
}
do_catchsql_test 16.1 {
do_catchsql_test 16.10 {
INSERT INTO y1_segments VALUES(1, X'1234567890');
} {1 {table y1_segments may not be modified}}
do_catchsql_test 16.2 {
do_catchsql_test 16.20 {
DROP TABLE y1_segments;
} {1 {table y1_segments may not be dropped}}
do_catchsql_test 16.20 {
ALTER TABLE y1_segments RENAME TO abc;
} {1 {table y1_segments may not be altered}}
sqlite3_db_config db DEFENSIVE 0
do_catchsql_test 16.22 {
ALTER TABLE y1_segments RENAME TO abc;
} {0 {}}
sqlite3_db_config db DEFENSIVE 1
do_catchsql_test 16.23 {
CREATE TABLE y1_segments AS SELECT * FROM abc;
} {1 {object name reserved for internal use: y1_segments}}
do_catchsql_test 16.24 {
CREATE VIEW y1_segments AS SELECT * FROM abc;
} {1 {object name reserved for internal use: y1_segments}}
sqlite3_db_config db DEFENSIVE 0
do_catchsql_test 16.25 {
ALTER TABLE abc RENAME TO y1_segments;
} {0 {}}
sqlite3_db_config db DEFENSIVE 1
do_execsql_test 16.3 {
do_execsql_test 16.30 {
ALTER TABLE y1 RENAME TO z1;
}
do_execsql_test 16.4 {
do_execsql_test 16.40 {
SELECT * FROM z1_segments;
}
}
+6
View File
@@ -399,6 +399,12 @@ ifcapable vtab {
SELECT name FROM pragma_table_info('t2');
} {Bbb}
}
do_execsql_test colname-9.330 { -- added 2019-08-10 to invalidate
DROP TABLE IF EXISTS t1; -- a couple assert()s that were
CREATE TABLE t1(a); -- added by ticket 3b44500725
INSERT INTO t1 VALUES(17),(2),(99),(-3),(7);
SELECT (SELECT avg(a) UNION SELECT min(a) OVER()) FROM t1;
} {17}
# Issue detected by OSSFuzz on 2017-12-24 (Christmas Eve)
# caused by check-in https://sqlite.org/src/info/6b2ff26c25
+4 -3
View File
@@ -228,6 +228,7 @@ do_test 2.0 {
}]} {}
do_execsql_test 2.1 {
PRAGMA writable_schema=on;
INSERT INTO t1(b) VALUES(X'a0fee3669f9fddefc5cba913e4225d4b6ce2b04f26b87fad3ee6f9b7d90a1ea62a169bf41e5d32707a6ca5c3d05e4bde05c9d89eaaa8c50e74333d2e9fcd7dfe95528a3a016aac1102d825c5cd70cf99d8a88e0ea7f798d4334386518b7ad359beb168b93aba059a2a3bd93112d65b44c12b9904ea786b204d80531cdf0504bf9b203dbe927061974caf7b9f30cbc3397b61f802e732012a6663d41c3607d6f1c0dbcfd489adac05ca500c0b04439d894cd93a840159225ef73b627e178b9f84b3ffe66cf22a963a8368813ff7961fc47f573211ccec95e0220dcbb3bf429f4a50ba54d7a53784ac51bfef346e6ac8ae0d0e7c3175946e62ba2b');
}
@@ -378,7 +379,7 @@ do_test 4.0 {
do_catchsql_test 4.1 {
INSERT INTO t3 SELECT * FROM t2;
} {1 {database disk image is malformed}}
} {1 {malformed database schema (t1)}}
#-------------------------------------------------------------------------
@@ -632,7 +633,7 @@ do_catchsql_test 6.1 {
INSERT INTO t1(b) VALUES(1);
INSERT INTO t1(b) VALUES(2);
COMMIT;
} {1 {malformed database schema (t1b) - invalid rootpage}}
} {1 {malformed database schema (t1)}}
#-------------------------------------------------------------------------
reset_db
@@ -836,6 +837,6 @@ do_test 8.0 {
do_catchsql_test 8.1 {
INSERT INTO t3 SELECT * FROM t2;
} {1 {database disk image is malformed}}
} {1 {malformed database schema (t1)}}
finish_test
+202
View File
@@ -0,0 +1,202 @@
# 2019-08-12
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# Check to ensure that the type, name, and tbl_name fields of the
# sqlite_master table are validated and errors are reported if they
# are inconsistent with the sql.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix corruptM
# These tests deal with corrupt database files
#
database_may_be_corrupt
db close
forcedelete test.db
sqlite3 db test.db
do_execsql_test corruptM-100 {
CREATE TABLE t1(a,b,c);
INSERT INTO t1 VALUES(111,222,333);
CREATE INDEX i1 ON t1(b);
CREATE VIEW v2 AS SELECT 15,22;
CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN SELECT 5; END;
SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {table t1 t1 | index i1 t1 | view v2 v2 | trigger r1 t1 |}
do_execsql_test corruptM-101 {
PRAGMA writable_schema=on;
UPDATE sqlite_master SET tbl_name=NULL WHERE name='t1';
SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {table t1 {} | index i1 t1 | view v2 v2 | trigger r1 t1 |}
sqlite3 db2 test.db
do_test corruptM-102 {
catchsql {
PRAGMA quick_check;
} db2
} {1 {malformed database schema (t1)}}
db2 close
do_execsql_test corruptM-110 {
UPDATE sqlite_master SET tbl_name='tx' WHERE name='t1';
SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {table t1 tx | index i1 t1 | view v2 v2 | trigger r1 t1 |}
sqlite3 db2 test.db
do_test corruptM-111 {
catchsql {
PRAGMA quick_check;
} db2
} {1 {malformed database schema (t1)}}
db2 close
do_execsql_test corruptM-112 {
UPDATE sqlite_master SET tbl_name='t1', type='tabl' WHERE name='t1';
SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {tabl t1 t1 | index i1 t1 | view v2 v2 | trigger r1 t1 |}
sqlite3 db2 test.db
do_test corruptM-113 {
catchsql {
PRAGMA quick_check;
} db2
} {1 {malformed database schema (t1)}}
db2 close
do_execsql_test corruptM-114 {
UPDATE sqlite_master SET tbl_name='t9',type='table',name='t9'WHERE name='t1';
SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {table t9 t9 | index i1 t1 | view v2 v2 | trigger r1 t1 |}
sqlite3 db2 test.db
do_test corruptM-114 {
catchsql {
PRAGMA quick_check;
} db2
} {1 {malformed database schema (t9)}}
db2 close
do_execsql_test corruptM-120 {
UPDATE sqlite_master SET name='t1',tbl_name='T1' WHERE name='t9';
SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {table t1 T1 | index i1 t1 | view v2 v2 | trigger r1 t1 |}
sqlite3 db2 test.db
do_test corruptM-121 {
catchsql {
PRAGMA quick_check;
SELECT * FROM t1, v2;
} db2
} {0 {ok 111 222 333 15 22}}
db2 close
do_execsql_test corruptM-130 {
UPDATE sqlite_master SET type='view' WHERE name='t1';
SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {view t1 T1 | index i1 t1 | view v2 v2 | trigger r1 t1 |}
sqlite3 db2 test.db
do_test corruptM-131 {
catchsql {
PRAGMA quick_check;
SELECT * FROM t1, v2;
} db2
} {1 {malformed database schema (t1)}}
db2 close
do_execsql_test corruptM-140 {
UPDATE sqlite_master SET type='table', tbl_name='t1' WHERE name='t1';
UPDATE sqlite_master SET tbl_name='tx' WHERE name='i1';
SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {table t1 t1 | index i1 tx | view v2 v2 | trigger r1 t1 |}
sqlite3 db2 test.db
do_test corruptM-141 {
catchsql {
PRAGMA quick_check;
SELECT * FROM t1, v2;
} db2
} {1 {malformed database schema (i1)}}
db2 close
do_execsql_test corruptM-150 {
UPDATE sqlite_master SET type='table', tbl_name='t1' WHERE name='i1';
SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {table t1 t1 | table i1 t1 | view v2 v2 | trigger r1 t1 |}
sqlite3 db2 test.db
do_test corruptM-151 {
catchsql {
PRAGMA quick_check;
SELECT * FROM t1, v2;
} db2
} {1 {malformed database schema (i1)}}
db2 close
do_execsql_test corruptM-160 {
UPDATE sqlite_master SET type='view', tbl_name='t1' WHERE name='i1';
SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {table t1 t1 | view i1 t1 | view v2 v2 | trigger r1 t1 |}
sqlite3 db2 test.db
do_test corruptM-161 {
catchsql {
PRAGMA quick_check;
SELECT * FROM t1, v2;
} db2
} {1 {malformed database schema (i1)}}
db2 close
do_execsql_test corruptM-170 {
UPDATE sqlite_master SET type='index', tbl_name='t1' WHERE name='i1';
UPDATE sqlite_master SET type='table', tbl_name='v2' WHERE name='v2';
SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {table t1 t1 | index i1 t1 | table v2 v2 | trigger r1 t1 |}
sqlite3 db2 test.db
do_test corruptM-171 {
catchsql {
PRAGMA quick_check;
SELECT * FROM t1, v2;
} db2
} {1 {malformed database schema (v2)}}
db2 close
do_execsql_test corruptM-180 {
UPDATE sqlite_master SET type='view',name='v3',tbl_name='v3' WHERE name='v2';
SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {table t1 t1 | index i1 t1 | view v3 v3 | trigger r1 t1 |}
sqlite3 db2 test.db
do_test corruptM-181 {
catchsql {
PRAGMA quick_check;
SELECT * FROM t1, v2;
} db2
} {1 {malformed database schema (v3)}}
db2 close
do_execsql_test corruptM-190 {
UPDATE sqlite_master SET type='view',name='v2',tbl_name='v2' WHERE name='v3';
UPDATE sqlite_master SET type='view' WHERE name='r1';
SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {table t1 t1 | index i1 t1 | view v2 v2 | view r1 t1 |}
sqlite3 db2 test.db
do_test corruptM-191 {
catchsql {
PRAGMA quick_check;
SELECT * FROM t1, v2;
} db2
} {1 {malformed database schema (r1)}}
db2 close
do_execsql_test corruptM-192 {
UPDATE sqlite_master SET type='trigger',tbl_name='v2' WHERE name='r1';
SELECT type, name, tbl_name, '|' FROM sqlite_master;
} {table t1 t1 | index i1 t1 | view v2 v2 | trigger r1 v2 |}
sqlite3 db2 test.db
do_test corruptM-193 {
catchsql {
PRAGMA quick_check;
SELECT * FROM t1, v2;
} db2
} {1 {malformed database schema (r1)}}
db2 close
finish_test
+13
View File
@@ -40,4 +40,17 @@ do_execsql_test 1.3 {
)
} {3}
# 2019-05-15
do_execsql_test 2.0 {
CREATE TABLE t1(x);
INSERT INTO t1 VALUES(1),(99),('abc');
CREATE VIEW v1(x,y) AS SELECT x,1 FROM t1 UNION ALL SELECT x,2 FROM t1;
SELECT count(*) FROM v1 WHERE x<>1;
} {4}
do_execsql_test 2.1 {
SELECT count(*) FROM v1 GROUP BY y;
} {3 3}
finish_test
+1 -1
View File
@@ -305,7 +305,7 @@ do_test dbfuzz001-310 {
| 384: 32 28 63 2c 64 29 28 05 06 17 11 11 01 3d 74 61 2(c,d)(......=ta
| 400: 62 6c 65 74 33 74 33 07 43 52 45 41 54 45 20 54 blet3t3.CREATE T
| 416: 41 42 4c 45 20 74 33 28 63 2c 78 2c 65 2c 66 29 ABLE t3(c,x,e,f)
| 432: 28 02 06 17 11 11 01 3d 74 61 74 65 6c 03 62 74 (......=tatel.bt
| 432: 28 02 06 17 11 11 01 3d 74 61 62 6c 65 74 32 74 (......=tablet2t
| 448: 32 32 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 22CREATE TABLE t
| 464: 32 28 63 2c 64 2c 65 2c 66 29 24 01 06 17 11 11 2(c,d,e,f)$.....
| 480: 01 35 74 61 62 6c 65 74 31 74 31 02 43 52 45 41 .5tablet1t1.CREA
+10 -4
View File
@@ -1946,7 +1946,8 @@ do_test 13.0 {
do_catchsql_test 13.1 {
SELECT quote(matchinfo(t1,'pcxybs'))==0 FROM t1 WHERE b MATCH 'e*';
} {0 {0 0}}
} {0 {}}
# in 3.31.0: {0 {0 0}}
#-------------------------------------------------------------------------
reset_db
@@ -2146,6 +2147,7 @@ do_test 14.0 {
}]} {}
do_execsql_test 14.1 {
PRAGMA writable_schema=on;
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<10)
INSERT INTO t1(a) SELECT randomblob(3000) FROM c;
}
@@ -2826,7 +2828,8 @@ do_test 18.0 {
do_catchsql_test 18.1 {
SELECT quote(matchinfo(t1,'pcxybs'))==0 FROM t1 WHERE b MATCH 'e*';
} {0 0}
} {0 {}}
# in 3.31.0: {0 0}
#-------------------------------------------------------------------------
reset_db
@@ -3048,6 +3051,7 @@ do_test 19.0 {
}]} {}
do_catchsql_test 19.1 {
PRAGMA writable_schema=ON;
SELECT rowid,a,c,snippet(t1,85101090932165,-1,10) FROM t1 WHERE a MATCH 'rtree';
} {1 {database disk image is malformed}}
@@ -3249,6 +3253,7 @@ do_test 20.0 {
}]} {}
do_execsql_test 20.1 {
PRAGMA writable_schema=on;
BEGIN;
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<10)
INSERT INTO t1(a) SELECT randomblob(3000) FROM c;
@@ -3471,8 +3476,8 @@ do_test 21.0 {
| end crash-18cc014e42e828.db
}]} {}
breakpoint
do_catchsql_test 21.1 {
PRAGMA writable_schema=ON;
SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'R*';
} {1 {database disk image is malformed}}
@@ -3693,6 +3698,7 @@ do_test 22.0 {
}]} {}
do_catchsql_test 22.1 {
PRAGMA writable_schema=on;
SELECT snippet(t1,'', '', '--',-1,01)==0
FROM t1 WHERE a MATCH 'rtree OR json1rtree OR json1';
} {0 {0 0 0 0 0 0 0}}
@@ -3912,8 +3918,8 @@ do_test 23.0 {
}]} {}
do_catchsql_test 23.1 {
PRAGMA writable_schema=on;
SELECT 'FyzLy'FROM t1 WHERE t1 MATCH 'j';
} {1 {database disk image is malformed}}
finish_test
+21
View File
@@ -1446,5 +1446,26 @@ do_execsql_test 6.1 {
SELECT * FROM (SELECT a FROM t1 UNION SELECT b FROM t2) WHERE a=a;
} {12345}
# 2020-06-15 ticket 8f157e8010b22af0
#
reset_db
do_execsql_test 7.1 {
CREATE TABLE t1(c1); INSERT INTO t1 VALUES(12),(123),(1234),(NULL),('abc');
CREATE TABLE t2(c2); INSERT INTO t2 VALUES(44),(55),(123);
CREATE TABLE t3(c3,c4); INSERT INTO t3 VALUES(66,1),(123,2),(77,3);
CREATE VIEW t4 AS SELECT c3 FROM t3;
CREATE VIEW t5 AS SELECT c3 FROM t3 ORDER BY c4;
}
do_execsql_test 7.2 {
SELECT * FROM t1, t2 WHERE c1=(SELECT 123 INTERSECT SELECT c2 FROM t4) AND c1=123;
} {123 123}
do_execsql_test 7.3 {
SELECT * FROM t1, t2 WHERE c1=(SELECT 123 INTERSECT SELECT c2 FROM t5) AND c1=123;
} {123 123}
do_execsql_test 7.4 {
CREATE TABLE a(b);
CREATE VIEW c(d) AS SELECT b FROM a ORDER BY b;
SELECT sum(d) OVER( PARTITION BY(SELECT 0 FROM c JOIN a WHERE b =(SELECT b INTERSECT SELECT d FROM c) AND b = 123)) FROM c;
} {}
finish_test
+15
View File
@@ -701,4 +701,19 @@ do_test view-25.2 {
set log
} $res
#-------------------------------------------------------------------------
do_execsql_test view-26.0 {
CREATE TABLE t16(a, b, c UNIQUE);
INSERT INTO t16 VALUES(1, 1, 1);
INSERT INTO t16 VALUES(2, 2, 2);
INSERT INTO t16 VALUES(3, 3, 3);
CREATE VIEW v16 AS SELECT max(a) AS mx, min(b) AS mn FROM t16 GROUP BY c;
SELECT * FROM v16 AS one, v16 AS two WHERE one.mx=1;
} {
1 1 1 1
1 1 2 2
1 1 3 3
}
finish_test
+15 -2
View File
@@ -1167,6 +1167,19 @@ do_execsql_test 29.2 {
11 K cc 'xyz' K |
}
#-------------------------------------------------------------------------
# Test that the SQL in ticket [c8d3b9f0a75] - CVE-2020-13871 - does not
# cause a problem for this version.
#
reset_db
do_execsql_test 30.0 {
CREATE TABLE a(b);
}
do_execsql_test 30.1 {
SELECT(SELECT b FROM a GROUP BY b HAVING(NULL AND b IN((SELECT COUNT() OVER(ORDER BY b) = lead(b) OVER(ORDER BY 3.100000 * SUM(DISTINCT CASE WHEN b LIKE 'SM PACK' THEN b * b ELSE 0 END) / b))))) FROM a EXCEPT SELECT b FROM a ORDER BY b, b, b;
}
finish_test
+1 -1
View File
@@ -48,6 +48,7 @@ extern int access(const char *path, int mode);
#define MAXRHS 1000
#endif
extern void memory_error();
static int showPrecedenceConflict = 0;
static char *msort(char*,char**,int(*)(const char*,const char*));
@@ -4919,7 +4920,6 @@ char *SetNew(void){
char *s;
s = (char*)calloc( size, 1);
if( s==0 ){
extern void memory_error();
memory_error();
}
return s;