]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix a stack overflow problem with INSTEAD OF triggers. (CVS 1310)
authordrh <drh@noemail.net>
Thu, 29 Apr 2004 16:16:29 +0000 (16:16 +0000)
committerdrh <drh@noemail.net>
Thu, 29 Apr 2004 16:16:29 +0000 (16:16 +0000)
FossilOrigin-Name: 5a33e0b06f495628704d0881940a792f342facc7

manifest
manifest.uuid
src/update.c
src/vdbe.c

index 7860e340d8a2ef569c021c87b59e942bfec5f0aa..3557084c25db7f88b882fb58cbd261217f40362f 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Changes\sto\slemon.c\sso\sthat\sit\scompiles\son\sOpenWatcom\s1.3.\s\sTicket\s#665.\s(CVS\s1307)
-D 2004-04-24T12:59:13
+C Fix\sa\sstack\soverflow\sproblem\swith\sINSTEAD\sOF\striggers.\s(CVS\s1310)
+D 2004-04-29T16:16:29
 F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -58,10 +58,10 @@ F src/test3.c 30985ebdfaf3ee1462a9b0652d3efbdc8d9798f5
 F src/test4.c 6e3e31acfaf21d66420fc35fda5b17dc0000cc8d
 F src/tokenize.c 6676b946fd8825b67ab52140af4fdc57a70bda48
 F src/trigger.c a9927b57c865b6f3df3fb5e40c9824d722660ded
-F src/update.c 4c50328ebc127852bde8e2950eb8933234802c21
+F src/update.c bd391079138e67d09c9af34528ca4137c29242d1
 F src/util.c 122bc174f6c8c2eb6a9127d9f13c4c74f83b85e4
 F src/vacuum.c a4e8464c9f6d60659c5343e9d62c742463227820
-F src/vdbe.c 7c33f761fdc799633468766fb53eda4301daa6b3
+F src/vdbe.c f006200348ef3feded56bef8714e052da74a885a
 F src/vdbe.h ac987945e4dd6f987bca534c6005899f089fc270
 F src/vdbeInt.h b40ff02ce39fd076e6ff3369e19c1bbfe1986682
 F src/vdbeaux.c e2cdd1ab63604a390612c73e26bdd2ef910e9438
@@ -188,7 +188,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
 F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
 F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
-P 635f674d20ca3e0b534eba54313004e859de16e9
-R 9c976d5c8583c7ac8ea10461b8760357
+P b8b8ce5c81ef614d488e0f79df8935ef609dc4f2
+R 09116ec27eaf3c7f0c80f307e42d61db
 U drh
-Z 6726be1b9326ca3188d590be44166ddf
+Z f5047c70c45fb9bcbbd3fb6ce59d57f5
index a35a050c38ae755c1bbecf8dc4f319bbe5a907b6..703299cd49eafa3f1473b86a4596854070aafef5 100644 (file)
@@ -1 +1 @@
-b8b8ce5c81ef614d488e0f79df8935ef609dc4f2
\ No newline at end of file
+5a33e0b06f495628704d0881940a792f342facc7
\ No newline at end of file
index a3d8811de3cc5ae3a1cfb7710f5c622637d2bc74..d1dc790b2a3ecc755f5d719edb1c42c7758df927 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle UPDATE statements.
 **
