/ Check-in [da627325]
Login

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

Overview
Comment:The {quote: SrcList} object was not being expanded correctly by a call to sqliteSrcListAppend() if the {quote: SrcList} had previously been duplicated by a call to sqliteSrcListDup(). Ticket #416. This check-in fixes that problem by keeping a separate nAlloc field on {quote: SrcList}. A similar change is made to {quote: IdList} and {quote: ExprList} to avoid future problems. (CVS 1067)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: da6273255471673841fdcadc688aeac80722e130
User & Date: drh 2003-07-30 12:34:12
Context
2003-08-05
13:13
Provide a more informative error message when a uniqueness constraint fails. Ticket #419. (CVS 1068) check-in: 086aa1c9 user: drh tags: trunk
2003-07-30
12:34
The {quote: SrcList} object was not being expanded correctly by a call to sqliteSrcListAppend() if the {quote: SrcList} had previously been duplicated by a call to sqliteSrcListDup(). Ticket #416. This check-in fixes that problem by keeping a separate nAlloc field on {quote: SrcList}. A similar change is made to {quote: IdList} and {quote: ExprList} to avoid future problems. (CVS 1067) check-in: da627325 user: drh tags: trunk
2003-07-27
18:59
When creating a new journal file, open a (read-only) file descriptor on the directory containing the journal and sync that directory once to make sure that the journal filename entry gets into the directory. Ticket #410. (CVS 1066) check-in: 09c10fe3 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/build.c.

    19     19   **     DROP INDEX
    20     20   **     creating ID lists
    21     21   **     BEGIN TRANSACTION
    22     22   **     COMMIT
    23     23   **     ROLLBACK
    24     24   **     PRAGMA
    25     25   **
    26         -** $Id: build.c,v 1.156 2003/07/01 18:13:15 drh Exp $
           26  +** $Id: build.c,v 1.157 2003/07/30 12:34:12 drh Exp $
    27     27   */
    28     28   #include "sqliteInt.h"
    29     29   #include <ctype.h>
    30     30   
    31     31   /*
    32     32   ** This routine is called when a new SQL statement is beginning to
    33     33   ** be parsed.  Check to see if the schema for the database needs
................................................................................
  1907   1907   **
  1908   1908   ** A new IdList is returned, or NULL if malloc() fails.
  1909   1909   */
  1910   1910   IdList *sqliteIdListAppend(IdList *pList, Token *pToken){
  1911   1911     if( pList==0 ){
  1912   1912       pList = sqliteMalloc( sizeof(IdList) );
  1913   1913       if( pList==0 ) return 0;
         1914  +    pList->nAlloc = 0;
  1914   1915     }
  1915         -  if( (pList->nId & 7)==0 ){
         1916  +  if( pList->nId>=pList->nAlloc ){
  1916   1917       struct IdList_item *a;
  1917         -    a = sqliteRealloc(pList->a, (pList->nId+8)*sizeof(pList->a[0]) );
         1918  +    pList->nAlloc = pList->nAlloc*2 + 5;
         1919  +    a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0]) );
  1918   1920       if( a==0 ){
  1919   1921         sqliteIdListDelete(pList);
  1920   1922         return 0;
  1921   1923       }
  1922   1924       pList->a = a;
  1923   1925     }
  1924   1926     memset(&pList->a[pList->nId], 0, sizeof(pList->a[0]));
