Change the MEM_Dyn flag so that it means that Mem.xDel exists and must be
used to free the string or blob. Add tighter invariant checks on Mem. FossilOrigin-Name: 44e1c33767cae3bf2cbd2238831fe67197009b43
This commit is contained in:
parent
75fd054201
commit
c91b2fd310
20
manifest
20
manifest
@ -1,5 +1,5 @@
|
||||
C Factor\sthe\sMem\sinvariant\schecker\sinto\sa\sseparate\sprocedure\s(rather\sthan\sa\nmacro)\sso\sthat\sit\scan\sbe\smore\seasily\sextended.
|
||||
D 2014-03-01T16:24:44.768
|
||||
C Change\sthe\sMEM_Dyn\sflag\sso\sthat\sit\smeans\sthat\sMem.xDel\sexists\sand\smust\sbe\nused\sto\sfree\sthe\sstring\sor\sblob.\s\sAdd\stighter\sinvariant\schecks\son\sMem.
|
||||
D 2014-03-01T18:13:23.744
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -274,16 +274,16 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/tokenize.c 6da2de6e12218ccb0aea5184b56727d011f4bee7
|
||||
F src/trigger.c a80036fcbd992729adc7cd34a875d59a71fa10cc
|
||||
F src/update.c 5b3e74a03b3811e586b4f2b4cbd7c49f01c93115
|
||||
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
|
||||
F src/utf.c 6dc9ec9f1b3db43ae8ba0365377f11df1ee4c01c
|
||||
F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf
|
||||
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
||||
F src/vdbe.c 9abaa1ebb8b98e33121ea1aade1022fdc195b464
|
||||
F src/vdbe.c cbed4957185bfee7e585dce208d8ec4cd87179c2
|
||||
F src/vdbe.h 147027d6e8e667a63e87177a38e2b42c71fdacf8
|
||||
F src/vdbeInt.h a82d5ab4fd8138bdff7de4a267ea5c04e4cbb370
|
||||
F src/vdbeInt.h d55cab859abb2c6656911497ae74eba9dcf34e28
|
||||
F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820
|
||||
F src/vdbeaux.c 2f97cd756e2704b06006b398ce468f0bcc006055
|
||||
F src/vdbeaux.c 89a0ad3b2ecdbe71cf827a1f99d0ae51eccd6cce
|
||||
F src/vdbeblob.c d939997de046b8fcc607cfee4248f3d33dbcca50
|
||||
F src/vdbemem.c 8c84ec056c7934cef359f4d49fa32b856eeffd88
|
||||
F src/vdbemem.c 868a498a670c08344a594a9d5903a3ff330916a7
|
||||
F src/vdbesort.c 9d83601f9d6243fe70dd0169a2820c5ddfd48147
|
||||
F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767
|
||||
F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
|
||||
@ -1152,7 +1152,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
||||
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
||||
P 4aeb3ae435c78070232fef21a147fde4e1c5cd31
|
||||
R c42d4082e634170a16f76850fb72106d
|
||||
P 354699d50e7d251504a7b3d6fbec9e5bcf99557f
|
||||
R 0950c7cf1a1151e6071aa7a5599d1f4e
|
||||
U drh
|
||||
Z e1bae2e998058d57d79a76345aaf3403
|
||||
Z c9678592d0817ad1269cd44af9e6bf96
|
||||
|
@ -1 +1 @@
|
||||
354699d50e7d251504a7b3d6fbec9e5bcf99557f
|
||||
44e1c33767cae3bf2cbd2238831fe67197009b43
|
@ -317,7 +317,7 @@ int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
|
||||
sqlite3VdbeMemRelease(pMem);
|
||||
pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem);
|
||||
pMem->enc = desiredEnc;
|
||||
pMem->flags |= (MEM_Term|MEM_Dyn);
|
||||
pMem->flags |= (MEM_Term);
|
||||
pMem->z = (char*)zOut;
|
||||
pMem->zMalloc = pMem->z;
|
||||
|
||||
@ -445,7 +445,6 @@ char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 enc){
|
||||
}
|
||||
assert( (m.flags & MEM_Term)!=0 || db->mallocFailed );
|
||||
assert( (m.flags & MEM_Str)!=0 || db->mallocFailed );
|
||||
assert( (m.flags & MEM_Dyn)!=0 || db->mallocFailed );
|
||||
assert( m.z || db->mallocFailed );
|
||||
return m.z;
|
||||
}
|
||||
|
23
src/vdbe.c
23
src/vdbe.c
@ -152,7 +152,7 @@ int sqlite3_found_count = 0;
|
||||
**
|
||||
** This routine converts an ephemeral string into a dynamically allocated
|
||||
** string that the register itself controls. In other words, it
|
||||
** converts an MEM_Ephem string into an MEM_Dyn string.
|
||||
** converts an MEM_Ephem string into a string with P.z==P.zMalloc.
|
||||
*/
|
||||
#define Deephemeralize(P) \
|
||||
if( ((P)->flags&MEM_Ephem)!=0 \
|
||||
@ -716,7 +716,7 @@ check_for_interrupt:
|
||||
case OP_Gosub: { /* jump */
|
||||
assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) );
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
assert( (pIn1->flags & MEM_Dyn)==0 );
|
||||
assert( VdbeMemDynamic(pIn1)==0 );
|
||||
memAboutToChange(p, pIn1);
|
||||
pIn1->flags = MEM_Int;
|
||||
pIn1->u.i = pc;
|
||||
@ -789,7 +789,7 @@ case OP_EndCoroutine: { /* in1 */
|
||||
case OP_Yield: { /* in1, jump */
|
||||
int pcDest;
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
assert( (pIn1->flags & MEM_Dyn)==0 );
|
||||
assert( VdbeMemDynamic(pIn1)==0 );
|
||||
pIn1->flags = MEM_Int;
|
||||
pcDest = (int)pIn1->u.i;
|
||||
pIn1->u.i = pc;
|
||||
@ -962,10 +962,9 @@ case OP_String8: { /* same as TK_STRING, out2-prerelease */
|
||||
if( rc==SQLITE_TOOBIG ) goto too_big;
|
||||
if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem;
|
||||
assert( pOut->zMalloc==pOut->z );
|
||||
assert( pOut->flags & MEM_Dyn );
|
||||
assert( VdbeMemDynamic(pOut)==0 );
|
||||
pOut->zMalloc = 0;
|
||||
pOut->flags |= MEM_Static;
|
||||
pOut->flags &= ~MEM_Dyn;
|
||||
if( pOp->p4type==P4_DYNAMIC ){
|
||||
sqlite3DbFree(db, pOp->p4.z);
|
||||
}
|
||||
@ -1101,14 +1100,16 @@ case OP_Move: {
|
||||
assert( pIn1<=&aMem[(p->nMem-p->nCursor)] );
|
||||
assert( memIsValid(pIn1) );
|
||||
memAboutToChange(p, pOut);
|
||||
VdbeMemRelease(pOut);
|
||||
zMalloc = pOut->zMalloc;
|
||||
pOut->zMalloc = 0;
|
||||
sqlite3VdbeMemMove(pOut, pIn1);
|
||||
memcpy(pOut, pIn1, sizeof(Mem));
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<&aMem[p1+pOp->p3] ){
|
||||
pOut->pScopyFrom += p1 - pOp->p2;
|
||||
}
|
||||
#endif
|
||||
pIn1->flags = MEM_Undefined;
|
||||
pIn1->xDel = 0;
|
||||
pIn1->zMalloc = zMalloc;
|
||||
REGISTER_TRACE(p2++, pOut);
|
||||
pIn1++;
|
||||
@ -1285,10 +1286,10 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
|
||||
if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
|
||||
goto too_big;
|
||||
}
|
||||
MemSetTypeFlag(pOut, MEM_Str);
|
||||
if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){
|
||||
goto no_mem;
|
||||
}
|
||||
MemSetTypeFlag(pOut, MEM_Str);
|
||||
if( pOut!=pIn2 ){
|
||||
memcpy(pOut->z, pIn2->z, pIn2->n);
|
||||
}
|
||||
@ -2501,8 +2502,8 @@ case OP_Column: {
|
||||
** This prevents a memory copy. */
|
||||
if( sMem.zMalloc ){
|
||||
assert( sMem.z==sMem.zMalloc );
|
||||
assert( !(pDest->flags & MEM_Dyn) );
|
||||
assert( !(pDest->flags & (MEM_Blob|MEM_Str)) || pDest->z==sMem.z );
|
||||
assert( VdbeMemDynamic(pDest)==0 );
|
||||
assert( (pDest->flags & (MEM_Blob|MEM_Str))==0 || pDest->z==sMem.z );
|
||||
pDest->flags &= ~(MEM_Ephem|MEM_Static);
|
||||
pDest->flags |= MEM_Term;
|
||||
pDest->z = sMem.z;
|
||||
@ -2685,7 +2686,7 @@ case OP_MakeRecord: {
|
||||
|
||||
assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
|
||||
pOut->n = (int)nByte;
|
||||
pOut->flags = MEM_Blob | MEM_Dyn;
|
||||
pOut->flags = MEM_Blob;
|
||||
pOut->xDel = 0;
|
||||
if( nZero ){
|
||||
pOut->u.nZero = nZero;
|
||||
|
@ -208,7 +208,7 @@ struct Mem {
|
||||
** string is \000 or \u0000 terminated
|
||||
*/
|
||||
#define MEM_Term 0x0200 /* String rep is nul terminated */
|
||||
#define MEM_Dyn 0x0400 /* Need to call sqliteFree() on Mem.z */
|
||||
#define MEM_Dyn 0x0400 /* Need to call Mem.xDel() on Mem.z */
|
||||
#define MEM_Static 0x0800 /* Mem.z points to a static string */
|
||||
#define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */
|
||||
#define MEM_Agg 0x2000 /* Mem.z points to an agg function context */
|
||||
|
@ -1414,7 +1414,7 @@ int sqlite3VdbeList(
|
||||
assert( p->db->mallocFailed );
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
|
||||
pMem->flags = MEM_Str|MEM_Term;
|
||||
zP4 = displayP4(pOp, pMem->z, 32);
|
||||
if( zP4!=pMem->z ){
|
||||
sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0);
|
||||
@ -1431,7 +1431,7 @@ int sqlite3VdbeList(
|
||||
assert( p->db->mallocFailed );
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
|
||||
pMem->flags = MEM_Str|MEM_Term;
|
||||
pMem->n = 2;
|
||||
sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */
|
||||
pMem->memType = MEM_Str;
|
||||
@ -1443,7 +1443,7 @@ int sqlite3VdbeList(
|
||||
assert( p->db->mallocFailed );
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
|
||||
pMem->flags = MEM_Str|MEM_Term;
|
||||
pMem->n = displayComment(pOp, zP4, pMem->z, 500);
|
||||
pMem->memType = MEM_Str;
|
||||
pMem->enc = SQLITE_UTF8;
|
||||
|
@ -26,11 +26,29 @@
|
||||
** this: assert( sqlite3VdbeCheckMemInvariants(pMem) );
|
||||
*/
|
||||
int sqlite3VdbeCheckMemInvariants(Mem *p){
|
||||
assert(
|
||||
(((p)->zMalloc && (p)->zMalloc==(p)->z) ? 1 : 0) +
|
||||
((((p)->flags&MEM_Dyn)&&(p)->xDel) ? 1 : 0) +
|
||||
(((p)->flags&MEM_Ephem) ? 1 : 0) +
|
||||
(((p)->flags&MEM_Static) ? 1 : 0) <= 1 );
|
||||
/* The MEM_Dyn bit is set if and only if Mem.xDel is a non-NULL destructor
|
||||
** function for Mem.z
|
||||
*/
|
||||
assert( (p->flags & MEM_Dyn)==0 || p->xDel!=0 );
|
||||
assert( (p->flags & MEM_Dyn)!=0 || p->xDel==0 );
|
||||
|
||||
/* If p holds a string or blob, the Mem.z must point to exactly
|
||||
** one of the following:
|
||||
**
|
||||
** (1) Memory in Mem.zMalloc and managed by the Mem object
|
||||
** (2) Memory to be freed using Mem.xDel
|
||||
** (3) An ephermal string or blob
|
||||
** (4) A static string or blob
|
||||
*/
|
||||
if( (p->flags & (MEM_Str|MEM_Blob)) && p->z!=0 ){
|
||||
assert(
|
||||
((p->z==p->zMalloc)? 1 : 0) +
|
||||
((p->flags&MEM_Dyn)!=0 ? 1 : 0) +
|
||||
((p->flags&MEM_Ephem)!=0 ? 1 : 0) +
|
||||
((p->flags&MEM_Static)!=0 ? 1 : 0) == 1
|
||||
);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
@ -103,7 +121,7 @@ int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
|
||||
pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n);
|
||||
}
|
||||
if( pMem->zMalloc==0 ){
|
||||
sqlite3VdbeMemRelease(pMem);
|
||||
VdbeMemRelease(pMem);
|
||||
pMem->flags = MEM_Null;
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
@ -112,13 +130,13 @@ int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
|
||||
if( pMem->z && bPreserve && pMem->z!=pMem->zMalloc ){
|
||||
memcpy(pMem->zMalloc, pMem->z, pMem->n);
|
||||
}
|
||||
if( (pMem->flags&MEM_Dyn)!=0 && pMem->xDel ){
|
||||
assert( pMem->xDel!=SQLITE_DYNAMIC );
|
||||
if( (pMem->flags&MEM_Dyn)!=0 ){
|
||||
assert( pMem->xDel!=0 && pMem->xDel!=SQLITE_DYNAMIC );
|
||||
pMem->xDel((void *)(pMem->z));
|
||||
}
|
||||
|
||||
pMem->z = pMem->zMalloc;
|
||||
pMem->flags &= ~(MEM_Ephem|MEM_Static);
|
||||
pMem->flags &= ~(MEM_Dyn|MEM_Ephem|MEM_Static);
|
||||
pMem->xDel = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@ -287,9 +305,9 @@ void sqlite3VdbeMemReleaseExternal(Mem *p){
|
||||
sqlite3VdbeMemFinalize(p, p->u.pDef);
|
||||
assert( (p->flags & MEM_Agg)==0 );
|
||||
sqlite3VdbeMemRelease(p);
|
||||
}else if( p->flags&MEM_Dyn && p->xDel ){
|
||||
}else if( p->flags&MEM_Dyn ){
|
||||
assert( (p->flags&MEM_RowSet)==0 );
|
||||
assert( p->xDel!=SQLITE_DYNAMIC );
|
||||
assert( p->xDel!=SQLITE_DYNAMIC && p->xDel!=0 );
|
||||
p->xDel((void *)p->z);
|
||||
p->xDel = 0;
|
||||
}else if( p->flags&MEM_RowSet ){
|
||||
@ -643,6 +661,7 @@ int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
|
||||
VdbeMemRelease(pTo);
|
||||
memcpy(pTo, pFrom, MEMCELLSIZE);
|
||||
pTo->flags &= ~MEM_Dyn;
|
||||
pTo->xDel = 0;
|
||||
|
||||
if( pTo->flags&(MEM_Str|MEM_Blob) ){
|
||||
if( 0==(pFrom->flags&MEM_Static) ){
|
||||
@ -922,7 +941,7 @@ int sqlite3VdbeMemFromBtree(
|
||||
pMem->z = &zData[offset];
|
||||
pMem->flags = MEM_Blob|MEM_Ephem;
|
||||
}else if( SQLITE_OK==(rc = sqlite3VdbeMemGrow(pMem, amt+2, 0)) ){
|
||||
pMem->flags = MEM_Blob|MEM_Dyn|MEM_Term;
|
||||
pMem->flags = MEM_Blob|MEM_Term;
|
||||
pMem->enc = 0;
|
||||
pMem->memType = MEM_Blob;
|
||||
if( key ){
|
||||
|
Loading…
Reference in New Issue
Block a user