]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Ensure that tables names are dequoted exactly once by the trigger logic.
authordrh <drh@noemail.net>
Thu, 21 May 2015 02:20:47 +0000 (02:20 +0000)
committerdrh <drh@noemail.net>
Thu, 21 May 2015 02:20:47 +0000 (02:20 +0000)
Cherrypick [59e92bd9521f1e8] and [9d887b92f8086961e].

FossilOrigin-Name: 9e3f64a4f4182ad80e82edb53095ed508e8b1d13

manifest
manifest.uuid
src/fkey.c
src/sqliteInt.h
src/trigger.c
test/fkey1.test
test/triggerC.test

index ed005501cc828bba348cba63edf7b328e47b92d0..4e296415dc0bc8ed6ca4eac68cde7361558decfd 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C When\sparsing\sthe\sschema,\signore\sany\sSQL\sthat\sdoes\snot\sbegin\nwith\s"CREATE".\sCherrypick\sof\s[d3c00d61581c]\swith\sadditional\schanges.
-D 2015-05-21T02:07:56.469
+C Ensure\sthat\stables\snames\sare\sdequoted\sexactly\sonce\sby\sthe\strigger\slogic.\nCherrypick\s[59e92bd9521f1e8]\sand\s[9d887b92f8086961e].
+D 2015-05-21T02:20:47.492
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -136,7 +136,7 @@ F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4
 F src/delete.c 51d32f0a9c880663e54ce309f52e40c325d5e112
 F src/expr.c 00675123e0beec98f999aa4594d2cbe1fec33c1b
 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
-F src/fkey.c 657212460bf5cfd3ae607d12ea62092844c227b5
+F src/fkey.c 46f9dc13b4f3e8f9659d31e71cd5f76c8ae465cc
 F src/func.c e75f41c421f00762ab9da7dc8fb90af3972cf99f
 F src/global.c 4cfdca5cb0edd33c4d021baec4ede958cb2c793b
 F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
@@ -184,7 +184,7 @@ F src/select.c 44ccdcb5d2a1c48622c179b2d72167b716388581
 F src/shell.c a31c37ed0959173dce7a565359e6372c68aa0268
 F src/sqlite.h.in 6af2d92925bfed3dfd2c022fef48469762ccd435
 F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
-F src/sqliteInt.h e65429a6f19b41720561b9434b2192574a91cfa2
+F src/sqliteInt.h ce9a4d64a183a0d3500123445a905607abaeb0a1
 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
 F src/status.c 4568e72dfd36b6a5911f93457364deb072e0b03a
 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@@ -235,7 +235,7 @@ F src/test_vfstrace.c 6b28adb2a0e8ecd0f2e3581482e1f658b11b4067
 F src/test_wholenumber.c 6129adfbe7c7444f2e60cc785927f3aa74e12290
 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
 F src/tokenize.c 1e86210d3976717a19238ea7b047fac481fe8c12
-F src/trigger.c ee7e178fb9188f44b532cebd449a7c1df90fb684
+F src/trigger.c bc7f94ec7a5e0067846acb0691996812a00336ca
 F src/update.c d3076782c887c10e882996550345da9c4c9f9dea
 F src/utf.c 890c67dcfcc7a74623c95baac7535aadfe265e84
 F src/util.c 4f6cfad661b2e3454b0cdd5b1b9d39a54942d0e3
@@ -406,7 +406,7 @@ F test/expr.test 67c9fd6f8f829e239dc8b0f4a08a73c08b09196d
 F test/fallocate.test b5d34437bd7ab01d41b1464b8117aefd4d32160e
 F test/filectrl.test f0327bd804d9c7bd048fa7a151c5eab8e27df42b
 F test/filefmt.test ffa17b5aebc3eb4b1e3be1ccb5ee906ffbd97f6e
