diff --git a/manifest b/manifest index 9b3f6a8700..a364c55cdf 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Modify\sthe\sOP_Once\sopcode\sso\sthat\sit\sworks\scorrectly\sin\strigger\ssub-programs.\sThis\sis\sa\scandidate\sfix\sfor\s[7bbfb7d442]. -D 2011-12-09T13:24:16.480 +C Change\sthe\sVDBE\sso\sthat\sall\sregisters\sare\sinitialized\sto\s"Invalid"\sinstead\sof\nNULL\sand\sreport\serrors\son\sany\sattempted\sread\sof\san\sInvalid\sregister.\s\sThis\nwill\shelp\sprevent\sfuture\sbugs\ssimilar\sto\s[7bbfb7d442]. +D 2011-12-09T18:06:44.319 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5b4a3e12a850b021547e43daf886b25133b44c07 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -134,7 +134,7 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c a9c26822515f81ec21588cbb482ca6724be02e33 F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4 F src/delete.c 51d32f0a9c880663e54ce309f52e40c325d5e112 -F src/expr.c 672c6e5fa3ad2eae9ff2588eac2317d76fcdfaef +F src/expr.c b5920f108d6955b262f8db8e38f40f59b2bfcd7d F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 657212460bf5cfd3ae607d12ea62092844c227b5 F src/func.c 6261ce00aad9c63cd5b4219249b05683979060e9 @@ -142,7 +142,7 @@ F src/global.c 107ccaacb4b30895cf3a3a39decf417c804acfa1 F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c 8f283d6734dd837ed7531b26d7622fda70874390 +F src/insert.c ea820fe9af748075b3b6827fb6f23f25079bf1f7 F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f F src/lempar.c 0ee69fca0be54cd93939df98d2aca4ca46f44416 @@ -180,7 +180,7 @@ F src/printf.c 03104cbff6959ff45df69dc9060ba6212f60a869 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/resolve.c 365ab1c870e38596d6869e76fb544fe6e4ffc809 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 -F src/select.c e16b188449a7841e9e801a3c45c973c24e345199 +F src/select.c fd3046fb39a1de8dce269e9b5ecbf58fe7e7e480 F src/shell.c 29812a900a780eb0f835c4bc65e216272689def8 F src/sqlite.h.in 57081d8e6b53ce29541d7437c93bce6087ac53b5 F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477 @@ -235,15 +235,15 @@ F src/test_wholenumber.c 6129adfbe7c7444f2e60cc785927f3aa74e12290 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/tokenize.c c819d9f72168a035d545a5bdafe9b085b20df705 F src/trigger.c ee7e178fb9188f44b532cebd449a7c1df90fb684 -F src/update.c 25e046a8f69d5e557aabde2000487b8545509d8d +F src/update.c d3076782c887c10e882996550345da9c4c9f9dea F src/utf.c 890c67dcfcc7a74623c95baac7535aadfe265e84 F src/util.c 01238e2b0f24a14779181dbf991fe02620a80e31 F src/vacuum.c 0c0ba2242355c6048d65e2b333abe0f7c06348fa -F src/vdbe.c f49816f99b853c6cbdec950eedd4434cb2452376 +F src/vdbe.c 029add0c5197a61db588824a58570547330b9d8f F src/vdbe.h 18f581cac1f4339ec3299f3e0cc6e11aec654cdb F src/vdbeInt.h 23a9506c9ab31e7823d7257d1828d2d7843443a0 F src/vdbeapi.c 86189ebba2c49791d75eaa12929f3ce6527596bd -F src/vdbeaux.c cdd74a86c6281b4393c5f94d8f5e40e160e44e19 +F src/vdbeaux.c 71a0cd6ae14ddb2e2a6d6b97d5b54ae753272682 F src/vdbeblob.c 32f2a4899d67f69634ea4dd93e3f651936d732cb F src/vdbemem.c 2fc78b3e0fabcc1eaa23cd79dd2e30e6dcfe1e56 F src/vdbesort.c 468d43c057063e54da4f1988b38b4f46d60e7790 @@ -978,7 +978,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 3702a31e56fe02d14ce246109b318a124cad9f1a -R 212172c6a4e482305cc0a6c8ccb724d1 -U dan -Z fd67074fb89c049640d6ea2f96341088 +P 557c69055a300b4082830b5f4803091dca1c3140 d9ba023c608bce7768bc08478f9df9243f2e73ce +R c86cf051b4407cf6125edf9f0e3046a6 +U drh +Z b55d92759eb01feac738f44135c5de26 diff --git a/manifest.uuid b/manifest.uuid index ae75c08960..2ddca39cd5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -557c69055a300b4082830b5f4803091dca1c3140 \ No newline at end of file +0064bab77149768640d7758a3e271d5a1d63b256 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 195e4627d0..3c69c564b5 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1444,6 +1444,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){ int eType = 0; /* Type of RHS table. IN_INDEX_* */ int iTab = pParse->nTab++; /* Cursor of the RHS table */ int mustBeUnique = (prNotFound==0); /* True if RHS must be unique */ + Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */ assert( pX->op==TK_IN ); @@ -1454,7 +1455,6 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){ p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0); if( ALWAYS(pParse->nErr==0) && isCandidateForInOpt(p) ){ sqlite3 *db = pParse->db; /* Database connection */ - Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */ Table *pTab; /* Table . */ Expr *pExpr; /* Expression */ int iCol; /* Index of column */ @@ -1521,6 +1521,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){ sqlite3VdbeJumpHere(v, iAddr); if( prNotFound && !pTab->aCol[iCol].notNull ){ *prNotFound = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound); } } } @@ -1536,6 +1537,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){ eType = IN_INDEX_EPH; if( prNotFound ){ *prNotFound = rMayHaveNull = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound); }else{ testcase( pParse->nQueryLoop>(double)1 ); pParse->nQueryLoop = (double)1; diff --git a/src/insert.c b/src/insert.c index eca3c12ddc..dadb10acdb 100644 --- a/src/insert.c +++ b/src/insert.c @@ -239,6 +239,7 @@ void sqlite3AutoincrementBegin(Parse *pParse){ memId = p->regCtr; assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenRead); + sqlite3VdbeAddOp3(v, OP_Null, 0, memId, memId+1); addr = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, p->pTab->zName, 0); sqlite3VdbeAddOp2(v, OP_Rewind, 0, addr+9); diff --git a/src/select.c b/src/select.c index a89ffe25c8..793b849b79 100644 --- a/src/select.c +++ b/src/select.c @@ -4154,6 +4154,7 @@ int sqlite3Select( VdbeComment((v, "clear abort flag")); sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag); VdbeComment((v, "indicate accumulator empty")); + sqlite3VdbeAddOp3(v, OP_Null, 0, iAMem, iAMem+pGroupBy->nExpr-1); /* Begin a loop that will extract all source rows in GROUP BY order. ** This might involve two separate loops with an OP_Sort in between, or diff --git a/src/update.c b/src/update.c index 1e3052218e..73d22690b5 100644 --- a/src/update.c +++ b/src/update.c @@ -126,8 +126,8 @@ void sqlite3Update( int regRowCount = 0; /* A count of rows changed */ int regOldRowid; /* The old rowid */ int regNewRowid; /* The new rowid */ - int regNew; - int regOld = 0; + int regNew; /* Content of the NEW.* table in triggers */ + int regOld = 0; /* Content of OLD.* table in triggers */ int regRowSet = 0; /* Rowset of rows to be updated */ memset(&sContext, 0, sizeof(sContext)); @@ -276,6 +276,7 @@ void sqlite3Update( #endif /* Allocate required registers. */ + regRowSet = ++pParse->nMem; regOldRowid = regNewRowid = ++pParse->nMem; if( pTrigger || hasFK ){ regOld = pParse->nMem + 1; @@ -310,7 +311,7 @@ void sqlite3Update( /* Begin the database scan */ - sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid); + sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid); pWInfo = sqlite3WhereBegin( pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED ); @@ -321,7 +322,6 @@ void sqlite3Update( */ sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regOldRowid); if( !okOnePass ){ - regRowSet = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid); } @@ -425,9 +425,10 @@ void sqlite3Update( newmask = sqlite3TriggerColmask( pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError ); + sqlite3VdbeAddOp3(v, OP_Null, 0, regNew, regNew+pTab->nCol-1); for(i=0; inCol; i++){ if( i==pTab->iPKey ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); + /*sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);*/ }else{ j = aXRef[i]; if( j>=0 ){ diff --git a/src/vdbe.c b/src/vdbe.c index 53cd4a2eff..64ae54e3db 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -764,7 +764,8 @@ case OP_Goto: { /* jump */ ** Write the current address onto register P1 ** and then jump to address P2. */ -case OP_Gosub: { /* jump, in1 */ +case OP_Gosub: { /* jump */ + assert( pOp->p1>0 && pOp->p1<=p->nMem ); pIn1 = &aMem[pOp->p1]; assert( (pIn1->flags & MEM_Dyn)==0 ); memAboutToChange(p, pIn1); @@ -961,12 +962,25 @@ case OP_String: { /* out2-prerelease */ break; } -/* Opcode: Null * P2 * * * +/* Opcode: Null * P2 P3 * * ** -** Write a NULL into register P2. +** Write a NULL into registers P2. If P3 greater than P2, then also write +** NULL into register P3 and ever register in between P2 and P3. If P3 +** is less than P2 (typically P3 is zero) then only register P2 is +** set to NULL */ case OP_Null: { /* out2-prerelease */ + int cnt; + cnt = pOp->p3-pOp->p2; + assert( pOp->p3<=p->nMem ); pOut->flags = MEM_Null; + while( cnt>0 ){ + pOut++; + memAboutToChange(p, pOut); + MemReleaseExt(pOut); + pOut->flags = MEM_Null; + cnt--; + } break; } @@ -2025,6 +2039,8 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */ ** ** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise, ** set the flag and fall through to the next instruction. +** +** See also: JumpOnce */ case OP_Once: { /* jump */ assert( pOp->p1nOnceFlag ); @@ -2040,13 +2056,13 @@ case OP_Once: { /* jump */ ** ** Jump to P2 if the value in register P1 is true. The value ** is considered true if it is numeric and non-zero. If the value -** in P1 is NULL then take the jump if P3 is true. +** in P1 is NULL then take the jump if P3 is non-zero. */ /* Opcode: IfNot P1 P2 P3 * * ** ** Jump to P2 if the value in register P1 is False. The value -** is considered true if it has a numeric value of zero. If the value -** in P1 is NULL then take the jump if P3 is true. +** is considered false if it has a numeric value of zero. If the value +** in P1 is NULL then take the jump if P3 is zero. */ case OP_If: /* jump, in1 */ case OP_IfNot: { /* jump, in1 */ @@ -5069,7 +5085,6 @@ case OP_Program: { /* jump */ pProgram = pOp->p4.pProgram; pRt = &aMem[pOp->p3]; - assert( memIsValid(pRt) ); assert( pProgram->nOp>0 ); /* If the p5 flag is clear, then recursive invocation of triggers is @@ -5134,7 +5149,7 @@ case OP_Program: { /* jump */ pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem]; for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){ - pMem->flags = MEM_Null; + pMem->flags = MEM_Invalid; pMem->db = db; } }else{ diff --git a/src/vdbeaux.c b/src/vdbeaux.c index b6e13f1335..8b085ea6ce 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -913,13 +913,14 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ } case P4_MEM: { Mem *pMem = pOp->p4.pMem; - assert( (pMem->flags & MEM_Null)==0 ); if( pMem->flags & MEM_Str ){ zP4 = pMem->z; }else if( pMem->flags & MEM_Int ){ sqlite3_snprintf(nTemp, zTemp, "%lld", pMem->u.i); }else if( pMem->flags & MEM_Real ){ sqlite3_snprintf(nTemp, zTemp, "%.16g", pMem->r); + }else if( pMem->flags & MEM_Null ){ + sqlite3_snprintf(nTemp, zTemp, "NULL"); }else{ assert( pMem->flags & MEM_Blob ); zP4 = "(blob)"; @@ -1094,7 +1095,7 @@ static void releaseMemArray(Mem *p, int N){ p->zMalloc = 0; } - p->flags = MEM_Null; + p->flags = MEM_Invalid; } db->mallocFailed = malloc_failed; } @@ -1532,8 +1533,7 @@ void sqlite3VdbeMakeReady( p->azVar = allocSpace(p->azVar, nVar*sizeof(char*), &zCsr, zEnd, &nByte); p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*), &zCsr, zEnd, &nByte); - p->aOnceFlag = allocSpace(p->aOnceFlag, nOnce*sizeof(u8), - &zCsr, zEnd, &nByte); + p->aOnceFlag = allocSpace(p->aOnceFlag, nOnce, &zCsr, zEnd, &nByte); if( nByte ){ p->pFree = sqlite3DbMallocZero(db, nByte); } @@ -1559,7 +1559,7 @@ void sqlite3VdbeMakeReady( p->aMem--; /* aMem[] goes from 1..nMem */ p->nMem = nMem; /* not from 0..nMem-1 */ for(n=1; n<=nMem; n++){ - p->aMem[n].flags = MEM_Null; + p->aMem[n].flags = MEM_Invalid; p->aMem[n].db = db; } } @@ -1649,7 +1649,6 @@ static void closeAllCursors(Vdbe *p){ p->pDelFrame = pDel->pParent; sqlite3VdbeFrameDelete(pDel); } - memset(p->aOnceFlag, 0, p->nOnceFlag); } /* @@ -1666,8 +1665,10 @@ static void Cleanup(Vdbe *p){ /* Execute assert() statements to ensure that the Vdbe.apCsr[] and ** Vdbe.aMem[] arrays have already been cleaned up. */ int i; - for(i=0; inCursor; i++) assert( p->apCsr==0 || p->apCsr[i]==0 ); - for(i=1; i<=p->nMem; i++) assert( p->aMem==0 || p->aMem[i].flags==MEM_Null ); + if( p->apCsr ) for(i=0; inCursor; i++) assert( p->apCsr[i]==0 ); + if( p->aMem ){ + for(i=1; i<=p->nMem; i++) assert( p->aMem[i].flags==MEM_Invalid ); + } #endif sqlite3DbFree(db, p->zErrMsg); @@ -2135,6 +2136,7 @@ int sqlite3VdbeHalt(Vdbe *p){ if( p->db->mallocFailed ){ p->rc = SQLITE_NOMEM; } + if( p->aOnceFlag ) memset(p->aOnceFlag, 0, p->nOnceFlag); closeAllCursors(p); if( p->magic!=VDBE_MAGIC_RUN ){ return SQLITE_OK;