1
0
mirror of https://github.com/sqlite/sqlite.git synced 2026-01-06 08:01:16 +03:00

Change the VDBE so that all registers are initialized to "Invalid" instead of

NULL and report errors on any attempted read of an Invalid register.  This
will help prevent future bugs similar to [7bbfb7d442].

FossilOrigin-Name: 0064bab77149768640d7758a3e271d5a1d63b256
This commit is contained in:
drh
2011-12-09 18:06:44 +00:00
8 changed files with 57 additions and 35 deletions

View File

@@ -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 <table>. */
Expr *pExpr; /* Expression <column> */
int iCol; /* Index of column <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;

View File

@@ -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);

View File

@@ -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

View File

@@ -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; i<pTab->nCol; 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 ){

View File

@@ -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->p1<p->nOnceFlag );
@@ -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{

View File

@@ -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; i<p->nCursor; 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; i<p->nCursor; 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;