-F test/fkey1.test 01c7de578e11747e720c2d9aeef27f239853c4da
+F test/fkey1.test fcaff62ae3c4322ba39bf01ee07944b72bccc76b
 F test/fkey2.test 080969fe219b3b082b0e097ac18c6af2e5b0631f
 F test/fkey3.test 5ec899d12b13bcf1e9ef40eff7fb692fdb91392e
 F test/fkey4.test c6c8f9f9be885f95c85c7bceb26f243ad906fd49
@@ -870,7 +870,7 @@ F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4
 F test/trigger9.test 5b0789f1c5c4600961f8e68511b825b87be53e31
 F test/triggerA.test e0aaba16d3547193d36bbd82a1b0ed75e9c88d40
 F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe
-F test/triggerC.test 4d4bdaf0230c206b50d350330107ef9802bc2d4f
+F test/triggerC.test a8fad3c4c87beb69c4e73497f8bde7285af9285f
 F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650
 F test/tt3_checkpoint.c 415eccce672d681b297485fc20f44cdf0eac93af
 F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff
@@ -992,9 +992,9 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
 F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a
 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
-P 0f0694e4245083f6abb4ce104c39add45f2eb71a
-Q +2c649cdf7e058cf490597ffbddd5dc1eb5c3b346
-Q +d3c00d61581c8ba6dce5618391432d3af8d324d4
-R d9dd499bc0772f79ea4a61d9b9920aea
+P 09784f376b47b6ca539a5106dfa65d8abebe1ef2
+Q +59e92bd9521f1e8315a9a7e7fd3d63b0c75eaf0e
+Q +9d887b92f8086961e045f8acb9ee7a443796d411
+R 8b9677253ae83c017d7457a710552396
 U drh
-Z 50e7ee5eace512a88d2256e7d4efb230
+Z 94b5f3dbcf1046c08af07824e7389b9d
index 869c696efad2d9802d4cba73cec47b3cc8f6c9ca..27418eb4fe4009e05608ba43bac9dc38e6e37a64 100644 (file)
@@ -1 +1 @@
-09784f376b47b6ca539a5106dfa65d8abebe1ef2
\ No newline at end of file
+9e3f64a4f4182ad80e82edb53095ed508e8b1d13
\ No newline at end of file
index 82e4cdc47139836195ce29962d0437ee2f8fb2fb..7c4a4bbd0bdc74a629632932ce9023c2512f5a06 100644 (file)
@@ -1018,10 +1018,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);
 
@@ -1033,12 +1033,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);
@@ -1048,8 +1048,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;
@@ -1096,13 +1096,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);
index 15c3f302e2abb2cc9560cd1f64f950ddc5e5a6fc..8a8b675d495ade16cede91a2c76be61eaf7c7c71 100644 (file)
@@ -2341,7 +2341,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 ... (<column-names>) VALUES ... 
@@ -2349,12 +2349,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
@@ -2366,8 +2366,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.  VALUES clause for INSERT */
   IdList *pIdList;     /* Column names for INSERT */
index 3c4bf62a18c949e7535f2ada4faddc75c6dd9a3b..2869e87f330bcab30c687a6584c705b99f7919be 100644 (file)
@@ -373,12 +373,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;
@@ -667,7 +667,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
@@ -680,17 +680,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( iDb<pParse->db->nDb );
+      assert( iDb<db->nDb );
       pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName);
     }
   }
index e7c00d16d4b38a9fbbc22f39f4c18ac735864c68..9141979b716801350a07ce41b26217041124ae7e 100644 (file)
@@ -118,4 +118,34 @@ do_test fkey1-3.4 {
   {0 1 t5 e {} {SET DEFAULT} CASCADE NONE} \
 ]
 
+# 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
index 12a5e4ac0881c28802d4b5c0ce45137ab4786f7f..b673b6d5704874f49cb2c733398e8b4e9684d587 100644 (file)
@@ -12,6 +12,7 @@
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
+set testprefix triggerC
 ifcapable {!trigger} {
   finish_test
   return
@@ -951,4 +952,52 @@ do_catchsql_test triggerC-13.2 {
 
 
 
+#-------------------------------------------------------------------------
+# 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