#include "sqliteInt.h"
#include "vdbeInt.h"
+/*
+** Invoke this macro on memory cells just prior to changing the
+** value of the cell. This macro verifies that shallow copies are
+** not misused.
+*/
+#ifdef SQLITE_DEBUG
+# define memAboutToChange(P,M) sqlite3VdbeMemPrepareToChange(P,M)
+#else
+# define memAboutToChange(P,M)
+#endif
+
/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_SeekXX, OP_Next, or OP_Prev opcodes. The test
assert( pOp->p2>0 );
assert( pOp->p2<=p->nMem );
pOut = &aMem[pOp->p2];
+ memAboutToChange(p, pOut);
sqlite3VdbeMemReleaseExternal(pOut);
pOut->flags = MEM_Int;
}
if( (pOp->opflags & OPFLG_IN1)!=0 ){
assert( pOp->p1>0 );
assert( pOp->p1<=p->nMem );
+ assert( memIsValid(&aMem[pOp->p1]) );
REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]);
}
if( (pOp->opflags & OPFLG_IN2)!=0 ){
assert( pOp->p2>0 );
assert( pOp->p2<=p->nMem );
+ assert( memIsValid(&aMem[pOp->p2]) );
REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]);
}
if( (pOp->opflags & OPFLG_IN3)!=0 ){
assert( pOp->p3>0 );
assert( pOp->p3<=p->nMem );
+ assert( memIsValid(&aMem[pOp->p3]) );
REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]);
}
if( (pOp->opflags & OPFLG_OUT2)!=0 ){
assert( pOp->p2>0 );
assert( pOp->p2<=p->nMem );
+ memAboutToChange(p, &aMem[pOp->p2]);
}
if( (pOp->opflags & OPFLG_OUT3)!=0 ){
assert( pOp->p3>0 );
assert( pOp->p3<=p->nMem );
+ memAboutToChange(p, &aMem[pOp->p3]);
}
#endif
case OP_Gosub: { /* jump, in1 */
pIn1 = &aMem[pOp->p1];
assert( (pIn1->flags & MEM_Dyn)==0 );
+ memAboutToChange(p, pIn1);
pIn1->flags = MEM_Int;
pIn1->u.i = pc;
REGISTER_TRACE(pOp->p1, pIn1);
while( n-- ){
assert( pOut<=&aMem[p->nMem] );
assert( pIn1<=&aMem[p->nMem] );
+ assert( memIsValid(pIn1) );
+ memAboutToChange(p, pOut);
zMalloc = pOut->zMalloc;
pOut->zMalloc = 0;
sqlite3VdbeMemMove(pOut, pIn1);
pOut = &aMem[pOp->p2];
assert( pOut!=pIn1 );
sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
+#ifdef SQLITE_DEBUG
+ if( pOut->pScopyFrom==0 ) pOut->pScopyFrom = pIn1;
+#endif
REGISTER_TRACE(pOp->p2, pOut);
break;
}
*/
pMem = p->pResultSet = &aMem[pOp->p1];
for(i=0; i<pOp->p2; i++){
+ assert( memIsValid(&pMem[i]) );
+ memAboutToChange(p, &pMem[i]);
sqlite3VdbeMemNulTerminate(&pMem[i]);
sqlite3VdbeMemStoreType(&pMem[i]);
REGISTER_TRACE(pOp->p1+i, &pMem[i]);
assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
pArg = &aMem[pOp->p2];
for(i=0; i<n; i++, pArg++){
+ assert( memIsValid(pArg) );
apVal[i] = pArg;
+ memAboutToChange(p, pArg);
sqlite3VdbeMemStoreType(pArg);
REGISTER_TRACE(pOp->p2+i, pArg);
}
assert( pOp->p3>0 && pOp->p3<=p->nMem );
pOut = &aMem[pOp->p3];
+ memAboutToChange(p, pOut);
ctx.s.flags = MEM_Null;
ctx.s.db = db;
ctx.s.xDel = 0;
*/
case OP_AddImm: { /* in1 */
pIn1 = &aMem[pOp->p1];
+ memAboutToChange(p, pIn1);
sqlite3VdbeMemIntegerify(pIn1);
pIn1->u.i += pOp->p2;
break;
*/
case OP_MustBeInt: { /* jump, in1 */
pIn1 = &aMem[pOp->p1];
+ memAboutToChange(p, pIn1);
applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding);
if( (pIn1->flags & MEM_Int)==0 ){
if( pOp->p2==0 ){
*/
case OP_RealAffinity: { /* in1 */
pIn1 = &aMem[pOp->p1];
+ memAboutToChange(p, pIn1);
if( pIn1->flags & MEM_Int ){
sqlite3VdbeMemRealify(pIn1);
}
*/
case OP_ToText: { /* same as TK_TO_TEXT, in1 */
pIn1 = &aMem[pOp->p1];
+ memAboutToChange(p, pIn1);
if( pIn1->flags & MEM_Null ) break;
assert( MEM_Str==(MEM_Blob>>3) );
pIn1->flags |= (pIn1->flags&MEM_Blob)>>3;
*/
case OP_ToBlob: { /* same as TK_TO_BLOB, in1 */
pIn1 = &aMem[pOp->p1];
+ memAboutToChange(p, pIn1);
if( pIn1->flags & MEM_Null ) break;
if( (pIn1->flags & MEM_Blob)==0 ){
applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding);
*/
case OP_ToNumeric: { /* same as TK_TO_NUMERIC, in1 */
pIn1 = &aMem[pOp->p1];
+ memAboutToChange(p, pIn1);
if( (pIn1->flags & (MEM_Null|MEM_Int|MEM_Real))==0 ){
sqlite3VdbeMemNumerify(pIn1);
}
*/
case OP_ToInt: { /* same as TK_TO_INT, in1 */
pIn1 = &aMem[pOp->p1];
+ memAboutToChange(p, pIn1);
if( (pIn1->flags & MEM_Null)==0 ){
sqlite3VdbeMemIntegerify(pIn1);
}
*/
case OP_ToReal: { /* same as TK_TO_REAL, in1 */
pIn1 = &aMem[pOp->p1];
+ memAboutToChange(p, pIn1);
if( (pIn1->flags & MEM_Null)==0 ){
sqlite3VdbeMemRealify(pIn1);
}
pIn1 = &aMem[pOp->p1];
pIn3 = &aMem[pOp->p3];
+ memAboutToChange(p, pIn1);
+ memAboutToChange(p, pIn3);
flags1 = pIn1->flags;
flags3 = pIn3->flags;
if( (pIn1->flags | pIn3->flags)&MEM_Null ){
if( pOp->p5 & SQLITE_STOREP2 ){
pOut = &aMem[pOp->p2];
+ memAboutToChange(p, pOut);
MemSetTypeFlag(pOut, MEM_Int);
pOut->u.i = res;
REGISTER_TRACE(pOp->p2, pOut);
#endif /* SQLITE_DEBUG */
for(i=0; i<n; i++){
idx = aPermute ? aPermute[i] : i;
+ assert( memIsValid(&aMem[p1+idx]) );
+ assert( memIsValid(&aMem[p2+idx]) );
REGISTER_TRACE(p1+idx, &aMem[p1+idx]);
REGISTER_TRACE(p2+idx, &aMem[p2+idx]);
assert( i<pKeyInfo->nField );
assert( p1<p->nCursor );
assert( pOp->p3>0 && pOp->p3<=p->nMem );
pDest = &aMem[pOp->p3];
+ memAboutToChange(p, pDest);
MemSetTypeFlag(pDest, MEM_Null);
zRec = 0;
}else if( pC->pseudoTableReg>0 ){
pReg = &aMem[pC->pseudoTableReg];
assert( pReg->flags & MEM_Blob );
+ assert( memIsValid(pReg) );
payloadSize = pReg->n;
zRec = pReg->z;
pC->cacheStatus = (pOp->p5&OPFLAG_CLEARCACHE) ? CACHE_STALE : p->cacheCtr;
pIn1 = &aMem[pOp->p1];
while( (cAff = *(zAffinity++))!=0 ){
assert( pIn1 <= &p->aMem[p->nMem] );
+ assert( memIsValid(pIn1) );
+ memAboutToChange(p, pIn1);
ExpandBlob(pIn1);
applyAffinity(pIn1, cAff, encoding);
pIn1++;
pLast = &pData0[nField-1];
file_format = p->minWriteFileFormat;
+ /* Identify the output register */
+ assert( pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2 );
+ pOut = &aMem[pOp->p3];
+ memAboutToChange(p, pOut);
+
/* Loop through the elements that will make up the record to figure
** out how much space is required for the new record.
*/
for(pRec=pData0; pRec<=pLast; pRec++){
+ assert( memIsValid(pRec) );
if( zAffinity ){
+ memAboutToChange(p, pRec);
applyAffinity(pRec, zAffinity[pRec-pData0], encoding);
}
if( pRec->flags&MEM_Zero && pRec->n>0 ){
** be one of the input registers (because the following call to
** sqlite3VdbeMemGrow() could clobber the value before it is used).
*/
- assert( pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2 );
- pOut = &aMem[pOp->p3];
if( sqlite3VdbeMemGrow(pOut, (int)nByte, 0) ){
goto no_mem;
}
assert( p2>0 );
assert( p2<=p->nMem );
pIn2 = &aMem[p2];
+ assert( memIsValid(pIn2) );
+ assert( (pIn2->flags & MEM_Int)!=0 );
sqlite3VdbeMemIntegerify(pIn2);
p2 = (int)pIn2->u.i;
/* The p2 value always comes from a prior OP_CreateTable opcode and
assert( oc!=OP_SeekLt || r.flags==0 );
r.aMem = &aMem[pOp->p3];
+#ifdef SQLITE_DEBUG
+ { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
+#endif
ExpandBlob(r.aMem);
rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, &r, 0, 0, &res);
if( rc!=SQLITE_OK ){
r.pKeyInfo = pC->pKeyInfo;
r.nField = (u16)pOp->p4.i;
r.aMem = pIn3;
+#ifdef SQLITE_DEBUG
+ { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
+#endif
r.flags = UNPACKED_PREFIX_MATCH;
pIdxKey = &r;
}else{
r.nField = nField + 1;
r.flags = UNPACKED_PREFIX_SEARCH;
r.aMem = aMx;
+#ifdef SQLITE_DEBUG
+ { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
+#endif
/* Extract the value of R from register P3. */
sqlite3VdbeMemIntegerify(pIn3);
/* Assert that P3 is a valid memory cell. */
assert( pOp->p3<=p->nMem );
pMem = &aMem[pOp->p3];
+ memAboutToChange(p, pMem);
}
+ assert( memIsValid(pMem) );
REGISTER_TRACE(pOp->p3, pMem);
sqlite3VdbeMemIntegerify(pMem);
pData = &aMem[pOp->p2];
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ assert( memIsValid(pData) );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pC->pCursor!=0 );
if( pOp->opcode==OP_Insert ){
pKey = &aMem[pOp->p3];
assert( pKey->flags & MEM_Int );
+ assert( memIsValid(pKey) );
REGISTER_TRACE(pOp->p3, pKey);
iKey = pKey->u.i;
}else{
i64 n64;
pOut = &aMem[pOp->p2];
+ memAboutToChange(p, pOut);
/* Note that RowKey and RowData are really exactly the same instruction */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
r.nField = (u16)pOp->p3;
r.flags = 0;
r.aMem = &aMem[pOp->p2];
+#ifdef SQLITE_DEBUG
+ { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
+#endif
rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res);
if( rc==SQLITE_OK && res==0 ){
rc = sqlite3BtreeDelete(pCrsr);
r.flags = UNPACKED_IGNORE_ROWID;
}
r.aMem = &aMem[pOp->p3];
+#ifdef SQLITE_DEBUG
+ { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
+#endif
rc = sqlite3VdbeIdxKeyCompare(pC, &r, &res);
if( pOp->opcode==OP_IdxLT ){
res = -res;
if( pOp->p3 ){
p->nChange += nChange;
if( pOp->p3>0 ){
+ assert( memIsValid(&aMem[pOp->p3]) );
+ memAboutToChange(p, &aMem[pOp->p3]);
aMem[pOp->p3].u.i += nChange;
}
}
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
}else{
pIn1 = &aMem[pOp->p1];
}
+ assert( memIsValid(pIn1) );
sqlite3VdbeMemIntegerify(pIn1);
pIn2 = &aMem[pOp->p2];
sqlite3VdbeMemIntegerify(pIn2);
apVal = p->apArg;
assert( apVal || n==0 );
for(i=0; i<n; i++, pRec++){
+ assert( memIsValid(pRec) );
apVal[i] = pRec;
+ memAboutToChange(p, pRec);
sqlite3VdbeMemStoreType(pRec);
}
ctx.pFunc = pOp->p4.pFunc;
pQuery = &aMem[pOp->p3];
pArgc = &pQuery[1];
pCur = p->apCsr[pOp->p1];
+ assert( memIsValid(pQuery) );
REGISTER_TRACE(pOp->p3, pQuery);
assert( pCur->pVtabCursor );
pVtabCursor = pCur->pVtabCursor;
assert( pCur->pVtabCursor );
assert( pOp->p3>0 && pOp->p3<=p->nMem );
pDest = &aMem[pOp->p3];
+ memAboutToChange(p, pDest);
if( pCur->nullRow ){
sqlite3VdbeMemSetNull(pDest);
break;
pVtab = pOp->p4.pVtab->pVtab;
pName = &aMem[pOp->p1];
assert( pVtab->pModule->xRename );
+ assert( memIsValid(pName) );
REGISTER_TRACE(pOp->p1, pName);
assert( pName->flags & MEM_Str );
rc = pVtab->pModule->xRename(pVtab, pName->z);
apArg = p->apArg;
pX = &aMem[pOp->p3];
for(i=0; i<nArg; i++){
+ assert( memIsValid(pX) );
+ memAboutToChange(p, pX);
sqlite3VdbeMemStoreType(pX);
apArg[i] = pX;
pX++;