................................................................................
  1961   1963   **
  1962   1964   ** Then C is the table name and B is the database name.
  1963   1965   */
  1964   1966   SrcList *sqliteSrcListAppend(SrcList *pList, Token *pTable, Token *pDatabase){
  1965   1967     if( pList==0 ){
  1966   1968       pList = sqliteMalloc( sizeof(SrcList) );
  1967   1969       if( pList==0 ) return 0;
         1970  +    pList->nAlloc = 1;
  1968   1971     }
  1969         -  if( (pList->nSrc & 7)==1 ){
         1972  +  if( pList->nSrc>=pList->nAlloc ){
  1970   1973       SrcList *pNew;
         1974  +    pList->nAlloc *= 2;
  1971   1975       pNew = sqliteRealloc(pList,
  1972         -               sizeof(*pList) + (pList->nSrc+8)*sizeof(pList->a[0]) );
         1976  +               sizeof(*pList) + (pList->nAlloc-1)*sizeof(pList->a[0]) );
  1973   1977       if( pNew==0 ){
  1974   1978         sqliteSrcListDelete(pList);
  1975   1979         return 0;
  1976   1980       }
  1977   1981       pList = pNew;
  1978   1982     }
  1979   1983     memset(&pList->a[pList->nSrc], 0, sizeof(pList->a[0]));

Changes to src/expr.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains routines used for analyzing expressions and
    13     13   ** for generating VDBE code that evaluates expressions in SQLite.
    14     14   **
    15         -** $Id: expr.c,v 1.97 2003/07/20 01:16:47 drh Exp $
           15  +** $Id: expr.c,v 1.98 2003/07/30 12:34:12 drh Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   #include <ctype.h>
    19     19   
    20     20   /*
    21     21   ** Construct a new expression node and return a pointer to it.  Memory
    22     22   ** for this node is obtained from sqliteMalloc().  The calling function
................................................................................
   156    156   }
   157    157   ExprList *sqliteExprListDup(ExprList *p){
   158    158     ExprList *pNew;
   159    159     int i;
   160    160     if( p==0 ) return 0;
   161    161     pNew = sqliteMalloc( sizeof(*pNew) );
   162    162     if( pNew==0 ) return 0;
   163         -  pNew->nExpr = p->nExpr;
          163  +  pNew->nExpr = pNew->nAlloc = p->nExpr;
   164    164     pNew->a = sqliteMalloc( p->nExpr*sizeof(p->a[0]) );
   165    165     if( pNew->a==0 ) return 0;
   166    166     for(i=0; i<p->nExpr; i++){
   167    167       Expr *pNewExpr, *pOldExpr;
   168    168       pNew->a[i].pExpr = pNewExpr = sqliteExprDup(pOldExpr = p->a[i].pExpr);
   169    169       if( pOldExpr->span.z!=0 && pNewExpr ){
   170    170         /* Always make a copy of the span for top-level expressions in the
................................................................................
   185    185     SrcList *pNew;
   186    186     int i;
   187    187     int nByte;
   188    188     if( p==0 ) return 0;
   189    189     nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0);
   190    190     pNew = sqliteMalloc( nByte );
   191    191     if( pNew==0 ) return 0;
   192         -  pNew->nSrc = p->nSrc;
          192  +  pNew->nSrc = pNew->nAlloc = p->nSrc;
   193    193     for(i=0; i<p->nSrc; i++){
   194    194       pNew->a[i].zDatabase = sqliteStrDup(p->a[i].zDatabase);
   195    195       pNew->a[i].zName = sqliteStrDup(p->a[i].zName);
   196    196       pNew->a[i].zAlias = sqliteStrDup(p->a[i].zAlias);
   197    197       pNew->a[i].jointype = p->a[i].jointype;
   198    198       pNew->a[i].iCursor = p->a[i].iCursor;
   199    199       pNew->a[i].pTab = 0;
................................................................................
   205    205   }
   206    206   IdList *sqliteIdListDup(IdList *p){
   207    207     IdList *pNew;
   208    208     int i;
   209    209     if( p==0 ) return 0;
   210    210     pNew = sqliteMalloc( sizeof(*pNew) );
   211    211     if( pNew==0 ) return 0;
   212         -  pNew->nId = p->nId;
          212  +  pNew->nId = pNew->nAlloc = p->nId;
   213    213     pNew->a = sqliteMalloc( p->nId*sizeof(p->a[0]) );
   214    214     if( pNew->a==0 ) return 0;
   215    215     for(i=0; i<p->nId; i++){
   216    216       pNew->a[i].zName = sqliteStrDup(p->a[i].zName);
   217    217       pNew->a[i].idx = p->a[i].idx;
   218    218     }
   219    219     return pNew;
................................................................................
   249    249     int i;
   250    250     if( pList==0 ){
   251    251       pList = sqliteMalloc( sizeof(ExprList) );
   252    252       if( pList==0 ){
   253    253         sqliteExprDelete(pExpr);
   254    254         return 0;
   255    255       }
          256  +    pList->nAlloc = 0;
   256    257     }
   257         -  if( (pList->nExpr & 7)==0 ){
   258         -    int n = pList->nExpr + 8;
          258  +  if( pList->nAlloc<=pList->nExpr ){
   259    259       struct ExprList_item *a;
   260         -    a = sqliteRealloc(pList->a, n*sizeof(pList->a[0]));
          260  +    pList->nAlloc = pList->nAlloc*2 + 4;
          261  +    a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0]));
   261    262       if( a==0 ){
   262    263         sqliteExprDelete(pExpr);
   263    264         return pList;
   264    265       }
   265    266       pList->a = a;
   266    267     }
   267    268     if( pExpr || pName ){

Changes to src/sqliteInt.h.

     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** Internal interface definitions for SQLite.
    13     13   **
    14         -** @(#) $Id: sqliteInt.h,v 1.194 2003/07/20 01:16:47 drh Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.195 2003/07/30 12:34:12 drh Exp $
    15     15   */
    16     16   #include "config.h"
    17     17   #include "sqlite.h"
    18     18   #include "hash.h"
    19     19   #include "vdbe.h"
    20     20   #include "parse.h"
    21     21   #include "btree.h"
................................................................................
   649    649   ** as the list of "expr AS ID" fields following a "SELECT" or in the
   650    650   ** list of "ID = expr" items in an UPDATE.  A list of expressions can
   651    651   ** also be used as the argument to a function, in which case the a.zName
   652    652   ** field is not used.
   653    653   */
   654    654   struct ExprList {
   655    655     int nExpr;             /* Number of expressions on the list */
          656  +  int nAlloc;            /* Number of entries allocated below */
   656    657     struct ExprList_item {
   657    658       Expr *pExpr;           /* The list of expressions */
   658    659       char *zName;           /* Token associated with this expression */
   659    660       u8 sortOrder;          /* 1 for DESC or 0 for ASC */
   660    661       u8 isAgg;              /* True if this is an aggregate like count(*) */
   661    662       u8 done;               /* A flag to indicate when processing is finished */
   662    663     } *a;                  /* One entry for each expression */
................................................................................
   675    676   **
   676    677   **     INSERT INTO t(a,b,c) ...
   677    678   **
   678    679   ** If "a" is the k-th column of table "t", then IdList.a[0].idx==k.
   679    680   */
   680    681   struct IdList {
   681    682     int nId;         /* Number of identifiers on the list */
          683  +  int nAlloc;      /* Number of entries allocated for a[] below */
   682    684     struct IdList_item {
   683    685       char *zName;      /* Name of the identifier */
   684    686       int idx;          /* Index in some Table.aCol[] of a column named zName */
   685    687     } *a;
   686    688   };
   687    689   
   688    690   /*
................................................................................
   693    695   ** With the addition of multiple database support, the following structure
   694    696   ** can also be used to describe a particular table such as the table that
   695    697   ** is modified by an INSERT, DELETE, or UPDATE statement.  In standard SQL,
   696    698   ** such a table must be a simple name: ID.  But in SQLite, the table can
   697    699   ** now be identified by a database name, a dot, then the table name: ID.ID.
   698    700   */
   699    701   struct SrcList {
   700         -  int nSrc;        /* Number of tables or subqueries in the FROM clause */
          702  +  u16 nSrc;        /* Number of tables or subqueries in the FROM clause */
          703  +  u16 nAlloc;      /* Number of entries allocated in a[] below */
   701    704     struct SrcList_item {
   702    705       char *zDatabase;  /* Name of database holding this table */
   703    706       char *zName;      /* Name of the table */
   704    707       char *zAlias;     /* The "B" part of a "A AS B" phrase.  zName is the "A" */
   705    708       Table *pTab;      /* An SQL table corresponding to zName */
   706    709       Select *pSelect;  /* A SELECT statement used in place of a table name */
   707    710       int jointype;     /* Type of join between this table and the next */

Changes to src/util.c.

    10     10   **
    11     11   *************************************************************************
    12     12   ** Utility functions used throughout sqlite.
    13     13   **
    14     14   ** This file contains functions for allocating memory, comparing
    15     15   ** strings, and stuff like that.
    16     16   **
    17         -** $Id: util.c,v 1.65 2003/06/05 14:27:56 drh Exp $
           17  +** $Id: util.c,v 1.66 2003/07/30 12:34:12 drh Exp $
    18     18   */
    19     19   #include "sqliteInt.h"
    20     20   #include <stdarg.h>
    21     21   #include <ctype.h>
    22     22   
    23     23   /*
    24     24   ** If malloc() ever fails, this global variable gets set to 1.
................................................................................
    39     39   int sqlite_nMalloc;         /* Number of sqliteMalloc() calls */
    40     40   int sqlite_nFree;           /* Number of sqliteFree() calls */
    41     41   int sqlite_iMallocFail;     /* Fail sqliteMalloc() after this many calls */
    42     42   #if MEMORY_DEBUG>1
    43     43   static int memcnt = 0;
    44     44   #endif
    45     45   
           46  +/*
           47  +** Number of 32-bit guard words
           48  +*/
           49  +#define N_GUARD 1
    46     50   
    47     51   /*
    48     52   ** Allocate new memory and set it to zero.  Return NULL if
    49     53   ** no memory is available.
    50     54   */
    51     55   void *sqliteMalloc_(int n, int bZero, char *zFile, int line){
    52     56     void *p;
    53     57     int *pi;
    54         -  int k;
           58  +  int i, k;
    55     59     if( sqlite_iMallocFail>=0 ){
    56     60       sqlite_iMallocFail--;
    57     61       if( sqlite_iMallocFail==0 ){
    58     62         sqlite_malloc_failed++;
    59     63   #if MEMORY_DEBUG>1
    60     64         fprintf(stderr,"**** failed to allocate %d bytes at %s:%d\n",
    61     65                 n, zFile,line);
................................................................................
    62     66   #endif
    63     67         sqlite_iMallocFail--;
    64     68         return 0;
    65     69       }
    66     70     }
    67     71     if( n==0 ) return 0;
    68     72     k = (n+sizeof(int)-1)/sizeof(int);
    69         -  pi = malloc( (3+k)*sizeof(int));
           73  +  pi = malloc( (N_GUARD*2+1+k)*sizeof(int));
    70     74     if( pi==0 ){
    71     75       sqlite_malloc_failed++;
    72     76       return 0;
    73     77     }
    74     78     sqlite_nMalloc++;
    75         -  pi[0] = 0xdead1122;
    76         -  pi[1] = n;
    77         -  pi[k+2] = 0xdead3344;
    78         -  p = &pi[2];
           79  +  for(i=0; i<N_GUARD; i++) pi[i] = 0xdead1122;
           80  +  pi[N_GUARD] = n;
           81  +  for(i=0; i<N_GUARD; i++) pi[k+1+N_GUARD+i] = 0xdead3344;
           82  +  p = &pi[N_GUARD+1];
    79     83     memset(p, bZero==0, n);
    80     84   #if MEMORY_DEBUG>1
    81     85     fprintf(stderr,"%06d malloc %d bytes at 0x%x from %s:%d\n",
    82     86         ++memcnt, n, (int)p, zFile,line);
    83     87   #endif
    84     88     return p;
    85     89   }
................................................................................
    89     93   ** and is able to hold at least N bytes.  Raise an exception if this
    90     94   ** is not the case.
    91     95   **
    92     96   ** This routine is used for testing purposes only.
    93     97   */
    94     98   void sqliteCheckMemory(void *p, int N){
    95     99     int *pi = p;
    96         -  int n, k;
    97         -  pi -= 2;
    98         -  assert( pi[0]==0xdead1122 );
    99         -  n = pi[1];
          100  +  int n, i, k;
          101  +  pi -= N_GUARD+1;
          102  +  for(i=0; i<N_GUARD; i++){
          103  +    assert( pi[i]==0xdead1122 );
          104  +  }
          105  +  n = pi[N_GUARD];
   100    106     assert( N>=0 && N<n );
   101    107     k = (n+sizeof(int)-1)/sizeof(int);
   102         -  assert( pi[k+2]==0xdead3344 );
          108  +  for(i=0; i<N_GUARD; i++){
          109  +    assert( pi[k+N_GUARD+1+i]==0xdead3344 );
          110  +  }
   103    111   }
   104    112   
   105    113   /*
   106    114   ** Free memory previously obtained from sqliteMalloc()
   107    115   */
   108    116   void sqliteFree_(void *p, char *zFile, int line){
   109    117     if( p ){
   110         -    int *pi, k, n;
          118  +    int *pi, i, k, n;
   111    119       pi = p;
   112         -    pi -= 2;
          120  +    pi -= N_GUARD+1;
   113    121       sqlite_nFree++;
   114         -    if( pi[0]!=0xdead1122 ){
   115         -      fprintf(stderr,"Low-end memory corruption at 0x%x\n", (int)p);
   116         -      return;
          122  +    for(i=0; i<N_GUARD; i++){
          123  +      if( pi[i]!=0xdead1122 ){
          124  +        fprintf(stderr,"Low-end memory corruption at 0x%x\n", (int)p);
          125  +        return;
          126  +      }
   117    127       }
   118         -    n = pi[1];
          128  +    n = pi[N_GUARD];
   119    129       k = (n+sizeof(int)-1)/sizeof(int);
   120         -    if( pi[k+2]!=0xdead3344 ){
   121         -      fprintf(stderr,"High-end memory corruption at 0x%x\n", (int)p);
   122         -      return;
          130  +    for(i=0; i<N_GUARD; i++){
          131  +      if( pi[k+N_GUARD+1+i]!=0xdead3344 ){
          132  +        fprintf(stderr,"High-end memory corruption at 0x%x\n", (int)p);
          133  +        return;
          134  +      }
   123    135       }
   124         -    memset(pi, 0xff, (k+3)*sizeof(int));
          136  +    memset(pi, 0xff, (k+N_GUARD*2+1)*sizeof(int));
   125    137   #if MEMORY_DEBUG>1
   126    138       fprintf(stderr,"%06d free %d bytes at 0x%x from %s:%d\n",
   127    139            ++memcnt, n, (int)p, zFile,line);
   128    140   #endif
   129    141       free(pi);
   130    142     }
   131    143   }
................................................................................
   132    144   
   133    145   /*
   134    146   ** Resize a prior allocation.  If p==0, then this routine
   135    147   ** works just like sqliteMalloc().  If n==0, then this routine
   136    148   ** works just like sqliteFree().
   137    149   */
   138    150   void *sqliteRealloc_(void *oldP, int n, char *zFile, int line){
   139         -  int *oldPi, *pi, k, oldN, oldK;
          151  +  int *oldPi, *pi, i, k, oldN, oldK;
   140    152     void *p;
   141    153     if( oldP==0 ){
   142    154       return sqliteMalloc_(n,1,zFile,line);
   143    155     }
   144    156     if( n==0 ){
   145    157       sqliteFree_(oldP,zFile,line);
   146    158       return 0;
   147    159     }
   148    160     oldPi = oldP;
   149         -  oldPi -= 2;
          161  +  oldPi -= N_GUARD+1;
   150    162     if( oldPi[0]!=0xdead1122 ){
   151    163       fprintf(stderr,"Low-end memory corruption in realloc at 0x%x\n", (int)p);
   152    164       return 0;
   153    165     }
   154         -  oldN = oldPi[1];
          166  +  oldN = oldPi[N_GUARD];
   155    167     oldK = (oldN+sizeof(int)-1)/sizeof(int);
   156         -  if( oldPi[oldK+2]!=0xdead3344 ){
   157         -    fprintf(stderr,"High-end memory corruption in realloc at 0x%x\n", (int)p);
   158         -    return 0;
          168  +  for(i=0; i<N_GUARD; i++){
          169  +    if( oldPi[oldK+N_GUARD+1+i]!=0xdead3344 ){
          170  +      fprintf(stderr,"High-end memory corruption in realloc at 0x%x\n", (int)p);
          171  +      return 0;
          172  +    }
   159    173     }
   160    174     k = (n + sizeof(int) - 1)/sizeof(int);
   161         -  pi = malloc( (k+3)*sizeof(int) );
          175  +  pi = malloc( (k+N_GUARD*2+1)*sizeof(int) );
   162    176     if( pi==0 ){
   163    177       sqlite_malloc_failed++;
   164    178       return 0;
   165    179     }
   166         -  pi[0] = 0xdead1122;
   167         -  pi[1] = n;
   168         -  pi[k+2] = 0xdead3344;
   169         -  p = &pi[2];
          180  +  for(i=0; i<N_GUARD; i++) pi[i] = 0xdead1122;
          181  +  pi[N_GUARD] = n;
          182  +  for(i=0; i<N_GUARD; i++) pi[k+N_GUARD+1+i] = 0xdead3344;
          183  +  p = &pi[N_GUARD+1];
   170    184     memcpy(p, oldP, n>oldN ? oldN : n);
   171    185     if( n>oldN ){
   172    186       memset(&((char*)p)[oldN], 0, n-oldN);
   173    187     }
   174         -  memset(oldPi, 0xab, (oldK+3)*sizeof(int));
          188  +  memset(oldPi, 0xab, (oldK+N_GUARD+2)*sizeof(int));
   175    189     free(oldPi);
   176    190   #if MEMORY_DEBUG>1
   177    191     fprintf(stderr,"%06d realloc %d to %d bytes at 0x%x to 0x%x at %s:%d\n",
   178    192       ++memcnt, oldN, n, (int)oldP, (int)p, zFile, line);
   179    193   #endif
   180    194     return p;
   181    195   }

Changes to test/misc2.test.

     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.
    12     12   #
    13     13   # This file implements tests for miscellanous features that were
    14     14   # left out of other test files.
    15     15   #
    16         -# $Id: misc2.test,v 1.5 2003/07/27 17:16:08 drh Exp $
           16  +# $Id: misc2.test,v 1.6 2003/07/30 12:34:13 drh Exp $
    17     17   
    18     18   set testdir [file dirname $argv0]
    19     19   source $testdir/tester.tcl
    20     20   
    21     21   # Test for ticket #360
    22     22   #
    23     23   do_test misc2-1.1 {
................................................................................
    94     94     }
    95     95   } {1 4000000000 2147483648 2147483647}
    96     96   do_test misc2-4.6 {
    97     97     execsql {
    98     98       SELECT a FROM t1 WHERE a<1000000000000 ORDER BY 1;
    99     99     }
   100    100   } {1 2147483647 2147483648 4000000000}
          101  +
          102  +# There were some issues with expanding a SrcList object using a call
          103  +# to sqliteSrcListAppend() if the SrcList had previously been duplicated
          104  +# using a call to sqliteSrcListDup().  Ticket #416.  The following test
          105  +# makes sure the problem has been fixed.
          106  +#
          107  +do_test misc2-5.1 {
          108  +  execsql {
          109  +    CREATE TABLE x(a,b);
          110  +    CREATE VIEW y AS 
          111  +      SELECT x1.b AS p, x2.b AS q FROM x AS x1, x AS x2 WHERE x1.a=x2.a;
          112  +    CREATE VIEW z AS
          113  +      SELECT y1.p, y2.p FROM y AS y1, y AS y2 WHERE y1.q=y2.q;
          114  +    SELECT * from z;
          115  +  }
          116  +} {}