mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-24 22:22:08 +03:00
Fix an OOM related crash in fkey.c.
FossilOrigin-Name: 635d6a775a3f192d4292738905f5e01bc956a712
This commit is contained in:
17
manifest
17
manifest
@ -1,5 +1,5 @@
|
||||
C Allow\sspecific\sexclusion\sof\slocaltime_s()\susage\son\sWindows.
|
||||
D 2009-09-22T13:25:00
|
||||
C Fix\san\sOOM\srelated\scrash\sin\sfkey.c.
|
||||
D 2009-09-22T15:53:48
|
||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||
F Makefile.in 4ca3f1dd6efa2075bcb27f4dc43eef749877740d
|
||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||
@ -116,7 +116,7 @@ F src/date.c 657ff12ca0f1195b531561afacbb38b772d16638
|
||||
F src/delete.c 15499f5d10047d38e68ce991b3f88cbddb6e0931
|
||||
F src/expr.c 638b599adad562d41c3bf90f542f9419664aa7b8
|
||||
F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff
|
||||
F src/fkey.c 6aad270ae5ed7b0496e25020bce89097c2cf9c79
|
||||
F src/fkey.c 2c20574e7cfed8f01d944009c5f035c0bd25bbf0
|
||||
F src/func.c e536218d193b8d326aab91120bc4c6f28aa2b606
|
||||
F src/global.c 271952d199a8cc59d4ce840b3bbbfd2f30c8ba32
|
||||
F src/hash.c ebcaa921ffd9d86f7ea5ae16a0a29d1c871130a7
|
||||
@ -330,7 +330,8 @@ F test/expr.test 80f3cf99f786ffbac19d2b0083673e7fc797030f
|
||||
F test/filectrl.test 8923a6dc7630f31c8a9dd3d3d740aa0922df7bf8
|
||||
F test/filefmt.test 84e3d0fe9f12d0d2ac852465c6f8450aea0d6f43
|
||||
F test/fkey1.test 01c7de578e11747e720c2d9aeef27f239853c4da
|
||||
F test/fkey2.test a8055d90eec17db00847cbcd527bc870d9218551
|
||||
F test/fkey2.test 968812cf06dc4d41ff44d7f73c3a7de64c4d7b36
|
||||
F test/fkey_malloc.test 9926c3b4fd5f7edeb2025359d35452e733a2fbba
|
||||
F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb
|
||||
F test/fts1a.test 46090311f85da51bb33bd5ce84f7948359c6d8d7
|
||||
F test/fts1b.test 5d8a01aefbecc8b7442b36c94c05eb7a845462d5
|
||||
@ -752,7 +753,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
P c447cb37d6439090eb08028d54a91d7d06043744
|
||||
R ce32ee8113b8a1ba098839e3f7d1953e
|
||||
U shane
|
||||
Z 02da1bc6a93c7b5ffdf3fb63ab11c5fe
|
||||
P 216bcda7d2818efda55849d5cb84aa483bc6429b
|
||||
R a5adfa0091a131eefdfdfb2dd488fa3e
|
||||
U dan
|
||||
Z 09ca6593e06ce2c3dfaca1d68f6c10bc
|
||||
|
@ -1 +1 @@
|
||||
216bcda7d2818efda55849d5cb84aa483bc6429b
|
||||
635d6a775a3f192d4292738905f5e01bc956a712
|
81
src/fkey.c
81
src/fkey.c
@ -622,8 +622,8 @@ static Trigger *fkActionTrigger(
|
||||
ExprList *pChanges /* Change-list for UPDATE, NULL for DELETE */
|
||||
){
|
||||
sqlite3 *db = pParse->db; /* Database handle */
|
||||
int action;
|
||||
Trigger *pTrigger;
|
||||
int action; /* One of OE_None, OE_Cascade etc. */
|
||||
Trigger *pTrigger; /* Trigger definition to return */
|
||||
|
||||
if( pChanges ){
|
||||
action = pFKey->updateConf;
|
||||
@ -637,43 +637,26 @@ static Trigger *fkActionTrigger(
|
||||
assert( OE_Cascade>OE_Restrict && OE_None<OE_Restrict );
|
||||
|
||||
if( action>OE_Restrict && !pTrigger ){
|
||||
u8 enableLookaside; /* Copy of db->lookaside.bEnabled */
|
||||
char const *zFrom; /* Name of referencing table */
|
||||
int nFrom; /* Length in bytes of zFrom */
|
||||
Index *pIdx = 0;
|
||||
int *aiCol = 0;
|
||||
TriggerStep *pStep;
|
||||
sqlite3 *dbMem = pTab->dbMem;
|
||||
Expr *pWhere = 0;
|
||||
ExprList *pList = 0;
|
||||
int i;
|
||||
Index *pIdx = 0; /* Parent key index for this FK */
|
||||
int *aiCol = 0; /* child table cols -> parent key cols */
|
||||
TriggerStep *pStep; /* First (only) step of trigger program */
|
||||
Expr *pWhere = 0; /* WHERE clause of trigger step */
|
||||
ExprList *pList = 0; /* Changes list if ON UPDATE CASCADE */
|
||||
int i; /* Iterator variable */
|
||||
|
||||
if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0;
|
||||
assert( aiCol || pFKey->nCol==1 );
|
||||
|
||||
assert( dbMem==0 || dbMem==pParse->db );
|
||||
zFrom = pFKey->pFrom->zName;
|
||||
nFrom = sqlite3Strlen30(zFrom);
|
||||
pTrigger = (Trigger *)sqlite3DbMallocZero(dbMem,
|
||||
sizeof(Trigger) + /* struct Trigger */
|
||||
sizeof(TriggerStep) + /* Single step in trigger program */
|
||||
nFrom + 1 /* Space for pStep->target.z */
|
||||
);
|
||||
if( !pTrigger ){
|
||||
pParse->db->mallocFailed = 1;
|
||||
return 0;
|
||||
}
|
||||
pStep = pTrigger->step_list = (TriggerStep *)&pTrigger[1];
|
||||
pStep->target.z = (char *)&pStep[1];
|
||||
pStep->target.n = nFrom;
|
||||
memcpy((char *)pStep->target.z, zFrom, nFrom);
|
||||
|
||||
for(i=0; i<pFKey->nCol; i++){
|
||||
Expr *pEq;
|
||||
int iFromCol; /* Idx of column in referencing table */
|
||||
Token tFromCol; /* Name of column in referencing table */
|
||||
Token tToCol; /* Name of column in referenced table */
|
||||
Token tOld = { "old", 3 }; /* Literal "old" token */
|
||||
Token tNew = { "new", 3 }; /* Literal "new" token */
|
||||
Token tFromCol; /* Name of column in referencing table */
|
||||
Token tToCol; /* Name of column in referenced table */
|
||||
int iFromCol; /* Idx of column in referencing table */
|
||||
Expr *pEq; /* tFromCol = OLD.tToCol */
|
||||
|
||||
iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
|
||||
tToCol.z = pIdx ? pTab->aCol[pIdx->aiColumn[i]].zName : "oid";
|
||||
@ -690,7 +673,7 @@ static Trigger *fkActionTrigger(
|
||||
sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol)
|
||||
, 0)
|
||||
, 0);
|
||||
pWhere = sqlite3ExprAnd(pParse->db, pWhere, pEq);
|
||||
pWhere = sqlite3ExprAnd(db, pWhere, pEq);
|
||||
|
||||
if( action!=OE_Cascade || pChanges ){
|
||||
Expr *pNew;
|
||||
@ -713,12 +696,42 @@ static Trigger *fkActionTrigger(
|
||||
sqlite3ExprListSetName(pParse, pList, &tFromCol, 0);
|
||||
}
|
||||
}
|
||||
sqlite3DbFree(pParse->db, aiCol);
|
||||
sqlite3DbFree(db, aiCol);
|
||||
|
||||
/* If pTab->dbMem==0, then the table may be part of a shared-schema.
|
||||
** Disable the lookaside buffer before allocating space for the
|
||||
** trigger definition in this case. */
|
||||
enableLookaside = db->lookaside.bEnabled;
|
||||
if( pTab->dbMem==0 ){
|
||||
db->lookaside.bEnabled = 0;
|
||||
}
|
||||
|
||||
zFrom = pFKey->pFrom->zName;
|
||||
nFrom = sqlite3Strlen30(zFrom);
|
||||
pTrigger = (Trigger *)sqlite3DbMallocZero(db,
|
||||
sizeof(Trigger) + /* struct Trigger */
|
||||
sizeof(TriggerStep) + /* Single step in trigger program */
|
||||
nFrom + 1 /* Space for pStep->target.z */
|
||||
);
|
||||
if( pTrigger ){
|
||||
pStep = pTrigger->step_list = (TriggerStep *)&pTrigger[1];
|
||||
pStep->target.z = (char *)&pStep[1];
|
||||
pStep->target.n = nFrom;
|
||||
memcpy((char *)pStep->target.z, zFrom, nFrom);
|
||||
|
||||
pStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
|
||||
pStep->pExprList = sqlite3ExprListDup(db, pList, EXPRDUP_REDUCE);
|
||||
}
|
||||
|
||||
/* Re-enable the lookaside buffer, if it was disabled earlier. */
|
||||
db->lookaside.bEnabled = enableLookaside;
|
||||
|
||||
pStep->pWhere = sqlite3ExprDup(dbMem, pWhere, EXPRDUP_REDUCE);
|
||||
pStep->pExprList = sqlite3ExprListDup(dbMem, pList, EXPRDUP_REDUCE);
|
||||
sqlite3ExprDelete(pParse->db, pWhere);
|
||||
sqlite3ExprListDelete(pParse->db, pList);
|
||||
if( db->mallocFailed==1 ){
|
||||
fkTriggerDelete(db, pTrigger);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pStep->op = (action!=OE_Cascade || pChanges) ? TK_UPDATE : TK_DELETE;
|
||||
pStep->pTrig = pTrigger;
|
||||
|
@ -44,6 +44,9 @@ ifcapable {!foreignkey||!trigger} {
|
||||
#
|
||||
# fkey2-7.*: Test using an IPK as the key in the child (referencing) table.
|
||||
#
|
||||
# fkey2-8.*: Test that enabling/disabling foreign key support while a
|
||||
# transaction is active is not possible.
|
||||
#
|
||||
# fkey2-genfkey.*: Tests that were used with the shell tool .genfkey
|
||||
# command. Recycled to test the built-in implementation.
|
||||
#
|
||||
@ -414,6 +417,7 @@ ifcapable vacuum {
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that it is possible to use an INTEGER PRIMARY KEY as the child key
|
||||
# of a foreign constraint.
|
||||
#
|
||||
drop_all_tables
|
||||
do_test fkey2-7.1 {
|
||||
execsql {
|
||||
@ -447,6 +451,32 @@ do_test fkey2-7.8 {
|
||||
catchsql { UPDATE t1 SET a = 3 }
|
||||
} {1 {foreign key constraint failed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that it is not possible to enable/disable FK support while a
|
||||
# transaction is open.
|
||||
#
|
||||
drop_all_tables
|
||||
proc fkey2-8-test {tn zSql value} {
|
||||
do_test fkey-2.8.$tn.1 [list execsql $zSql] {}
|
||||
do_test fkey-2.8.$tn.2 { execsql "PRAGMA foreign_keys" } $value
|
||||
}
|
||||
fkey2-8-test 1 { PRAGMA foreign_keys = 0 } 0
|
||||
fkey2-8-test 2 { PRAGMA foreign_keys = 1 } 1
|
||||
fkey2-8-test 3 { BEGIN } 1
|
||||
fkey2-8-test 4 { PRAGMA foreign_keys = 0 } 1
|
||||
fkey2-8-test 5 { COMMIT } 1
|
||||
fkey2-8-test 6 { PRAGMA foreign_keys = 0 } 0
|
||||
fkey2-8-test 7 { BEGIN } 0
|
||||
fkey2-8-test 8 { PRAGMA foreign_keys = 1 } 0
|
||||
fkey2-8-test 9 { COMMIT } 0
|
||||
fkey2-8-test 10 { PRAGMA foreign_keys = 1 } 1
|
||||
fkey2-8-test 11 { PRAGMA foreign_keys = off } 0
|
||||
fkey2-8-test 12 { PRAGMA foreign_keys = on } 1
|
||||
fkey2-8-test 13 { PRAGMA foreign_keys = no } 0
|
||||
fkey2-8-test 14 { PRAGMA foreign_keys = yes } 1
|
||||
fkey2-8-test 15 { PRAGMA foreign_keys = false } 0
|
||||
fkey2-8-test 16 { PRAGMA foreign_keys = true } 1
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# The following block of tests, those prefixed with "fkey2-genfkey.", are
|
||||
# the same tests that were used to test the ".genfkey" command provided
|
||||
|
36
test/fkey_malloc.test
Normal file
36
test/fkey_malloc.test
Normal file
@ -0,0 +1,36 @@
|
||||
# 2009 September 22
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
ifcapable !foreignkey||!trigger {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
source $testdir/malloc_common.tcl
|
||||
|
||||
do_malloc_test fkey_malloc-1 -sqlprep {
|
||||
PRAGMA foreign_keys = 1;
|
||||
CREATE TABLE t1(a PRIMARY KEY, b);
|
||||
CREATE TABLE t2(x REFERENCES t1 ON UPDATE CASCADE ON DELETE CASCADE);
|
||||
} -sqlbody {
|
||||
INSERT INTO t1 VALUES('aaa', 1);
|
||||
INSERT INTO t2 VALUES('aaa');
|
||||
UPDATE t1 SET a = 'bbb';
|
||||
DELETE FROM t1;
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
Reference in New Issue
Block a user