From: dan Date: Wed, 20 May 2015 20:30:37 +0000 (+0000) Subject: Ensure that tables names are dequoted exactly once by the trigger and FK logic. Cherr... X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7b759980710dc9c24e3d455e6e88f6539e57c416;p=thirdparty%2Fsqlite.git Ensure that tables names are dequoted exactly once by the trigger and FK logic. Cherrypick of [59e92bd9521f] and [9d887b92f808]. FossilOrigin-Name: bd357739d74bfc97064e515645bce0834e586649 --- diff --git a/manifest b/manifest index 4e959360d3..a3fb5a5d80 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\sobscure\sproblem\swith\s"INSERT\sINTO\stbl(cols)\sSELECT"\sstatements\swhere\sthe\sSELECT\sis\sa\scompound\swith\san\sORDER\sBY\sand\s"cols"\sis\sa\sstrict\ssubset\sof\stbl's\scolumns.\sCherrypick\sof\s[718d5d0eab04]. -D 2015-05-20T20:27:00.289 +C Ensure\sthat\stables\snames\sare\sdequoted\sexactly\sonce\sby\sthe\strigger\sand\sFK\slogic.\sCherrypick\sof\s[59e92bd9521f]\sand\s[9d887b92f808]. +D 2015-05-20T20:30:37.354 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -178,7 +178,7 @@ F src/date.c 593c744b2623971e45affd0bde347631bdfa4625 F src/delete.c bcf8f72126cea80fc3d5bc5494cf19b3f8935aaf F src/expr.c 1686997ef7a2ccb6db0a9215761a138bd8e182a0 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb -F src/fkey.c 8545f3b36da47473e10800ea4fb0810fd4062514 +F src/fkey.c 5fadcfb51f6c8e249ab795348612e2793a59c826 F src/func.c bbb724b74ed96ca42675a7274646a71dd52bcda7 F src/global.c 1e4bd956dc2f608f87d2a929abc4a20db65f30e4 F src/hash.c d139319967164f139c8d1bb8a11b14db9c4ba3cd @@ -227,7 +227,7 @@ F src/shell.c 75bb7bd2c80bb44861598f322a417c4bafe98fd7 F src/sqlite.h.in ed9d35990c61f0388ca6405706455c4095310553 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h 10038993697680d281fa7dfb2c7219646e59fec1 +F src/sqliteInt.h 978e6e01780b5d7dd328e1247ca878e074f64f6c F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -278,7 +278,7 @@ F src/test_vfs.c f84075a388527892ff184988f43b69ce69b8083c F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/tokenize.c ae45399d6252b4d736af43bee1576ce7bff86aec -F src/trigger.c 66f3470b03b52b395e839155786966e3e037fddb +F src/trigger.c 274874731e060355be9ed25c670190775654ac25 F src/update.c ea336ce7b8b3fc5e316ba8f082e6445babf81059 F src/utf.c a0314e637768a030e6e84a957d0c4f6ba910cc05 F src/util.c 3076bdd51cdbf60a6e2e57fada745be37133c73e @@ -473,7 +473,7 @@ F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9 F test/fallocate.test 3e979af17dfa7e5e9dda5eba1a696c04fa9d47f7 F test/filectrl.test 14fa712e42c4cb791e09dfd58a6a03efb47ef13a F test/filefmt.test cb34663f126cbc2d358af552dcaf5c72769b0146 -F test/fkey1.test e1d1fa84cde579185ea01358436839703e415a5b +F test/fkey1.test de5b287f6a480b36bd51e8debcf48168e26e4ed2 F test/fkey2.test 32ca728bcb854feed72d1406ea375fe423eebff2 F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49 F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d @@ -1034,7 +1034,7 @@ F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4 F test/trigger9.test 5b0789f1c5c4600961f8e68511b825b87be53e31 F test/triggerA.test fe5597f47ee21bacb4936dc827994ed94161e332 F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe -F test/triggerC.test a68980c5955d62ee24be6f97129d824f199f9a4c +F test/triggerC.test 302d8995f5ffe63bbc15053abb3ef7a39cf5a092 F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650 F test/triggerE.test 355e9c5cbaed5cd039a60baad1fb2197caeb8e52 F test/tt3_checkpoint.c 415eccce672d681b297485fc20f44cdf0eac93af @@ -1186,8 +1186,9 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 7f3943fb01490180055312363cdd8a47642f4e9d -Q +718d5d0eab045a874107e078a857226a80ab912d -R 674066d8a74c7196d2f6ff9302d84144 +P 3cd2b7722186ad2b2a581b7f7e7782c59536e523 +Q +59e92bd9521f1e8315a9a7e7fd3d63b0c75eaf0e +Q +9d887b92f8086961e045f8acb9ee7a443796d411 +R 0c68a1a4983e75713540bb859d2c365a U dan -Z 8b40aaadaed2e2b26011aeadc2d4c018 +Z c00eee9d808bc1be37169bb3151d8ab7 diff --git a/manifest.uuid b/manifest.uuid index f1d5627772..c248e90d73 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3cd2b7722186ad2b2a581b7f7e7782c59536e523 \ No newline at end of file +bd357739d74bfc97064e515645bce0834e586649 \ No newline at end of file diff --git a/src/fkey.c b/src/fkey.c index 50c10da822..fa17a595e1 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -1158,10 +1158,10 @@ static Trigger *fkActionTrigger( ** parent table are used for the comparison. */ pEq = sqlite3PExpr(pParse, TK_EQ, sqlite3PExpr(pParse, TK_DOT, - sqlite3PExpr(pParse, TK_ID, 0, 0, &tOld), - sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol) + sqlite3ExprAlloc(db, TK_ID, &tOld, 0), + sqlite3ExprAlloc(db, TK_ID, &tToCol, 0) , 0), - sqlite3PExpr(pParse, TK_ID, 0, 0, &tFromCol) + sqlite3ExprAlloc(db, TK_ID, &tFromCol, 0) , 0); pWhere = sqlite3ExprAnd(db, pWhere, pEq); @@ -1173,12 +1173,12 @@ static Trigger *fkActionTrigger( if( pChanges ){ pEq = sqlite3PExpr(pParse, TK_IS, sqlite3PExpr(pParse, TK_DOT, - sqlite3PExpr(pParse, TK_ID, 0, 0, &tOld), - sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol), + sqlite3ExprAlloc(db, TK_ID, &tOld, 0), + sqlite3ExprAlloc(db, TK_ID, &tToCol, 0), 0), sqlite3PExpr(pParse, TK_DOT, - sqlite3PExpr(pParse, TK_ID, 0, 0, &tNew), - sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol), + sqlite3ExprAlloc(db, TK_ID, &tNew, 0), + sqlite3ExprAlloc(db, TK_ID, &tToCol, 0), 0), 0); pWhen = sqlite3ExprAnd(db, pWhen, pEq); @@ -1188,8 +1188,8 @@ static Trigger *fkActionTrigger( Expr *pNew; if( action==OE_Cascade ){ pNew = sqlite3PExpr(pParse, TK_DOT, - sqlite3PExpr(pParse, TK_ID, 0, 0, &tNew), - sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol) + sqlite3ExprAlloc(db, TK_ID, &tNew, 0), + sqlite3ExprAlloc(db, TK_ID, &tToCol, 0) , 0); }else if( action==OE_SetDflt ){ Expr *pDflt = pFKey->pFrom->aCol[iFromCol].pDflt; @@ -1236,13 +1236,12 @@ static Trigger *fkActionTrigger( pTrigger = (Trigger *)sqlite3DbMallocZero(db, sizeof(Trigger) + /* struct Trigger */ sizeof(TriggerStep) + /* Single step in trigger program */ - nFrom + 1 /* Space for pStep->target.z */ + nFrom + 1 /* Space for pStep->zTarget */ ); 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->zTarget = (char *)&pStep[1]; + memcpy((char *)pStep->zTarget, zFrom, nFrom); pStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); pStep->pExprList = sqlite3ExprListDup(db, pList, EXPRDUP_REDUCE); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 400aa49287..1b41482d8c 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2621,7 +2621,7 @@ struct Trigger { * orconf -> stores the ON CONFLICT algorithm * pSelect -> If this is an INSERT INTO ... SELECT ... statement, then * this stores a pointer to the SELECT statement. Otherwise NULL. - * target -> A token holding the quoted name of the table to insert into. + * zTarget -> Dequoted name of the table to insert into. * pExprList -> If this is an INSERT INTO ... VALUES ... statement, then * this stores values to be inserted. Otherwise NULL. * pIdList -> If this is an INSERT INTO ... () VALUES ... @@ -2629,12 +2629,12 @@ struct Trigger { * inserted into. * * (op == TK_DELETE) - * target -> A token holding the quoted name of the table to delete from. + * zTarget -> Dequoted name of the table to delete from. * pWhere -> The WHERE clause of the DELETE statement if one is specified. * Otherwise NULL. * * (op == TK_UPDATE) - * target -> A token holding the quoted name of the table to update rows of. + * zTarget -> Dequoted name of the table to update. * pWhere -> The WHERE clause of the UPDATE statement if one is specified. * Otherwise NULL. * pExprList -> A list of the columns to update and the expressions to update @@ -2646,8 +2646,8 @@ struct TriggerStep { u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */ u8 orconf; /* OE_Rollback etc. */ Trigger *pTrig; /* The trigger that this step is a part of */ - Select *pSelect; /* SELECT statment or RHS of INSERT INTO .. SELECT ... */ - Token target; /* Target table for DELETE, UPDATE, INSERT */ + Select *pSelect; /* SELECT statement or RHS of INSERT INTO SELECT ... */ + char *zTarget; /* Target table for DELETE, UPDATE, INSERT */ Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */ ExprList *pExprList; /* SET clause for UPDATE. */ IdList *pIdList; /* Column names for INSERT */ diff --git a/src/trigger.c b/src/trigger.c index 01f7b21f74..a7259d3106 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -375,12 +375,12 @@ static TriggerStep *triggerStepAllocate( ){ TriggerStep *pTriggerStep; - pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n); + pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n + 1); if( pTriggerStep ){ char *z = (char*)&pTriggerStep[1]; memcpy(z, pName->z, pName->n); - pTriggerStep->target.z = z; - pTriggerStep->target.n = pName->n; + sqlite3Dequote(z); + pTriggerStep->zTarget = z; pTriggerStep->op = op; } return pTriggerStep; @@ -666,7 +666,7 @@ Trigger *sqlite3TriggersExist( } /* -** Convert the pStep->target token into a SrcList and return a pointer +** Convert the pStep->zTarget string into a SrcList and return a pointer ** to that SrcList. ** ** This routine adds a specific database name, if needed, to the target when @@ -679,17 +679,17 @@ static SrcList *targetSrcList( Parse *pParse, /* The parsing context */ TriggerStep *pStep /* The trigger containing the target token */ ){ + sqlite3 *db = pParse->db; int iDb; /* Index of the database to use */ SrcList *pSrc; /* SrcList to be returned */ - pSrc = sqlite3SrcListAppend(pParse->db, 0, &pStep->target, 0); + pSrc = sqlite3SrcListAppend(db, 0, 0, 0); if( pSrc ){ assert( pSrc->nSrc>0 ); - assert( pSrc->a!=0 ); - iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema); + pSrc->a[pSrc->nSrc-1].zName = sqlite3DbStrDup(db, pStep->zTarget); + iDb = sqlite3SchemaToIndex(db, pStep->pTrig->pSchema); if( iDb==0 || iDb>=2 ){ - sqlite3 *db = pParse->db; - assert( iDbdb->nDb ); + assert( iDbnDb ); pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName); } } diff --git a/test/fkey1.test b/test/fkey1.test index 90a4c44409..0bd4939eb5 100644 --- a/test/fkey1.test +++ b/test/fkey1.test @@ -121,4 +121,34 @@ do_test fkey1-3.5 { sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0 } {0 0 0} +# Stress the dequoting logic. The first test is not so bad. +do_execsql_test fkey1-4.0 { + PRAGMA foreign_keys=ON; + CREATE TABLE "xx1"("xx2" TEXT PRIMARY KEY, "xx3" TEXT); + INSERT INTO "xx1"("xx2","xx3") VALUES('abc','def'); + CREATE TABLE "xx4"("xx5" TEXT REFERENCES "xx1" ON DELETE CASCADE); + INSERT INTO "xx4"("xx5") VALUES('abc'); + INSERT INTO "xx1"("xx2","xx3") VALUES('uvw','xyz'); + SELECT 1, "xx5" FROM "xx4"; + DELETE FROM "xx1"; + SELECT 2, "xx5" FROM "xx4"; +} {1 abc} + +# This case is identical to the previous except the "xx" in each name +# is changed to a single escaped double-quote character. +do_execsql_test fkey1-4.1 { + PRAGMA foreign_keys=ON; + CREATE TABLE """1"("""2" TEXT PRIMARY KEY, """3" TEXT); + INSERT INTO """1"("""2","""3") VALUES('abc','def'); + CREATE TABLE """4"("""5" TEXT REFERENCES """1" ON DELETE CASCADE); + INSERT INTO """4"("""5") VALUES('abc'); + INSERT INTO """1"("""2","""3") VALUES('uvw','xyz'); + SELECT 1, """5" FROM """4"; + DELETE FROM """1"; + SELECT 2, """5" FROM """4"; +} {1 abc} +do_execsql_test fkey1-4.2 { + PRAGMA table_info="""1"; +} {0 {"2} TEXT 0 {} 1 1 {"3} TEXT 0 {} 0} + finish_test diff --git a/test/triggerC.test b/test/triggerC.test index 14cc0f01dd..3e47521fd1 100644 --- a/test/triggerC.test +++ b/test/triggerC.test @@ -12,6 +12,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +set testprefix triggerC ifcapable {!trigger} { finish_test return @@ -993,4 +994,52 @@ reset_db optimization_control db factor-constants 0 do_execsql_test triggerC-14.2 $SQL {1 2 3} +#------------------------------------------------------------------------- +# Check that table names used by trigger programs are dequoted exactly +# once. +# +do_execsql_test 15.1.1 { + PRAGMA recursive_triggers = 1; + CREATE TABLE node( + id int not null primary key, + pid int not null default 0 references node, + key varchar not null, + path varchar default '', + unique(pid, key) + ); + CREATE TRIGGER node_delete_referencing AFTER DELETE ON "node" + BEGIN + DELETE FROM "node" WHERE pid = old."id"; + END; +} +do_execsql_test 15.1.2 { + INSERT INTO node(id, pid, key) VALUES(9, 0, 'test'); + INSERT INTO node(id, pid, key) VALUES(90, 9, 'test1'); + INSERT INTO node(id, pid, key) VALUES(900, 90, 'test2'); + DELETE FROM node WHERE id=9; + SELECT * FROM node; +} + +do_execsql_test 15.2.1 { + CREATE TABLE x1 (x); + + CREATE TABLE x2 (a, b); + CREATE TABLE '"x2"'(a, b); + + INSERT INTO x2 VALUES(1, 2); + INSERT INTO x2 VALUES(3, 4); + INSERT INTO '"x2"' SELECT * FROM x2; + + CREATE TRIGGER x1ai AFTER INSERT ON x1 BEGIN + INSERT INTO """x2""" VALUES('x', 'y'); + DELETE FROM """x2""" WHERE a=1; + UPDATE """x2""" SET b = 11 WHERE a = 3; + END; + + INSERT INTO x1 VALUES('go!'); +} + +do_execsql_test 15.2.2 { SELECT * FROM x2; } {1 2 3 4} +do_execsql_test 15.2.3 { SELECT * FROM """x2"""; } {3 11 x y} + finish_test