Index: src/build.c ================================================================== --- src/build.c +++ src/build.c @@ -21,11 +21,11 @@ ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** -** $Id: build.c,v 1.156 2003/07/01 18:13:15 drh Exp $ +** $Id: build.c,v 1.157 2003/07/30 12:34:12 drh Exp $ */ #include "sqliteInt.h" #include /* @@ -1909,14 +1909,16 @@ */ IdList *sqliteIdListAppend(IdList *pList, Token *pToken){ if( pList==0 ){ pList = sqliteMalloc( sizeof(IdList) ); if( pList==0 ) return 0; + pList->nAlloc = 0; } - if( (pList->nId & 7)==0 ){ + if( pList->nId>=pList->nAlloc ){ struct IdList_item *a; - a = sqliteRealloc(pList->a, (pList->nId+8)*sizeof(pList->a[0]) ); + pList->nAlloc = pList->nAlloc*2 + 5; + a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0]) ); if( a==0 ){ sqliteIdListDelete(pList); return 0; } pList->a = a; @@ -1963,15 +1965,17 @@ */ SrcList *sqliteSrcListAppend(SrcList *pList, Token *pTable, Token *pDatabase){ if( pList==0 ){ pList = sqliteMalloc( sizeof(SrcList) ); if( pList==0 ) return 0; + pList->nAlloc = 1; } - if( (pList->nSrc & 7)==1 ){ + if( pList->nSrc>=pList->nAlloc ){ SrcList *pNew; + pList->nAlloc *= 2; pNew = sqliteRealloc(pList, - sizeof(*pList) + (pList->nSrc+8)*sizeof(pList->a[0]) ); + sizeof(*pList) + (pList->nAlloc-1)*sizeof(pList->a[0]) ); if( pNew==0 ){ sqliteSrcListDelete(pList); return 0; } pList = pNew; Index: src/expr.c ================================================================== --- src/expr.c +++ src/expr.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.97 2003/07/20 01:16:47 drh Exp $ +** $Id: expr.c,v 1.98 2003/07/30 12:34:12 drh Exp $ */ #include "sqliteInt.h" #include /* @@ -158,11 +158,11 @@ ExprList *pNew; int i; if( p==0 ) return 0; pNew = sqliteMalloc( sizeof(*pNew) ); if( pNew==0 ) return 0; - pNew->nExpr = p->nExpr; + pNew->nExpr = pNew->nAlloc = p->nExpr; pNew->a = sqliteMalloc( p->nExpr*sizeof(p->a[0]) ); if( pNew->a==0 ) return 0; for(i=0; inExpr; i++){ Expr *pNewExpr, *pOldExpr; pNew->a[i].pExpr = pNewExpr = sqliteExprDup(pOldExpr = p->a[i].pExpr); @@ -187,11 +187,11 @@ int nByte; if( p==0 ) return 0; nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0); pNew = sqliteMalloc( nByte ); if( pNew==0 ) return 0; - pNew->nSrc = p->nSrc; + pNew->nSrc = pNew->nAlloc = p->nSrc; for(i=0; inSrc; i++){ pNew->a[i].zDatabase = sqliteStrDup(p->a[i].zDatabase); pNew->a[i].zName = sqliteStrDup(p->a[i].zName); pNew->a[i].zAlias = sqliteStrDup(p->a[i].zAlias); pNew->a[i].jointype = p->a[i].jointype; @@ -207,11 +207,11 @@ IdList *pNew; int i; if( p==0 ) return 0; pNew = sqliteMalloc( sizeof(*pNew) ); if( pNew==0 ) return 0; - pNew->nId = p->nId; + pNew->nId = pNew->nAlloc = p->nId; pNew->a = sqliteMalloc( p->nId*sizeof(p->a[0]) ); if( pNew->a==0 ) return 0; for(i=0; inId; i++){ pNew->a[i].zName = sqliteStrDup(p->a[i].zName); pNew->a[i].idx = p->a[i].idx; @@ -251,15 +251,16 @@ pList = sqliteMalloc( sizeof(ExprList) ); if( pList==0 ){ sqliteExprDelete(pExpr); return 0; } + pList->nAlloc = 0; } - if( (pList->nExpr & 7)==0 ){ - int n = pList->nExpr + 8; + if( pList->nAlloc<=pList->nExpr ){ struct ExprList_item *a; - a = sqliteRealloc(pList->a, n*sizeof(pList->a[0])); + pList->nAlloc = pList->nAlloc*2 + 4; + a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0])); if( a==0 ){ sqliteExprDelete(pExpr); return pList; } pList->a = a; Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -9,11 +9,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.194 2003/07/20 01:16:47 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.195 2003/07/30 12:34:12 drh Exp $ */ #include "config.h" #include "sqlite.h" #include "hash.h" #include "vdbe.h" @@ -651,10 +651,11 @@ ** also be used as the argument to a function, in which case the a.zName ** field is not used. */ struct ExprList { int nExpr; /* Number of expressions on the list */ + int nAlloc; /* Number of entries allocated below */ struct ExprList_item { Expr *pExpr; /* The list of expressions */ char *zName; /* Token associated with this expression */ u8 sortOrder; /* 1 for DESC or 0 for ASC */ u8 isAgg; /* True if this is an aggregate like count(*) */ @@ -677,10 +678,11 @@ ** ** If "a" is the k-th column of table "t", then IdList.a[0].idx==k. */ struct IdList { int nId; /* Number of identifiers on the list */ + int nAlloc; /* Number of entries allocated for a[] below */ struct IdList_item { char *zName; /* Name of the identifier */ int idx; /* Index in some Table.aCol[] of a column named zName */ } *a; }; @@ -695,11 +697,12 @@ ** is modified by an INSERT, DELETE, or UPDATE statement. In standard SQL, ** such a table must be a simple name: ID. But in SQLite, the table can ** now be identified by a database name, a dot, then the table name: ID.ID. */ struct SrcList { - int nSrc; /* Number of tables or subqueries in the FROM clause */ + u16 nSrc; /* Number of tables or subqueries in the FROM clause */ + u16 nAlloc; /* Number of entries allocated in a[] below */ struct SrcList_item { char *zDatabase; /* Name of database holding this table */ char *zName; /* Name of the table */ char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */ Table *pTab; /* An SQL table corresponding to zName */ Index: src/util.c ================================================================== --- src/util.c +++ src/util.c @@ -12,11 +12,11 @@ ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: util.c,v 1.65 2003/06/05 14:27:56 drh Exp $ +** $Id: util.c,v 1.66 2003/07/30 12:34:12 drh Exp $ */ #include "sqliteInt.h" #include #include @@ -41,19 +41,23 @@ int sqlite_iMallocFail; /* Fail sqliteMalloc() after this many calls */ #if MEMORY_DEBUG>1 static int memcnt = 0; #endif +/* +** Number of 32-bit guard words +*/ +#define N_GUARD 1 /* ** Allocate new memory and set it to zero. Return NULL if ** no memory is available. */ void *sqliteMalloc_(int n, int bZero, char *zFile, int line){ void *p; int *pi; - int k; + int i, k; if( sqlite_iMallocFail>=0 ){ sqlite_iMallocFail--; if( sqlite_iMallocFail==0 ){ sqlite_malloc_failed++; #if MEMORY_DEBUG>1 @@ -64,20 +68,20 @@ return 0; } } if( n==0 ) return 0; k = (n+sizeof(int)-1)/sizeof(int); - pi = malloc( (3+k)*sizeof(int)); + pi = malloc( (N_GUARD*2+1+k)*sizeof(int)); if( pi==0 ){ sqlite_malloc_failed++; return 0; } sqlite_nMalloc++; - pi[0] = 0xdead1122; - pi[1] = n; - pi[k+2] = 0xdead3344; - p = &pi[2]; + for(i=0; i1 fprintf(stderr,"%06d malloc %d bytes at 0x%x from %s:%d\n", ++memcnt, n, (int)p, zFile,line); #endif @@ -91,39 +95,47 @@ ** ** This routine is used for testing purposes only. */ void sqliteCheckMemory(void *p, int N){ int *pi = p; - int n, k; - pi -= 2; - assert( pi[0]==0xdead1122 ); - n = pi[1]; + int n, i, k; + pi -= N_GUARD+1; + for(i=0; i=0 && N1 fprintf(stderr,"%06d free %d bytes at 0x%x from %s:%d\n", ++memcnt, n, (int)p, zFile,line); #endif free(pi); @@ -134,46 +146,48 @@ ** Resize a prior allocation. If p==0, then this routine ** works just like sqliteMalloc(). If n==0, then this routine ** works just like sqliteFree(). */ void *sqliteRealloc_(void *oldP, int n, char *zFile, int line){ - int *oldPi, *pi, k, oldN, oldK; + int *oldPi, *pi, i, k, oldN, oldK; void *p; if( oldP==0 ){ return sqliteMalloc_(n,1,zFile,line); } if( n==0 ){ sqliteFree_(oldP,zFile,line); return 0; } oldPi = oldP; - oldPi -= 2; + oldPi -= N_GUARD+1; if( oldPi[0]!=0xdead1122 ){ fprintf(stderr,"Low-end memory corruption in realloc at 0x%x\n", (int)p); return 0; } - oldN = oldPi[1]; + oldN = oldPi[N_GUARD]; oldK = (oldN+sizeof(int)-1)/sizeof(int); - if( oldPi[oldK+2]!=0xdead3344 ){ - fprintf(stderr,"High-end memory corruption in realloc at 0x%x\n", (int)p); - return 0; + for(i=0; ioldN ? oldN : n); if( n>oldN ){ memset(&((char*)p)[oldN], 0, n-oldN); } - memset(oldPi, 0xab, (oldK+3)*sizeof(int)); + memset(oldPi, 0xab, (oldK+N_GUARD+2)*sizeof(int)); free(oldPi); #if MEMORY_DEBUG>1 fprintf(stderr,"%06d realloc %d to %d bytes at 0x%x to 0x%x at %s:%d\n", ++memcnt, oldN, n, (int)oldP, (int)p, zFile, line); #endif Index: test/misc2.test ================================================================== --- test/misc2.test +++ test/misc2.test @@ -11,11 +11,11 @@ # This file implements regression tests for SQLite library. # # This file implements tests for miscellanous features that were # left out of other test files. # -# $Id: misc2.test,v 1.5 2003/07/27 17:16:08 drh Exp $ +# $Id: misc2.test,v 1.6 2003/07/30 12:34:13 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Test for ticket #360 @@ -96,5 +96,21 @@ do_test misc2-4.6 { execsql { SELECT a FROM t1 WHERE a<1000000000000 ORDER BY 1; } } {1 2147483647 2147483648 4000000000} + +# There were some issues with expanding a SrcList object using a call +# to sqliteSrcListAppend() if the SrcList had previously been duplicated +# using a call to sqliteSrcListDup(). Ticket #416. The following test +# makes sure the problem has been fixed. +# +do_test misc2-5.1 { + execsql { + CREATE TABLE x(a,b); + CREATE VIEW y AS + SELECT x1.b AS p, x2.b AS q FROM x AS x1, x AS x2 WHERE x1.a=x2.a; + CREATE VIEW z AS + SELECT y1.p, y2.p FROM y AS y1, y AS y2 WHERE y1.q=y2.q; + SELECT * from z; + } +} {}