]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Change the MEM_Dyn flag so that it means that Mem.xDel exists and must be enhanced-mem-check
authordrh <drh@noemail.net>
Sat, 1 Mar 2014 18:13:23 +0000 (18:13 +0000)
committerdrh <drh@noemail.net>
Sat, 1 Mar 2014 18:13:23 +0000 (18:13 +0000)
used to free the string or blob.  Add tighter invariant checks on Mem.

FossilOrigin-Name: 44e1c33767cae3bf2cbd2238831fe67197009b43

manifest
manifest.uuid
src/utf.c
src/vdbe.c
src/vdbeInt.h
src/vdbeaux.c
src/vdbemem.c

index 75bec546796c0a78bf6cbfc99fa79469e6a821bb..5a221fb21d0de015b4ba9086fc70a49785e3b50b 100644 (file)
--- a/manifest
+++ b/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
index 7b0fa50ebd1e3ce6239f4725623d6cbd95cbb897..764bf41b7a61cb417ccaf428f91c2b4ce82bb766 100644 (file)
@@ -1 +1 @@
-354699d50e7d251504a7b3d6fbec9e5bcf99557f
\ No newline at end of file
+44e1c33767cae3bf2cbd2238831fe67197009b43
\ No newline at end of file
index ecb3ea03b87a3f49622ee860490171de0aab51f3..96b679fff4e09721a1e645bd7d8e2b362ebf592d 100644 (file)
--- a/src/utf.c
+++ b/src/utf.c
@@ -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;
 }
index c8e837b81bfddcd99dd1dede50e7f3214501ce7d..8e5a3da00f086349d459bad5c41a139432791a56 100644 (file)
@@ -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;
index 047a4f2697fb2c1ed3d07d26a18606533d98dbbb..c16baff685e3d9c970aaab9c748610cd53f4de8f 100644 (file)
@@ -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 */
index 4a541e0d480be8f9cf3dae23541fd874a12a4cf8..39be964093d953b59e1773bc809bec20458d4bad 100644 (file)
@@ -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;
index 532cd58d9e788e944311dcff545679a7574b822c..3c9412a700313528355374f986404183a8628049 100644 (file)
 ** 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 ){