From 4e0e4d7a9e9f5d7c72359712a920fbfdeaee14c2 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 29 Apr 2004 16:16:29 +0000 Subject: [PATCH] Fix a stack overflow problem with INSTEAD OF triggers. (CVS 1310) FossilOrigin-Name: 5a33e0b06f495628704d0881940a792f342facc7 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/update.c | 27 +++++++++++++++++---------- src/vdbe.c | 32 +++++++++++++++++++++++++++++++- 4 files changed, 56 insertions(+), 19 deletions(-) diff --git a/manifest b/manifest index 7860e340d8..3557084c25 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index a35a050c38..703299cd49 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b8b8ce5c81ef614d488e0f79df8935ef609dc4f2 \ No newline at end of file +5a33e0b06f495628704d0881940a792f342facc7 \ No newline at end of file diff --git a/src/update.c b/src/update.c index a3d8811de3..d1dc790b2a 100644 --- a/src/update.c +++ b/src/update.c @@ -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 */ diff --git a/src/vdbe.c b/src/vdbe.c index 0d3fb43e6f..ce71f8d0b2 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -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