/ Check-in [562da534]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Take care to track ephemeral strings in the VDBE and make copies of ephemeral strings that need to be preserved. Ticket #177. (CVS 769)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:562da534bbb605a8ce15824135b012ef2d86bbeb
User & Date: drh 2002-10-22 15:04:34
Context
2002-10-22
23:38
Correctly handle column names and string constants in parentheses. Fix for ticket #179. (CVS 770) check-in: 3b68aa25 user: drh tags: trunk
15:04
Take care to track ephemeral strings in the VDBE and make copies of ephemeral strings that need to be preserved. Ticket #177. (CVS 769) check-in: 562da534 user: drh tags: trunk
2002-10-20
18:19
Rework the changes for ticket #176 (check-ins (760) and (761)) to be more consistent with the rest of the source code. (CVS 768) check-in: f50a177b user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/vdbe.c.

    32     32   **
    33     33   ** Various scripts scan this source file in order to generate HTML
    34     34   ** documentation, headers files, or other derived files.  The formatting
    35     35   ** of the code in this file is, therefore, important.  See other comments
    36     36   ** in this file for details.  If in doubt, do not deviate from existing
    37     37   ** commenting and indentation practices when changing or adding code.
    38     38   **
    39         -** $Id: vdbe.c,v 1.180 2002/10/19 20:16:38 drh Exp $
           39  +** $Id: vdbe.c,v 1.181 2002/10/22 15:04:34 drh Exp $
    40     40   */
    41     41   #include "sqliteInt.h"
    42     42   #include <ctype.h>
    43     43   
    44     44   /*
    45     45   ** The makefile scans this source file and creates the following
    46     46   ** array of string constants which are the names of all VDBE opcodes.
................................................................................
   148    148   /*
   149    149   ** Allowed values for Stack.flags
   150    150   */
   151    151   #define STK_Null      0x0001   /* Value is NULL */
   152    152   #define STK_Str       0x0002   /* Value is a string */
   153    153   #define STK_Int       0x0004   /* Value is an integer */
   154    154   #define STK_Real      0x0008   /* Value is a real number */
   155         -#define STK_Dyn       0x0010   /* Need to call sqliteFree() on zStack[*] */
          155  +#define STK_Dyn       0x0010   /* Need to call sqliteFree() on zStack[] */
   156    156   #define STK_Static    0x0020   /* zStack[] points to a static string */
          157  +#define STK_Ephem     0x0040   /* zStack[] points to an ephemeral string */
   157    158   
   158    159   /* The following STK_ value appears only in AggElem.aMem.s.flag fields.
   159    160   ** It indicates that the corresponding AggElem.aMem.z points to a
   160    161   ** aggregate function context that needs to be finalized.
   161    162   */
   162    163   #define STK_AggCtx    0x0040   /* zStack[] points to an agg function context */
   163    164   