-** $Id: update.c,v 1.70 2004/02/22 20:05:02 drh Exp $
+** $Id: update.c,v 1.70.2.1 2004/04/29 16:16:29 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -32,7 +32,8 @@ void sqliteUpdate(
 ){
   int i, j;              /* Loop counters */
   Table *pTab;           /* The table to be updated */
-  int addr;              /* VDBE instruction address of the start of the loop */
+  int loopStart;         /* VDBE instruction address of the start of the loop */
+  int jumpInst;          /* Addr of VDBE instruction to jump out of loop */
   WhereInfo *pWInfo;     /* Information about the WHERE clause */
   Vdbe *v;               /* The virtual database engine */
   Index *pIdx;           /* For looping over indices */
@@ -49,6 +50,7 @@ void sqliteUpdate(
   Expr *pRecnoExpr;      /* Expression defining the new record number */
   int openAll;           /* True if all indices need to be opened */
   int isView;            /* Trying to update a view */
+  int iStackDepth;       /* Index of memory cell holding stack depth */
   AuthContext sContext;  /* The authorization context */
 
   int before_triggers;         /* True if there are any BEFORE triggers */
@@ -62,6 +64,7 @@ void sqliteUpdate(
   if( pParse->nErr || sqlite_malloc_failed ) goto update_cleanup;
   db = pParse->db;
   assert( pTabList->nSrc==1 );
+  iStackDepth = pParse->nMem++;
 
   /* Locate the table which we want to update. 
   */
@@ -248,7 +251,11 @@ void sqliteUpdate(
     /* The top of the update loop for when there are triggers.
     */
     sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
-    addr = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
+    sqliteVdbeAddOp(v, OP_StackDepth, 0, 0);
+    sqliteVdbeAddOp(v, OP_MemStore, iStackDepth, 1);
+    loopStart = sqliteVdbeAddOp(v, OP_MemLoad, iStackDepth, 0);
+    sqliteVdbeAddOp(v, OP_StackReset, 0, 0);
+    jumpInst = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
     sqliteVdbeAddOp(v, OP_Dup, 0, 0);
 
     /* Open a cursor and make it point to the record that is
@@ -295,7 +302,7 @@ void sqliteUpdate(
     /* Fire the BEFORE and INSTEAD OF triggers
     */
     if( sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE, pTab, 
-          newIdx, oldIdx, onError, addr) ){
+          newIdx, oldIdx, onError, loopStart) ){
       goto update_cleanup;
     }
   }
@@ -336,10 +343,10 @@ void sqliteUpdate(
     */
     if( !row_triggers_exist ){
       sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
-      addr = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
+      jumpInst = loopStart = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
       sqliteVdbeAddOp(v, OP_Dup, 0, 0);
     }
-    sqliteVdbeAddOp(v, OP_NotExists, iCur, addr);
+    sqliteVdbeAddOp(v, OP_NotExists, iCur, loopStart);
 
     /* If the record number will change, push the record number as it
     ** will be after the update. (The old record number is currently
@@ -368,7 +375,7 @@ void sqliteUpdate(
     /* Do constraint checks
     */
     sqliteGenerateConstraintChecks(pParse, pTab, iCur, aIdxUsed, chngRecno, 1,
-                                   onError, addr);
+                                   onError, loopStart);
 
     /* Delete the old indices for the current record.
     */
@@ -404,7 +411,7 @@ void sqliteUpdate(
       pParse->nTab = iCur;
     }
     if( sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER, pTab, 
-          newIdx, oldIdx, onError, addr) ){
+          newIdx, oldIdx, onError, loopStart) ){
       goto update_cleanup;
     }
   }
@@ -412,8 +419,8 @@ void sqliteUpdate(
   /* Repeat the above with the next record to be updated, until
   ** all record selected by the WHERE clause have been updated.
   */
-  sqliteVdbeAddOp(v, OP_Goto, 0, addr);
-  sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
+  sqliteVdbeAddOp(v, OP_Goto, 0, loopStart);
+  sqliteVdbeChangeP2(v, jumpInst, sqliteVdbeCurrentAddr(v));
   sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
 
   /* Close all tables if there were no FOR EACH ROW triggers */
index 0d3fb43e6f86f5e0cff4d4817f2381ded8a6fff0..ce71f8d0b2a2d5152611cd14f829770e7533a080 100644 (file)
@@ -43,7 +43,7 @@
 ** in this file for details.  If in doubt, do not deviate from existing
 ** commenting and indentation practices when changing or adding code.
 **
-** $Id: vdbe.c,v 1.268 2004/03/03 01:51:25 drh Exp $
+** $Id: vdbe.c,v 1.268.2.1 2004/04/29 16:16:30 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -4723,6 +4723,36 @@ case OP_Vacuum: {
   break;
 }
 
+/* Opcode: StackDepth * * *
+**
+** Push an integer onto the stack which is the depth of the stack prior
+** to that integer being pushed.
+*/
+case OP_StackDepth: {
+  int depth = (&pTos[1]) - p->aStack;
+  pTos++;
+  pTos->i = depth;
+  pTos->flags = MEM_Int;
+  break;
+}
+
+/* Opcode: StackReset * * *
+**
+** Pop a single integer off of the stack.  Then pop the stack
+** as many times as necessary to get the depth of the stack down
+** to the value of the integer that was popped.
+*/
+case OP_StackReset: {
+  int depth, goal;
+  assert( pTos>=p->aStack );
+  Integerify(pTos);
+  goal = pTos->i;
+  depth = (&pTos[1]) - p->aStack;
+  assert( goal<depth );
+  popStack(&pTos, depth-goal);
+  break;
+}
+
 /* An other opcode is illegal...
 */
 default: {