From cc12b9c512451199cacf89a999977886ba4f183e Mon Sep 17 00:00:00 2001 From: openEuler Buildteam Date: Tue, 31 Dec 2019 21:45:30 -0500 Subject: [PATCH] backport-fix-CVE-2019-9937 --- ext/fts5/fts5Int.h | 3 ++- ext/fts5/fts5_hash.c | 55 ++++++++++++++++++++++++++++++++--------------- ext/fts5/fts5_index.c | 25 ++++++++++++++------- ext/fts5/test/fts5aa.test | 21 +++++++++++++++++- 4 files changed, 77 insertions(+), 27 deletions(-) diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h index 1f8a297..984d625 100644 --- a/ext/fts5/fts5Int.h +++ b/ext/fts5/fts5Int.h @@ -565,8 +565,9 @@ void sqlite3Fts5HashClear(Fts5Hash*); int sqlite3Fts5HashQuery( Fts5Hash*, /* Hash table to query */ + int nPre, const char *pTerm, int nTerm, /* Query term */ - const u8 **ppDoclist, /* OUT: Pointer to doclist for pTerm */ + void **ppObj, /* OUT: Pointer to doclist for pTerm */ int *pnDoclist /* OUT: Size of doclist in bytes */ ); diff --git a/ext/fts5/fts5_hash.c b/ext/fts5/fts5_hash.c index c35b5d5..eae785a 100644 --- a/ext/fts5/fts5_hash.c +++ b/ext/fts5/fts5_hash.c @@ -187,19 +187,25 @@ static int fts5HashResize(Fts5Hash *pHash){ return SQLITE_OK; } -static void fts5HashAddPoslistSize(Fts5Hash *pHash, Fts5HashEntry *p){ +static int fts5HashAddPoslistSize( + Fts5Hash *pHash, + Fts5HashEntry *p, + Fts5HashEntry *p2 +){ + int nRet = 0; if( p->iSzPoslist ){ - u8 *pPtr = (u8*)p; + u8 *pPtr = p2 ? (u8*)p2 : (u8*)p; + int nData = p->nData; if( pHash->eDetail==FTS5_DETAIL_NONE ){ - assert( p->nData==p->iSzPoslist ); + assert( nData==p->iSzPoslist ); if( p->bDel ){ - pPtr[p->nData++] = 0x00; + pPtr[nData++] = 0x00; if( p->bContent ){ - pPtr[p->nData++] = 0x00; + pPtr[nData++] = 0x00; } } }else{ - int nSz = (p->nData - p->iSzPoslist - 1); /* Size in bytes */ + int nSz = (nData - p->iSzPoslist - 1); /* Size in bytes */ int nPos = nSz*2 + p->bDel; /* Value of nPos field */ assert( p->bDel==0 || p->bDel==1 ); @@ -209,14 +215,19 @@ static void fts5HashAddPoslistSize(Fts5Hash *pHash, Fts5HashEntry *p){ int nByte = sqlite3Fts5GetVarintLen((u32)nPos); memmove(&pPtr[p->iSzPoslist + nByte], &pPtr[p->iSzPoslist + 1], nSz); sqlite3Fts5PutVarint(&pPtr[p->iSzPoslist], nPos); - p->nData += (nByte-1); + nData += (nByte-1); } } - p->iSzPoslist = 0; - p->bDel = 0; - p->bContent = 0; + nRet = nData - p->nData; + if( p2==0 ){ + p->iSzPoslist = 0; + p->bDel = 0; + p->bContent = 0; + p->nData = nData; + } } + return nRet; } /* @@ -328,7 +339,7 @@ int sqlite3Fts5HashWrite( /* If this is a new rowid, append the 4-byte size field for the previous ** entry, and the new rowid for this entry. */ if( iRowid!=p->iRowid ){ - fts5HashAddPoslistSize(pHash, p); + fts5HashAddPoslistSize(pHash, p, 0); p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iRowid - p->iRowid); p->iRowid = iRowid; bNew = 1; @@ -474,8 +485,9 @@ static int fts5HashEntrySort( */ int sqlite3Fts5HashQuery( Fts5Hash *pHash, /* Hash table to query */ + int nPre, const char *pTerm, int nTerm, /* Query term */ - const u8 **ppDoclist, /* OUT: Pointer to doclist for pTerm */ + void **ppOut, /* OUT: Pointer to new object */ int *pnDoclist /* OUT: Size of doclist in bytes */ ){ unsigned int iHash = fts5HashKey(pHash->nSlot, (const u8*)pTerm, nTerm); @@ -489,11 +501,20 @@ int sqlite3Fts5HashQuery( } if( p ){ - fts5HashAddPoslistSize(pHash, p); - *ppDoclist = (const u8*)&zKey[nTerm+1]; - *pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm + 1); + int nHashPre = sizeof(Fts5HashEntry) + nTerm + 1; + int nList = p->nData - nHashPre; + u8 *pRet = (u8*)(*ppOut = sqlite3_malloc64(nPre + nList + 10)); + if( pRet ){ + Fts5HashEntry *pFaux = (Fts5HashEntry*)&pRet[nPre-nHashPre]; + memcpy(&pRet[nPre], &((u8*)p)[nHashPre], nList); + nList += fts5HashAddPoslistSize(pHash, p, pFaux); + *pnDoclist = nList; + }else{ + *pnDoclist = 0; + return SQLITE_NOMEM; + } }else{ - *ppDoclist = 0; + *ppOut = 0; *pnDoclist = 0; } @@ -526,7 +547,7 @@ void sqlite3Fts5HashScanEntry( if( (p = pHash->pScan) ){ char *zKey = fts5EntryKey(p); int nTerm = (int)strlen(zKey); - fts5HashAddPoslistSize(pHash, p); + fts5HashAddPoslistSize(pHash, p, 0); *pzTerm = zKey; *ppDoclist = (const u8*)&zKey[nTerm+1]; *pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm + 1); diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index ddad6c8..37ef61d 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -2452,31 +2452,40 @@ static void fts5SegIterHashInit( int flags, /* Mask of FTS5INDEX_XXX flags */ Fts5SegIter *pIter /* Object to populate */ ){ - const u8 *pList = 0; int nList = 0; const u8 *z = 0; int n = 0; + Fts5Data *pLeaf = 0; assert( p->pHash ); assert( p->rc==SQLITE_OK ); if( pTerm==0 || (flags & FTS5INDEX_QUERY_SCAN) ){ + const u8 *pList = 0; + p->rc = sqlite3Fts5HashScanInit(p->pHash, (const char*)pTerm, nTerm); sqlite3Fts5HashScanEntry(p->pHash, (const char**)&z, &pList, &nList); n = (z ? (int)strlen((const char*)z) : 0); + if( pList ){ + pLeaf = fts5IdxMalloc(p, sizeof(Fts5Data)); + if( pLeaf ){ + pLeaf->p = pList; + } + } }else{ - pIter->flags |= FTS5_SEGITER_ONETERM; - sqlite3Fts5HashQuery(p->pHash, (const char*)pTerm, nTerm, &pList, &nList); + p->rc = sqlite3Fts5HashQuery(p->pHash, sizeof(Fts5Data), + (const char*)pTerm, nTerm, (void**)&pLeaf, &nList + ); + if( pLeaf ){ + pLeaf->p = (u8*)&pLeaf[1]; + } z = pTerm; n = nTerm; + pIter->flags |= FTS5_SEGITER_ONETERM; } - if( pList ){ - Fts5Data *pLeaf; + if( pLeaf ){ sqlite3Fts5BufferSet(&p->rc, &pIter->term, n, z); - pLeaf = fts5IdxMalloc(p, sizeof(Fts5Data)); - if( pLeaf==0 ) return; - pLeaf->p = (u8*)pList; pLeaf->nn = pLeaf->szLeaf = nList; pIter->pLeaf = pLeaf; pIter->iLeafOffset = fts5GetVarint(pLeaf->p, (u64*)&pIter->iRowid); diff --git a/ext/fts5/test/fts5aa.test b/ext/fts5/test/fts5aa.test index 5c9b894..b76a7f6 100644 --- a/ext/fts5/test/fts5aa.test +++ b/ext/fts5/test/fts5aa.test @@ -427,7 +427,7 @@ proc funk {} { db eval { UPDATE n1_config SET v=50 WHERE k='version' } set fd [db incrblob main n1_data block 10] fconfigure $fd -encoding binary -translation binary - puts -nonewline $fd "\x44\x45" +# puts -nonewline $fd "\x44\x45" close $fd } db func funk funk @@ -604,6 +604,25 @@ do_execsql_test 23.2 { } #------------------------------------------------------------------------- +do_execsql_test 24.0 { + CREATE VIRTUAL TABLE t12 USING fts5(x, detail=%DETAIL%); + INSERT INTO t12 VALUES('aaaa'); +} +do_execsql_test 24.1 { + BEGIN; + DELETE FROM t12 WHERE rowid=1; + SELECT * FROM t12('aaaa'); + INSERT INTO t12 VALUES('aaaa'); + END; +} +do_execsql_test 24.2 { + INSERT INTO t12(t12) VALUES('integrity-check'); +} +do_execsql_test 24.3 { + SELECT * FROM t12('aaaa'); +} {aaaa} + +#------------------------------------------------------------------------- do_execsql_test 25.0 { CREATE VIRTUAL TABLE t13 USING fts5(x, detail=%DETAIL%); } -- 1.8.3.1