................................................................................
   793    794       pStack->z[0] = 0;
   794    795     }
   795    796     *pzStack = pStack->z;
   796    797     pStack->n = strlen(*pzStack)+1;
   797    798     pStack->flags = STK_Str;
   798    799     return 0;
   799    800   }
          801  +
          802  +/*
          803  +** An ephemeral string value (signified by the STK_Ephem flag) contains
          804  +** a pointer to a dynamically allocated string where some other entity
          805  +** is responsible for deallocating that string.  Because the stack entry
          806  +** does not control the string, it might be deleted without the stack
          807  +** entry knowing it.
          808  +**
          809  +** This routine converts an ephemeral string into a dynamically allocated
          810  +** string that the stack entry itself controls.  In other words, it
          811  +** converts an STK_Ephem string into an STK_Dyn string.
          812  +*/
          813  +#define Deephemeralize(P,I) \
          814  +   if( ((P)->aStack[I].flags&STK_Ephem)!=0 && hardDeephem(P,I) ){ goto no_mem;}
          815  +static int hardDeephem(Vdbe *p, int i){
          816  +  Stack *pStack = &p->aStack[i];
          817  +  char **pzStack = &p->zStack[i];
          818  +  char *z;
          819  +  assert( (pStack->flags & STK_Ephem)!=0 );
          820  +  z = sqliteMalloc( pStack->n );
          821  +  if( z==0 ) return 1;
          822  +  memcpy(z, *pzStack, pStack->n);
          823  +  *pzStack = z;
          824  +  return 0;
          825  +}
   800    826   
   801    827   /*
   802    828   ** Release the memory associated with the given stack level
   803    829   */
   804    830   #define Release(P,I)  if((P)->aStack[I].flags&STK_Dyn){ hardRelease(P,I); }
   805    831   static void hardRelease(Vdbe *p, int i){
   806    832     sqliteFree(p->zStack[i]);
   807    833     p->zStack[i] = 0;
   808         -  p->aStack[i].flags &= ~(STK_Str|STK_Dyn|STK_Static);
          834  +  p->aStack[i].flags &= ~(STK_Str|STK_Dyn|STK_Static|STK_Ephem);
   809    835   }
   810    836   
   811    837   /*
   812    838   ** Convert the given stack entity into a integer if it isn't one
   813    839   ** already.
   814    840   **
   815    841   ** Any prior string or real representation is invalidated.  
................................................................................
  1573   1599   case OP_Dup: {
  1574   1600     int i = p->tos - pOp->p1;
  1575   1601     int j = ++p->tos;
  1576   1602     VERIFY( if( i<0 ) goto not_enough_stack; )
  1577   1603     VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; )
  1578   1604     memcpy(&aStack[j], &aStack[i], sizeof(aStack[i])-NBFS);
  1579   1605     if( aStack[j].flags & STK_Str ){
  1580         -    if( pOp->p2 || (aStack[j].flags & STK_Static)!=0 ){
         1606  +    int isStatic = (aStack[j].flags & STK_Static)!=0;
         1607  +    if( pOp->p2 || isStatic ){
  1581   1608         zStack[j] = zStack[i];
  1582   1609         aStack[j].flags &= ~STK_Dyn;
         1610  +      if( !isStatic ) aStack[j].flags |= STK_Ephem;
  1583   1611       }else if( aStack[i].n<=NBFS ){
  1584   1612         memcpy(aStack[j].z, zStack[i], aStack[j].n);
  1585   1613         zStack[j] = aStack[j].z;
  1586         -      aStack[j].flags &= ~(STK_Static|STK_Dyn);
         1614  +      aStack[j].flags &= ~(STK_Static|STK_Dyn|STK_Ephem);
  1587   1615       }else{
  1588   1616         zStack[j] = sqliteMalloc( aStack[j].n );
  1589   1617         if( zStack[j]==0 ) goto no_mem;
  1590   1618         memcpy(zStack[j], zStack[i], aStack[j].n);
  1591         -      aStack[j].flags &= ~STK_Static;
         1619  +      aStack[j].flags &= ~(STK_Static|STK_Ephem);
         1620  +      aStack[j].flags |= STK_Dyn;
  1592   1621       }
  1593   1622     }
  1594   1623     break;
  1595   1624   }
  1596   1625   
  1597   1626   /* Opcode: Pull P1 * *
  1598   1627   **
................................................................................
  1609   1638     int to = p->tos;
  1610   1639     int i;
  1611   1640     Stack ts;
  1612   1641     char *tz;
  1613   1642     VERIFY( if( from<0 ) goto not_enough_stack; )
  1614   1643     ts = aStack[from];
  1615   1644     tz = zStack[from];
         1645  +  Deephemeralize(p, to);
  1616   1646     for(i=from; i<to; i++){
         1647  +    Deephemeralize(p, i);
  1617   1648       aStack[i] = aStack[i+1];
         1649  +    assert( (aStack[i].flags & STK_Ephem)==0 );
  1618   1650       if( aStack[i].flags & (STK_Dyn|STK_Static) ){
  1619   1651         zStack[i] = zStack[i+1];
  1620   1652       }else{
  1621   1653         zStack[i] = aStack[i].z;
  1622   1654       }
  1623   1655     }
  1624   1656     aStack[to] = ts;
         1657  +  assert( (aStack[to].flags & STK_Ephem)==0 );
  1625   1658     if( aStack[to].flags & (STK_Dyn|STK_Static) ){
  1626   1659       zStack[to] = tz;
  1627   1660     }else{
  1628   1661       zStack[to] = aStack[to].z;
  1629   1662     }
  1630   1663     break;
  1631   1664   }
................................................................................
  1640   1673     int from = p->tos;
  1641   1674     int to = p->tos - pOp->p1;
  1642   1675   
  1643   1676     VERIFY( if( to<0 ) goto not_enough_stack; )
  1644   1677     if( aStack[to].flags & STK_Dyn ){
  1645   1678       sqliteFree(zStack[to]);
  1646   1679     }
         1680  +  Deephemeralize(p, from);
  1647   1681     aStack[to] = aStack[from];
  1648         -  if( aStack[to].flags & (STK_Dyn|STK_Static) ){
         1682  +  if( aStack[to].flags & (STK_Dyn|STK_Static|STK_Ephem) ){
  1649   1683       zStack[to] = zStack[from];
  1650   1684     }else{
  1651   1685       zStack[to] = aStack[to].z;
  1652   1686     }
  1653         -  aStack[from].flags &= ~STK_Dyn;
         1687  +  aStack[from].flags = 0;
  1654   1688     p->tos--;
  1655   1689     break;
  1656   1690   }
  1657   1691   
  1658   1692   /* Opcode: ColumnCount P1 * *
  1659   1693   **
  1660   1694   ** Specify the number of column values that will appear in the
................................................................................
  2892   2926   ** the key itself.
  2893   2927   */
  2894   2928   case OP_IncrKey: {
  2895   2929     int tos = p->tos;
  2896   2930   
  2897   2931     VERIFY( if( tos<0 ) goto bad_instruction );
  2898   2932     if( Stringify(p, tos) ) goto no_mem;
  2899         -  if( aStack[tos].flags & STK_Static ){
         2933  +  if( aStack[tos].flags & (STK_Static|STK_Ephem) ){
  2900   2934       /* CANT HAPPEN.  The IncrKey opcode is only applied to keys
  2901   2935       ** generated by MakeKey or MakeIdxKey and the results of those
  2902   2936       ** operands are always dynamic strings.
  2903   2937       */
  2904   2938       goto abort_due_to_error;
  2905   2939     }
  2906   2940     zStack[tos][aStack[tos].n-1]++;
................................................................................
  3802   3836   
  3803   3837     /* amt and offset now hold the offset to the start of data and the
  3804   3838     ** amount of data.  Go get the data and put it on the stack.
  3805   3839     */
  3806   3840     if( amt==0 ){
  3807   3841       aStack[tos].flags = STK_Null;
  3808   3842     }else if( zRec ){
  3809         -    aStack[tos].flags = STK_Str | STK_Static;
         3843  +    aStack[tos].flags = STK_Str | STK_Ephem;
  3810   3844       aStack[tos].n = amt;
  3811   3845       zStack[tos] = &zRec[offset];
  3812   3846     }else{
  3813   3847       if( amt<=NBFS ){
  3814   3848         aStack[tos].flags = STK_Str;
  3815   3849         zStack[tos] = aStack[tos].z;
  3816   3850         aStack[tos].n = amt;
................................................................................
  4766   4800   ** the original data remains on the stack.
  4767   4801   */
  4768   4802   case OP_MemStore: {
  4769   4803     int i = pOp->p1;
  4770   4804     int tos = p->tos;
  4771   4805     char *zOld;
  4772   4806     Mem *pMem;
         4807  +  int flags;
  4773   4808     VERIFY( if( tos<0 ) goto not_enough_stack; )
  4774   4809     if( i>=p->nMem ){
  4775   4810       int nOld = p->nMem;
  4776   4811       Mem *aMem;
  4777   4812       p->nMem = i + 5;
  4778   4813       aMem = sqliteRealloc(p->aMem, p->nMem*sizeof(p->aMem[0]));
  4779   4814       if( aMem==0 ) goto no_mem;
................................................................................
  4787   4822       }
  4788   4823       p->aMem = aMem;
  4789   4824       if( nOld<p->nMem ){
  4790   4825         memset(&p->aMem[nOld], 0, sizeof(p->aMem[0])*(p->nMem-nOld));
  4791   4826       }
  4792   4827     }
  4793   4828     pMem = &p->aMem[i];
  4794         -  if( pMem->s.flags & STK_Dyn ){
         4829  +  flags = pMem->s.flags;
         4830  +  if( flags & STK_Dyn ){
  4795   4831       zOld = pMem->z;
  4796   4832     }else{
  4797   4833       zOld = 0;
  4798   4834     }
  4799   4835     pMem->s = aStack[tos];
  4800         -  if( pMem->s.flags & (STK_Static|STK_Dyn) ){
  4801         -    if( pOp->p2==0 && (pMem->s.flags & STK_Dyn)!=0 ){
         4836  +  flags = pMem->s.flags;
         4837  +  if( flags & (STK_Static|STK_Dyn|STK_Ephem) ){
         4838  +    if( (flags & STK_Static)!=0 || (pOp->p2 && (flags & STK_Dyn)!=0) ){
         4839  +      pMem->z = zStack[tos];
         4840  +    }else if( flags & STK_Str ){
  4802   4841         pMem->z = sqliteMalloc( pMem->s.n );
  4803   4842         if( pMem->z==0 ) goto no_mem;
  4804   4843         memcpy(pMem->z, zStack[tos], pMem->s.n);
  4805         -    }else{
  4806         -      pMem->z = zStack[tos];
         4844  +      pMem->s.flags |= STK_Dyn;
         4845  +      pMem->s.flags &= ~(STK_Static|STK_Ephem);
  4807   4846       }
  4808   4847     }else{
  4809   4848       pMem->z = pMem->s.z;
  4810   4849     }
  4811   4850     if( zOld ) sqliteFree(zOld);
  4812   4851     if( pOp->p2 ){
  4813   4852       zStack[tos] = 0;
................................................................................
  4830   4869     int tos = ++p->tos;
  4831   4870     int i = pOp->p1;
  4832   4871     VERIFY( if( NeedStack(p, tos) ) goto no_mem; )
  4833   4872     VERIFY( if( i<0 || i>=p->nMem ) goto bad_instruction; )
  4834   4873     memcpy(&aStack[tos], &p->aMem[i].s, sizeof(aStack[tos])-NBFS);;
  4835   4874     if( aStack[tos].flags & STK_Str ){
  4836   4875       zStack[tos] = p->aMem[i].z;
  4837         -    aStack[tos].flags |= STK_Static;
         4876  +    aStack[tos].flags |= STK_Ephem;
  4838   4877       aStack[tos].flags &= ~STK_Dyn;
  4839   4878     }
  4840   4879     break;
  4841   4880   }
  4842   4881   
  4843   4882   /* Opcode: MemIncr P1 P2 *
  4844   4883   **
................................................................................
  4984   5023       Mem *pMem = &pFocus->aMem[i];
  4985   5024       char *zOld;
  4986   5025       if( pMem->s.flags & STK_Dyn ){
  4987   5026         zOld = pMem->z;
  4988   5027       }else{
  4989   5028         zOld = 0;
  4990   5029       }
         5030  +    Deephemeralize(p, tos);
  4991   5031       pMem->s = aStack[tos];
  4992   5032       if( pMem->s.flags & STK_Dyn ){
  4993   5033         pMem->z = zStack[tos];
  4994   5034         zStack[tos] = 0;
  4995   5035         aStack[tos].flags = 0;
  4996   5036       }else if( pMem->s.flags & (STK_Static|STK_AggCtx) ){
  4997   5037         pMem->z = zStack[tos];
................................................................................
  5017   5057     VERIFY( if( NeedStack(p, tos) ) goto no_mem; )
  5018   5058     if( pFocus==0 ) goto no_mem;
  5019   5059     if( VERIFY( i>=0 && ) i<p->agg.nMem ){
  5020   5060       Mem *pMem = &pFocus->aMem[i];
  5021   5061       aStack[tos] = pMem->s;
  5022   5062       zStack[tos] = pMem->z;
  5023   5063       aStack[tos].flags &= ~STK_Dyn;
         5064  +    aStack[tos].flags |= STK_Ephem;
  5024   5065     }
  5025   5066     break;
  5026   5067   }
  5027   5068   
  5028   5069   /* Opcode: AggNext * P2 *
  5029   5070   **
  5030   5071   ** Make the next aggregate value the current aggregate.  The prior
................................................................................
  5066   5107         (*p->agg.apFunc[i]->xFinalize)(&ctx);
  5067   5108         if( freeCtx ){
  5068   5109           sqliteFree( aMem[i].z );
  5069   5110         }
  5070   5111         aMem[i].s = ctx.s;
  5071   5112         aMem[i].z = ctx.z;
  5072   5113         if( (aMem[i].s.flags & STK_Str) &&
  5073         -              (aMem[i].s.flags & (STK_Dyn|STK_Static))==0 ){
         5114  +              (aMem[i].s.flags & (STK_Dyn|STK_Static|STK_Ephem))==0 ){
  5074   5115           aMem[i].z = aMem[i].s.z;
  5075   5116         }
  5076   5117         nErr += ctx.isError;
  5077   5118       }
  5078   5119     }
  5079   5120     break;
  5080   5121   }
................................................................................
  5181   5222         pc = pOp->p2 - 1;
  5182   5223       }
  5183   5224     }
  5184   5225     tos = ++p->tos;
  5185   5226     VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; )
  5186   5227     zStack[tos] = sqliteHashKey(pSet->prev);
  5187   5228     aStack[tos].n = sqliteHashKeysize(pSet->prev);
  5188         -  aStack[tos].flags = STK_Str | STK_Static;
         5229  +  aStack[tos].flags = STK_Str | STK_Ephem;
  5189   5230     break;
  5190   5231   }
  5191   5232   
  5192   5233   /* An other opcode is illegal...
  5193   5234   */
  5194   5235   default: {
  5195   5236     sprintf(zBuf,"%d",pOp->opcode);
................................................................................
  5230   5271             fprintf(p->trace, " r:%g", aStack[i].r);
  5231   5272           }else if( aStack[i].flags & STK_Str ){
  5232   5273             int j, k;
  5233   5274             char zBuf[100];
  5234   5275             zBuf[0] = ' ';
  5235   5276             if( aStack[i].flags & STK_Dyn ){
  5236   5277               zBuf[1] = 'z';
         5278  +            assert( (aStack[i].flags & (STK_Static|STK_Ephem))==0 );
  5237   5279             }else if( aStack[i].flags & STK_Static ){
  5238   5280               zBuf[1] = 't';
         5281  +            assert( (aStack[i].flags & (STK_Dyn|STK_Ephem))==0 );
         5282  +          }else if( aStack[i].flags & STK_Ephem ){
         5283  +            zBuf[1] = 'e';
         5284  +            assert( (aStack[i].flags & (STK_Static|STK_Dyn))==0 );
  5239   5285             }else{
  5240   5286               zBuf[1] = 's';
  5241   5287             }
  5242   5288             zBuf[2] = '[';
  5243   5289             k = 3;
  5244   5290             for(j=0; j<20 && j<aStack[i].n; j++){
  5245   5291               int c = zStack[i][j];