mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-01 06:27:03 +03:00
Fix a problem with OOM handling in the sorter code.
FossilOrigin-Name: 59cd5229e2b5be5272cf57c7e7d09e97d16a5425
This commit is contained in:
22
manifest
22
manifest
@ -1,5 +1,5 @@
|
||||
C Add\sthe\sSQLITE_MAX_WORKER_THREADS\scompile\stime\soption.\sAnd\sthe\sSQLITE_CONFIG_WORKER_THREADS\ssqlite3_config()\sswitch.
|
||||
D 2014-03-31T19:57:34.075
|
||||
C Fix\sa\sproblem\swith\sOOM\shandling\sin\sthe\ssorter\scode.
|
||||
D 2014-04-01T10:19:02.635
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in ad0921c4b2780d01868cf69b419a4f102308d125
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -164,7 +164,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||
F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53
|
||||
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
|
||||
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
||||
F src/btree.c a59a199f21338ae1847d69f5db87c3e8ef1b1578
|
||||
F src/btree.c 0d1be67448c45eccc40114556186397eb9da7f7d
|
||||
F src/btree.h 232836cb51753f2e96aa8ce0f052c6df850f76ba
|
||||
F src/btreeInt.h 0be66063468a520e4d66b80c7a1dc26d04ee6ea4
|
||||
F src/build.c 0d50ef95aad63f4c4fc47f3fa2670d4557c45db0
|
||||
@ -222,12 +222,12 @@ F src/shell.c f48b63f8e582e7998ecefd051d697f91fb1453df
|
||||
F src/sqlite.h.in 0249af5d9d3bbeab0dc1f58e1f9fee878807732a
|
||||
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||
F src/sqliteInt.h 7f42c2792b951db22fa189bbed828a5e3b38789c
|
||||
F src/sqliteInt.h 3ed0fedb5b64ece395a2114b7c73417678f3e420
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
F src/tclsqlite.c e87c99e28a145943666b51b212dacae35fcea0bd
|
||||
F src/test1.c 2401eee14a4309a7cfe2aeb2f30ad517a1d9c299
|
||||
F src/test1.c 31596bf8a9c0629f88e514a4ec864847c8946c4e
|
||||
F src/test2.c 7355101c085304b90024f2261e056cdff13c6c35
|
||||
F src/test3.c 1c0e5d6f080b8e33c1ce8b3078e7013fdbcd560c
|
||||
F src/test4.c 9b32d22f5f150abe23c1830e2057c4037c45b3df
|
||||
@ -283,10 +283,10 @@ F src/vdbe.c 02f2de0b2f3b198438e3e64a2ceba9407bb8348b
|
||||
F src/vdbe.h 394464909ed682334aa3d5831aae0c2fe2abef94
|
||||
F src/vdbeInt.h e6d83e5bfd62fc6685ba1ed6153f7099f82de9f7
|
||||
F src/vdbeapi.c 0ed6053f947edd0b30f64ce5aeb811872a3450a4
|
||||
F src/vdbeaux.c 1153175fb57a8454e1c8cf79b59b7bf92b26779d
|
||||
F src/vdbeaux.c d8dc38965507a34b0e150c0d7fc82b02f8cf25ea
|
||||
F src/vdbeblob.c 15377abfb59251bccedd5a9c7d014a895f0c04aa
|
||||
F src/vdbemem.c 6fc77594c60f6155404f3f8d71bf36d1fdeb4447
|
||||
F src/vdbesort.c b4d6133bada297e118492420346f83cd76c6da31
|
||||
F src/vdbesort.c 35c270630fa5af14791fc6abc70024d1aeeaac0e
|
||||
F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767
|
||||
F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
|
||||
F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8
|
||||
@ -663,7 +663,7 @@ F test/lock_common.tcl 0c270b121d40959fa2f3add382200c27045b3d95
|
||||
F test/lookaside.test 93f07bac140c5bb1d49f3892d2684decafdc7af2
|
||||
F test/main.test 39c4bb8a157f57298ed1659d6df89d9f35aaf2c8
|
||||
F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
|
||||
F test/malloc.test fd368e31fe98d4779ed80442f311ed9f03bcd1f7
|
||||
F test/malloc.test 26ae08a09cc15a98d147ee63925e3a66048e71c9
|
||||
F test/malloc3.test e3b32c724b5a124b57cb0ed177f675249ad0c66a
|
||||
F test/malloc4.test 957337613002b7058a85116493a262f679f3a261
|
||||
F test/malloc5.test fafce0aa9157060445cd1a56ad50fc79d82f28c3
|
||||
@ -1160,7 +1160,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
||||
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
||||
P 18d1b402f2dbe78f1a1113bb356b710e348365ef
|
||||
R 8b3347b8372cc17a3226330524ab6da6
|
||||
P 2774710df8cd2bfaca49888c69f1b01c0ddadf9a
|
||||
R a6fe6d7d652069432584e1a691602cb5
|
||||
U dan
|
||||
Z 11cb5db8cbfdddf6047ddaf9c26850df
|
||||
Z ac080311c2ad2c3d7bf733448ffc0f03
|
||||
|
@ -1 +1 @@
|
||||
2774710df8cd2bfaca49888c69f1b01c0ddadf9a
|
||||
59cd5229e2b5be5272cf57c7e7d09e97d16a5425
|
@ -4588,7 +4588,7 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
|
||||
if( pIdxKey ){
|
||||
xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
|
||||
pIdxKey->isCorrupt = 0;
|
||||
pIdxKey->errCode = 0;
|
||||
assert( pIdxKey->default_rc==1
|
||||
|| pIdxKey->default_rc==0
|
||||
|| pIdxKey->default_rc==-1
|
||||
@ -4712,7 +4712,10 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
c = xRecordCompare(nCell, pCellKey, pIdxKey, 0);
|
||||
sqlite3_free(pCellKey);
|
||||
}
|
||||
assert( pIdxKey->isCorrupt==0 || c==0 );
|
||||
assert(
|
||||
(pIdxKey->errCode!=SQLITE_CORRUPT || c==0)
|
||||
&& (pIdxKey->errCode!=SQLITE_NOMEM || !pCur->pBtree->db->mallocFailed)
|
||||
);
|
||||
if( c<0 ){
|
||||
lwr = idx+1;
|
||||
}else if( c>0 ){
|
||||
@ -4722,7 +4725,7 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
*pRes = 0;
|
||||
rc = SQLITE_OK;
|
||||
pCur->aiIdx[pCur->iPage] = (u16)idx;
|
||||
if( pIdxKey->isCorrupt ) rc = SQLITE_CORRUPT;
|
||||
if( pIdxKey->errCode ) rc = SQLITE_CORRUPT;
|
||||
goto moveto_finish;
|
||||
}
|
||||
if( lwr>upr ) break;
|
||||
|
@ -1641,7 +1641,7 @@ struct UnpackedRecord {
|
||||
KeyInfo *pKeyInfo; /* Collation and sort-order information */
|
||||
u16 nField; /* Number of entries in apMem[] */
|
||||
i8 default_rc; /* Comparison result if keys are equal */
|
||||
u8 isCorrupt; /* Corruption detected by xRecordCompare() */
|
||||
u8 errCode; /* Error detected by xRecordCompare (CORRUPT or NOMEM) */
|
||||
Mem *aMem; /* Values */
|
||||
int r1; /* Value to return if (lhs > rhs) */
|
||||
int r2; /* Value to return if (rhs < lhs) */
|
||||
|
41
src/test1.c
41
src/test1.c
@ -2703,6 +2703,46 @@ bad_args:
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: add_test_utf16bin_collate <db ptr>
|
||||
**
|
||||
** Add a utf-16 collation sequence named "utf16bin" to the database
|
||||
** handle. This collation sequence compares arguments in the same way as the
|
||||
** built-in collation "binary".
|
||||
*/
|
||||
static int test_utf16bin_collate_func(
|
||||
void *pCtx,
|
||||
int nA, const void *zA,
|
||||
int nB, const void *zB
|
||||
){
|
||||
int nCmp = (nA>nB ? nB : nA);
|
||||
int res = memcmp(zA, zB, nCmp);
|
||||
if( res==0 ) res = nA - nB;
|
||||
return res;
|
||||
}
|
||||
static int test_utf16bin_collate(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
sqlite3 *db;
|
||||
int rc;
|
||||
|
||||
if( objc!=2 ) goto bad_args;
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
||||
|
||||
rc = sqlite3_create_collation(db, "utf16bin", SQLITE_UTF16, 0,
|
||||
test_utf16bin_collate_func
|
||||
);
|
||||
if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
|
||||
return TCL_OK;
|
||||
|
||||
bad_args:
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
** When the collation needed callback is invoked, record the name of
|
||||
** the requested collating function here. The recorded name is linked
|
||||
@ -6481,6 +6521,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "add_test_collate", test_collate, 0 },
|
||||
{ "add_test_collate_needed", test_collate_needed, 0 },
|
||||
{ "add_test_function", test_function, 0 },
|
||||
{ "add_test_utf16bin_collate", test_utf16bin_collate, 0 },
|
||||
#endif
|
||||
{ "sqlite3_test_errstr", test_errstr, 0 },
|
||||
{ "tcl_variable_type", tcl_variable_type, 0 },
|
||||
|
@ -3229,7 +3229,8 @@ static int vdbeRecordCompareDebug(
|
||||
static int vdbeCompareMemString(
|
||||
const Mem *pMem1,
|
||||
const Mem *pMem2,
|
||||
const CollSeq *pColl
|
||||
const CollSeq *pColl,
|
||||
u8 *prcErr /* If an OOM occurs, set to SQLITE_NOMEM */
|
||||
){
|
||||
if( pMem1->enc==pColl->enc ){
|
||||
/* The strings are already in the correct encoding. Call the
|
||||
@ -3252,6 +3253,7 @@ static int vdbeCompareMemString(
|
||||
rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2);
|
||||
sqlite3VdbeMemRelease(&c1);
|
||||
sqlite3VdbeMemRelease(&c2);
|
||||
if( (v1==0 || v2==0) && prcErr ) *prcErr = SQLITE_NOMEM;
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
@ -3334,7 +3336,7 @@ int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
|
||||
assert( !pColl || pColl->xCmp );
|
||||
|
||||
if( pColl ){
|
||||
return vdbeCompareMemString(pMem1, pMem2, pColl);
|
||||
return vdbeCompareMemString(pMem1, pMem2, pColl, 0);
|
||||
}
|
||||
/* If a NULL pointer was passed as the collate function, fall through
|
||||
** to the blob case and use memcmp(). */
|
||||
@ -3406,8 +3408,10 @@ static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){
|
||||
** fields that appear in both keys are equal, then pPKey2->default_rc is
|
||||
** returned.
|
||||
**
|
||||
** If database corruption is discovered, set pPKey2->isCorrupt to non-zero
|
||||
** and return 0.
|
||||
** If database corruption is discovered, set pPKey2->errCode to
|
||||
** SQLITE_CORRUPT and return 0. If an OOM error is encountered,
|
||||
** pPKey2->errCode is set to SQLITE_NOMEM and, if it is not NULL, the
|
||||
** malloc-failed flag set on database handle (pPKey2->pKeyInfo->db).
|
||||
*/
|
||||
int sqlite3VdbeRecordCompare(
|
||||
int nKey1, const void *pKey1, /* Left key */
|
||||
@ -3438,7 +3442,7 @@ int sqlite3VdbeRecordCompare(
|
||||
idx1 = getVarint32(aKey1, szHdr1);
|
||||
d1 = szHdr1;
|
||||
if( d1>(unsigned)nKey1 ){
|
||||
pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
|
||||
pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
|
||||
return 0; /* Corruption */
|
||||
}
|
||||
i = 0;
|
||||
@ -3517,14 +3521,16 @@ int sqlite3VdbeRecordCompare(
|
||||
testcase( (d1+mem1.n)==(unsigned)nKey1 );
|
||||
testcase( (d1+mem1.n+1)==(unsigned)nKey1 );
|
||||
if( (d1+mem1.n) > (unsigned)nKey1 ){
|
||||
pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
|
||||
pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
|
||||
return 0; /* Corruption */
|
||||
}else if( pKeyInfo->aColl[i] ){
|
||||
mem1.enc = pKeyInfo->enc;
|
||||
mem1.db = pKeyInfo->db;
|
||||
mem1.flags = MEM_Str;
|
||||
mem1.z = (char*)&aKey1[d1];
|
||||
rc = vdbeCompareMemString(&mem1, pRhs, pKeyInfo->aColl[i]);
|
||||
rc = vdbeCompareMemString(
|
||||
&mem1, pRhs, pKeyInfo->aColl[i], &pPKey2->errCode
|
||||
);
|
||||
}else{
|
||||
int nCmp = MIN(mem1.n, pRhs->n);
|
||||
rc = memcmp(&aKey1[d1], pRhs->z, nCmp);
|
||||
@ -3544,7 +3550,7 @@ int sqlite3VdbeRecordCompare(
|
||||
testcase( (d1+nStr)==(unsigned)nKey1 );
|
||||
testcase( (d1+nStr+1)==(unsigned)nKey1 );
|
||||
if( (d1+nStr) > (unsigned)nKey1 ){
|
||||
pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
|
||||
pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
|
||||
return 0; /* Corruption */
|
||||
}else{
|
||||
int nCmp = MIN(nStr, pRhs->n);
|
||||
@ -3564,7 +3570,7 @@ int sqlite3VdbeRecordCompare(
|
||||
if( pKeyInfo->aSortOrder[i] ){
|
||||
rc = -rc;
|
||||
}
|
||||
assert( CORRUPT_DB
|
||||
assert( CORRUPT_DB || pKeyInfo->db==0
|
||||
|| (rc<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0)
|
||||
|| (rc>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0)
|
||||
|| pKeyInfo->db->mallocFailed
|
||||
@ -3724,7 +3730,7 @@ static int vdbeRecordCompareString(
|
||||
|
||||
nStr = (serial_type-12) / 2;
|
||||
if( (szHdr + nStr) > nKey1 ){
|
||||
pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
|
||||
pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
|
||||
return 0; /* Corruption */
|
||||
}
|
||||
nCmp = MIN( pPKey2->aMem[0].n, nStr );
|
||||
|
@ -1134,6 +1134,7 @@ static void *vdbeSorterThreadMain(void *pCtx){
|
||||
goto thread_out;
|
||||
}
|
||||
pThread->pUnpacked->nField = pThread->pKeyInfo->nField;
|
||||
pThread->pUnpacked->errCode = 0;
|
||||
}
|
||||
|
||||
if( pThread->eWork==SORTER_THREAD_CONS ){
|
||||
@ -1222,6 +1223,10 @@ static void *vdbeSorterThreadMain(void *pCtx){
|
||||
|
||||
thread_out:
|
||||
pThread->bDone = 1;
|
||||
if( rc==SQLITE_OK && pThread->pUnpacked->errCode ){
|
||||
assert( pThread->pUnpacked->errCode==SQLITE_NOMEM );
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
return SQLITE_INT_TO_PTR(rc);
|
||||
}
|
||||
|
||||
@ -1267,8 +1272,6 @@ static int vdbeSorterFlushPMA(sqlite3 *db, const VdbeCursor *pCsr, int bFg){
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
int bUseFg = (bFg || i==(pSorter->nThread-1));
|
||||
|
||||
assert( pThread->pThread==0 && pThread->bDone==0 );
|
||||
pThread->eWork = SORTER_THREAD_TO_PMA;
|
||||
pThread->pList = pSorter->pRecord;
|
||||
@ -1283,7 +1286,7 @@ static int vdbeSorterFlushPMA(sqlite3 *db, const VdbeCursor *pCsr, int bFg){
|
||||
}
|
||||
|
||||
#if SQLITE_MAX_WORKER_THREADS>0
|
||||
if( bUseFg==0 ){
|
||||
if( bFg || i==(pSorter->nThread-1) ){
|
||||
/* Launch a background thread for this operation */
|
||||
void *pCtx = (void*)pThread;
|
||||
assert( pSorter->aMemory==0 || pThread->aListMemory!=0 );
|
||||
|
@ -880,6 +880,28 @@ do_malloc_test 39 -tclprep {
|
||||
db close
|
||||
}
|
||||
|
||||
reset_db
|
||||
add_test_utf16bin_collate db
|
||||
do_execsql_test 40.1 {
|
||||
CREATE TABLE t1(a);
|
||||
INSERT INTO t1 VALUES('fghij');
|
||||
INSERT INTO t1 VALUES('pqrst');
|
||||
INSERT INTO t1 VALUES('abcde');
|
||||
INSERT INTO t1 VALUES('uvwxy');
|
||||
INSERT INTO t1 VALUES('klmno');
|
||||
}
|
||||
do_execsql_test 40.2 {
|
||||
SELECT * FROM t1 ORDER BY 1 COLLATE utf16bin;
|
||||
} {abcde fghij klmno pqrst uvwxy}
|
||||
do_faultsim_test 40.3 -faults oom-trans* -body {
|
||||
execsql {
|
||||
SELECT * FROM t1 ORDER BY 1 COLLATE utf16bin;
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {abcde fghij klmno pqrst uvwxy}}
|
||||
faultsim_integrity_check
|
||||
}
|
||||
|
||||
# Ensure that no file descriptors were leaked.
|
||||
do_test malloc-99.X {
|
||||
catch {db close}
|
||||
|
Reference in New Issue
Block a user