/ Check-in [01ad352c]
Login

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

Overview
Comment:Fix some places where a malloc() failure would lead to a segfault. (CVS 580)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:01ad352c3c82a86d9c94010cbc85d098b8fbc08a
User & Date: drh 2002-05-23 02:09:04
Context
2002-05-23
12:50
Partial fix for ticket #49. The correct result is computed, but now we have a memory leak. I'm not sure if the memory leak was pre-existing or a result of this change. (CVS 581) check-in: 4d27ee41 user: drh tags: trunk
02:09
Fix some places where a malloc() failure would lead to a segfault. (CVS 580) check-in: 01ad352c user: drh tags: trunk
00:30
Do not allow triggers on the SQLITE_MASTER table. (CVS 579) check-in: 275ba356 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/expr.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
182
183
184
185
186
187
188

189
190
191
192
193
194
195
...
199
200
201
202
203
204
205

206
207
208
209
210
211
212
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.61 2002/05/21 13:43:04 drh Exp $
*/
#include "sqliteInt.h"


/*
** Construct a new expression node and return a pointer to it.  Memory
** for this node is obtained from sqliteMalloc().  The calling function
................................................................................
  ExprList *pNew;
  int i;
  if( p==0 ) return 0;
  pNew = sqliteMalloc( sizeof(*pNew) );
  if( pNew==0 ) return 0;
  pNew->nExpr = p->nExpr;
  pNew->a = sqliteMalloc( p->nExpr*sizeof(p->a[0]) );

  for(i=0; i<p->nExpr; i++){
    pNew->a[i].pExpr = sqliteExprDup(p->a[i].pExpr);
    pNew->a[i].zName = sqliteStrDup(p->a[i].zName);
    pNew->a[i].sortOrder = p->a[i].sortOrder;
    pNew->a[i].isAgg = p->a[i].isAgg;
    pNew->a[i].done = 0;
  }
................................................................................
  IdList *pNew;
  int i;
  if( p==0 ) return 0;
  pNew = sqliteMalloc( sizeof(*pNew) );
  if( pNew==0 ) return 0;
  pNew->nId = p->nId;
  pNew->a = sqliteMalloc( p->nId*sizeof(p->a[0]) );

  for(i=0; i<p->nId; i++){
    pNew->a[i].zName = sqliteStrDup(p->a[i].zName);
    pNew->a[i].zAlias = sqliteStrDup(p->a[i].zAlias);
    pNew->a[i].idx = p->a[i].idx;
    pNew->a[i].pTab = 0;
    pNew->a[i].pSelect = sqliteSelectDup(p->a[i].pSelect);
  }







|







 







>







 







>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
...
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.62 2002/05/23 02:09:04 drh Exp $
*/
#include "sqliteInt.h"


/*
** Construct a new expression node and return a pointer to it.  Memory
** for this node is obtained from sqliteMalloc().  The calling function
................................................................................
  ExprList *pNew;
  int i;
  if( p==0 ) return 0;
  pNew = sqliteMalloc( sizeof(*pNew) );
  if( pNew==0 ) return 0;
  pNew->nExpr = p->nExpr;
  pNew->a = sqliteMalloc( p->nExpr*sizeof(p->a[0]) );
  if( pNew->a==0 ) return 0;
  for(i=0; i<p->nExpr; i++){
    pNew->a[i].pExpr = sqliteExprDup(p->a[i].pExpr);
    pNew->a[i].zName = sqliteStrDup(p->a[i].zName);
    pNew->a[i].sortOrder = p->a[i].sortOrder;
    pNew->a[i].isAgg = p->a[i].isAgg;
    pNew->a[i].done = 0;
  }
................................................................................
  IdList *pNew;
  int i;
  if( p==0 ) return 0;
  pNew = sqliteMalloc( sizeof(*pNew) );
  if( pNew==0 ) return 0;
  pNew->nId = p->nId;
  pNew->a = sqliteMalloc( p->nId*sizeof(p->a[0]) );
  if( pNew->a==0 ) return 0;
  for(i=0; i<p->nId; i++){
    pNew->a[i].zName = sqliteStrDup(p->a[i].zName);
    pNew->a[i].zAlias = sqliteStrDup(p->a[i].zAlias);
    pNew->a[i].idx = p->a[i].idx;
    pNew->a[i].pTab = 0;
    pNew->a[i].pSelect = sqliteSelectDup(p->a[i].pSelect);
  }

Changes to src/main.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
383
384
385
386
387
388
389


390
391

392
393
394
395
396
397
398
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.75 2002/05/19 23:43:14 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** This is the callback routine for the code that initializes the
................................................................................
** either the database is being closed or because some other process
** changed the schema and this process needs to reread it.
*/
static void clearHashTable(sqlite *db, int preserveTemps){
  HashElem *pElem;
  Hash temp1;
  Hash temp2;


  assert( sqliteHashFirst(&db->tblDrop)==0 ); /* There can not be uncommitted */
  assert( sqliteHashFirst(&db->idxDrop)==0 ); /*   DROP TABLEs or DROP INDEXs */

  temp1 = db->tblHash;
  temp2 = db->trigHash;
  sqliteHashInit(&db->trigHash, SQLITE_HASH_STRING, 0);
  sqliteHashClear(&db->idxHash);

  for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
    Trigger * pTrigger = sqliteHashData(pElem);







|







 







>
>
|
|
>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.76 2002/05/23 02:09:04 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** This is the callback routine for the code that initializes the
................................................................................
** either the database is being closed or because some other process
** changed the schema and this process needs to reread it.
*/
static void clearHashTable(sqlite *db, int preserveTemps){
  HashElem *pElem;
  Hash temp1;
  Hash temp2;

  /* Make sure there are no uncommited DROPs */
  assert( sqliteHashFirst(&db->tblDrop)==0 || sqlite_malloc_failed );
  assert( sqliteHashFirst(&db->idxDrop)==0 || sqlite_malloc_failed );
  assert( sqliteHashFirst(&db->trigDrop)==0 || sqlite_malloc_failed );
  temp1 = db->tblHash;
  temp2 = db->trigHash;
  sqliteHashInit(&db->trigHash, SQLITE_HASH_STRING, 0);
  sqliteHashClear(&db->idxHash);

  for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
    Trigger * pTrigger = sqliteHashData(pElem);

Changes to src/trigger.c.

48
49
50
51
52
53
54

55
56
57
58
59
60
61
..
66
67
68
69
70
71
72

73
74


75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
...
116
117
118
119
120
121
122

123
124
125
126
127
128
129
...
171
172
173
174
175
176
177

178
179
180
181
182
183
184
...
194
195
196
197
198
199
200

201
202
203
204
205
206
207
...
220
221
222
223
224
225
226

227
228
229
230
231
232
233
...
236
237
238
239
240
241
242
243

244
245
246
247
248
249
250
...
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
      pParse->nErr++;
      goto trigger_cleanup;
    }
    sqliteFree(tmp_str);
  }
  {
    char *tmp_str = sqliteStrNDup(pTableName->z, pTableName->n);

    tab = sqliteFindTable(pParse->db, tmp_str);
    sqliteFree(tmp_str);
    if( !tab ){
      sqliteSetNString(&pParse->zErrMsg, "no such table: ", -1,
          pTableName->z, pTableName->n, 0);
      pParse->nErr++;
      goto trigger_cleanup;
................................................................................
      pParse->nErr++;
      goto trigger_cleanup;
    }
  }

  /* Build the Trigger object */
  nt = (Trigger*)sqliteMalloc(sizeof(Trigger));

  nt->name = sqliteStrNDup(pName->z, pName->n);
  nt->table = sqliteStrNDup(pTableName->z, pTableName->n);


  nt->op = op;
  nt->tr_tm = tr_tm;
  nt->pWhen = pWhen;
  nt->pColumns = pColumns;
  nt->foreach = foreach;
  nt->step_list = pStepList;
  nt->isCommit = 0;

  nt->strings = sqliteStrNDup(zData, zDataLen);
  offset = (int)(nt->strings - zData);

  sqliteExprMoveStrings(nt->pWhen, offset);

  ss = nt->step_list;
  while( ss ){
    sqliteSelectMoveStrings(ss->pSelect, offset);
    if( ss->target.z ){
      ss->target.z += offset;
................................................................................
      { OP_Close,      0, 0,  0          },
    };
    int addr;
    Vdbe *v;

    /* Make an entry in the sqlite_master table */
    v = sqliteGetVdbe(pParse);

    sqliteBeginWriteOperation(pParse, 0);
    addr = sqliteVdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
    sqliteVdbeChangeP3(v, addr+3, nt->name, 0); 
    sqliteVdbeChangeP3(v, addr+4, nt->table, 0); 
    sqliteVdbeChangeP3(v, addr+6, nt->strings, 0);
    sqliteChangeCookie(pParse->db);
    sqliteVdbeChangeP1(v, addr+9, pParse->db->next_cookie);
................................................................................
** a trigger step.  Return a pointer to a TriggerStep structure.
**
** The parser calls this routine when it finds a SELECT statement in
** body of a TRIGGER.  
*/
TriggerStep *sqliteTriggerSelectStep(Select *pSelect){
  TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));


  pTriggerStep->op = TK_SELECT;
  pTriggerStep->pSelect = pSelect;
  pTriggerStep->orconf = OE_Default;

  return pTriggerStep;
}
................................................................................
  Token *pTableName,  /* Name of the table into which we insert */
  IdList *pColumn,    /* List of columns in pTableName to insert into */
  ExprList *pEList,   /* The VALUE clause: a list of values to be inserted */
  Select *pSelect,    /* A SELECT statement that supplies values */
  int orconf          /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
){
  TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));


  assert(pEList == 0 || pSelect == 0);
  assert(pEList != 0 || pSelect != 0);

  pTriggerStep->op = TK_INSERT;
  pTriggerStep->pSelect = pSelect;
  pTriggerStep->target  = *pTableName;
................................................................................
TriggerStep *sqliteTriggerUpdateStep(
  Token *pTableName,   /* Name of the table to be updated */
  ExprList *pEList,    /* The SET clause: list of column and new values */
  Expr *pWhere,        /* The WHERE clause */
  int orconf           /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
){
  TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));


  pTriggerStep->op = TK_UPDATE;
  pTriggerStep->target  = *pTableName;
  pTriggerStep->pExprList = pEList;
  pTriggerStep->pWhere = pWhere;
  pTriggerStep->orconf = orconf;

................................................................................

/*
** Construct a trigger step that implements a DELETE statement and return
** a pointer to that trigger step.  The parser calls this routine when it
** sees a DELETE statement inside the body of a CREATE TRIGGER.
*/
TriggerStep *sqliteTriggerDeleteStep(Token *pTableName, Expr *pWhere){
  TriggerStep * pTriggerStep = sqliteMalloc(sizeof(TriggerStep));


  pTriggerStep->op = TK_DELETE;
  pTriggerStep->target  = *pTableName;
  pTriggerStep->pWhere = pWhere;
  pTriggerStep->orconf = OE_Default;

  return pTriggerStep;
................................................................................
      }
      if( op == TK_UPDATE && pTrigger->pColumns &&
          !checkColumnOverLap(pTrigger->pColumns, pChanges) ){
        fire_this = 0;
      }
    }

    if( fire_this ){
      int endTrigger;
      IdList dummyTablist;
      Expr * whenExpr;

      dummyTablist.nId = 0;
      dummyTablist.a = 0;

      /* Push an entry on to the trigger stack */
      pTriggerStack = sqliteMalloc(sizeof(TriggerStack));
      pTriggerStack->pTrigger = pTrigger;
      pTriggerStack->newIdx = newIdx;
      pTriggerStack->oldIdx = oldIdx;
      pTriggerStack->pTab = pTab;
      pTriggerStack->pNext = pParse->trigStack;
      pParse->trigStack = pTriggerStack;








>







 







>


>
>







<
<

<







 







>







 







>







 







>







 







>







 







|
>







 







|








<







48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
..
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85


86

87
88
89
90
91
92
93
...
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
...
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
...
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
...
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
...
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
...
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580

581
582
583
584
585
586
587
      pParse->nErr++;
      goto trigger_cleanup;
    }
    sqliteFree(tmp_str);
  }
  {
    char *tmp_str = sqliteStrNDup(pTableName->z, pTableName->n);
    if( tmp_str==0 ) goto trigger_cleanup;
    tab = sqliteFindTable(pParse->db, tmp_str);
    sqliteFree(tmp_str);
    if( !tab ){
      sqliteSetNString(&pParse->zErrMsg, "no such table: ", -1,
          pTableName->z, pTableName->n, 0);
      pParse->nErr++;
      goto trigger_cleanup;
................................................................................
      pParse->nErr++;
      goto trigger_cleanup;
    }
  }

  /* Build the Trigger object */
  nt = (Trigger*)sqliteMalloc(sizeof(Trigger));
  if( nt==0 ) goto trigger_cleanup;
  nt->name = sqliteStrNDup(pName->z, pName->n);
  nt->table = sqliteStrNDup(pTableName->z, pTableName->n);
  nt->strings = sqliteStrNDup(zData, zDataLen);
  if( sqlite_malloc_failed ) goto trigger_cleanup;
  nt->op = op;
  nt->tr_tm = tr_tm;
  nt->pWhen = pWhen;
  nt->pColumns = pColumns;
  nt->foreach = foreach;
  nt->step_list = pStepList;
  nt->isCommit = 0;


  offset = (int)(nt->strings - zData);

  sqliteExprMoveStrings(nt->pWhen, offset);

  ss = nt->step_list;
  while( ss ){
    sqliteSelectMoveStrings(ss->pSelect, offset);
    if( ss->target.z ){
      ss->target.z += offset;
................................................................................
      { OP_Close,      0, 0,  0          },
    };
    int addr;
    Vdbe *v;

    /* Make an entry in the sqlite_master table */
    v = sqliteGetVdbe(pParse);
    if( v==0 ) goto trigger_cleanup;
    sqliteBeginWriteOperation(pParse, 0);
    addr = sqliteVdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
    sqliteVdbeChangeP3(v, addr+3, nt->name, 0); 
    sqliteVdbeChangeP3(v, addr+4, nt->table, 0); 
    sqliteVdbeChangeP3(v, addr+6, nt->strings, 0);
    sqliteChangeCookie(pParse->db);
    sqliteVdbeChangeP1(v, addr+9, pParse->db->next_cookie);
................................................................................
** a trigger step.  Return a pointer to a TriggerStep structure.
**
** The parser calls this routine when it finds a SELECT statement in
** body of a TRIGGER.  
*/
TriggerStep *sqliteTriggerSelectStep(Select *pSelect){
  TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
  if( pTriggerStep==0 ) return 0;

  pTriggerStep->op = TK_SELECT;
  pTriggerStep->pSelect = pSelect;
  pTriggerStep->orconf = OE_Default;

  return pTriggerStep;
}
................................................................................
  Token *pTableName,  /* Name of the table into which we insert */
  IdList *pColumn,    /* List of columns in pTableName to insert into */
  ExprList *pEList,   /* The VALUE clause: a list of values to be inserted */
  Select *pSelect,    /* A SELECT statement that supplies values */
  int orconf          /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
){
  TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
  if( pTriggerStep==0 ) return 0;

  assert(pEList == 0 || pSelect == 0);
  assert(pEList != 0 || pSelect != 0);

  pTriggerStep->op = TK_INSERT;
  pTriggerStep->pSelect = pSelect;
  pTriggerStep->target  = *pTableName;
................................................................................
TriggerStep *sqliteTriggerUpdateStep(
  Token *pTableName,   /* Name of the table to be updated */
  ExprList *pEList,    /* The SET clause: list of column and new values */
  Expr *pWhere,        /* The WHERE clause */
  int orconf           /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
){
  TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
  if( pTriggerStep==0 ) return 0;

  pTriggerStep->op = TK_UPDATE;
  pTriggerStep->target  = *pTableName;
  pTriggerStep->pExprList = pEList;
  pTriggerStep->pWhere = pWhere;
  pTriggerStep->orconf = orconf;

................................................................................

/*
** Construct a trigger step that implements a DELETE statement and return
** a pointer to that trigger step.  The parser calls this routine when it
** sees a DELETE statement inside the body of a CREATE TRIGGER.
*/
TriggerStep *sqliteTriggerDeleteStep(Token *pTableName, Expr *pWhere){
  TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
  if( pTriggerStep==0 ) return 0;

  pTriggerStep->op = TK_DELETE;
  pTriggerStep->target  = *pTableName;
  pTriggerStep->pWhere = pWhere;
  pTriggerStep->orconf = OE_Default;

  return pTriggerStep;
................................................................................
      }
      if( op == TK_UPDATE && pTrigger->pColumns &&
          !checkColumnOverLap(pTrigger->pColumns, pChanges) ){
        fire_this = 0;
      }
    }

    if( fire_this && (pTriggerStack = sqliteMalloc(sizeof(TriggerStack)))!=0 ){
      int endTrigger;
      IdList dummyTablist;
      Expr * whenExpr;

      dummyTablist.nId = 0;
      dummyTablist.a = 0;

      /* Push an entry on to the trigger stack */

      pTriggerStack->pTrigger = pTrigger;
      pTriggerStack->newIdx = newIdx;
      pTriggerStack->oldIdx = oldIdx;
      pTriggerStack->pTab = pTab;
      pTriggerStack->pNext = pParse->trigStack;
      pParse->trigStack = pTriggerStack;

Changes to src/vdbe.c.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
...
963
964
965
966
967
968
969

970
971
972

973
974
975
976
977
978
979
...
991
992
993
994
995
996
997

998
999

1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
** type to the other occurs as necessary.
** 
** Most of the code in this file is taken up by the sqliteVdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** $Id: vdbe.c,v 1.144 2002/05/19 23:43:14 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_MoveTo or the OP_Next opcode.  The test
................................................................................
*/
static void Cleanup(Vdbe *p){
  int i;
  PopStack(p, p->tos+1);
  sqliteFree(p->azColName);
  p->azColName = 0;
  closeAllCursors(p);

  for(i=0; i<p->nMem; i++){
    if( p->aMem[i].s.flags & STK_Dyn ){
      sqliteFree(p->aMem[i].z);

    }
  }
  sqliteFree(p->aMem);
  p->aMem = 0;
  p->nMem = 0;
  if( p->pList ){
    KeylistFree(p->pList);
................................................................................
  p->nField = 0;
  if( p->zLine ){
    sqliteFree(p->zLine);
    p->zLine = 0;
  }
  p->nLineAlloc = 0;
  AggReset(&p->agg);

  for(i=0; i<p->nSet; i++){
    sqliteHashClear(&p->aSet[i].hash);

  }
  sqliteFree(p->aSet);
  p->aSet = 0;
  p->nSet = 0;
  if( p->keylistStackDepth > 0 ){
    int ii;
    for(ii = 0; ii < p->keylistStackDepth; ii++){
      KeylistFree(p->keylistStack[ii]);
    }
    sqliteFree(p->keylistStack);
    p->keylistStackDepth = 0;
    p->keylistStack = 0;







|







 







>
|
|
|
>







 







>
|
|
>




|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
...
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
...
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
** type to the other occurs as necessary.
** 
** Most of the code in this file is taken up by the sqliteVdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** $Id: vdbe.c,v 1.145 2002/05/23 02:09:04 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_MoveTo or the OP_Next opcode.  The test
................................................................................
*/
static void Cleanup(Vdbe *p){
  int i;
  PopStack(p, p->tos+1);
  sqliteFree(p->azColName);
  p->azColName = 0;
  closeAllCursors(p);
  if( p->aMem ){
    for(i=0; i<p->nMem; i++){
      if( p->aMem[i].s.flags & STK_Dyn ){
        sqliteFree(p->aMem[i].z);
      }
    }
  }
  sqliteFree(p->aMem);
  p->aMem = 0;
  p->nMem = 0;
  if( p->pList ){
    KeylistFree(p->pList);
................................................................................
  p->nField = 0;
  if( p->zLine ){
    sqliteFree(p->zLine);
    p->zLine = 0;
  }
  p->nLineAlloc = 0;
  AggReset(&p->agg);
  if( p->aSet ){
    for(i=0; i<p->nSet; i++){
      sqliteHashClear(&p->aSet[i].hash);
    }
  }
  sqliteFree(p->aSet);
  p->aSet = 0;
  p->nSet = 0;
  if( p->keylistStack ){
    int ii;
    for(ii = 0; ii < p->keylistStackDepth; ii++){
      KeylistFree(p->keylistStack[ii]);
    }
    sqliteFree(p->keylistStack);
    p->keylistStackDepth = 0;
    p->keylistStack = 0;

Changes to test/malloc.test.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
...
174
175
176
177
178
179
180


































181
182
183
184
185
186
187
#***********************************************************************
# This file attempts to check the library in an out-of-memory situation.
# When compiled with -DMEMORY_DEBUG=1, the SQLite library accepts a special
# command (sqlite_malloc_fail N) which causes the N-th malloc to fail.  This
# special feature is used to see what happens in the library if a malloc
# were to really fail due to an out-of-memory situation.
#
# $Id: malloc.test,v 1.4 2001/10/22 02:58:11 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Only run these tests if memory debugging is turned on.
#
if {[info command sqlite_malloc_fail]==""} {
................................................................................
     } else {
       set v2 [expr {$msg=="" || $msg=="out of memory"}]
       if {!$v2} {puts "\nError message returned: $msg"}
       lappend v $v2
     }
  } {1 1}
}

finish_test
return


set fd [open ./data.tmp w]
for {set i 1} {$i<=20} {incr i} {
  puts $fd "$i\t[expr {$i*$i}]\t[expr {100-$i}] abcdefghijklmnopqrstuvwxyz"
}
close $fd

................................................................................
         UPDATE t1 SET b=a WHERE a in (10,12,22);
         INSERT INTO t1 SELECT * FROM t1
             WHERE a IN (SELECT a FROM t1 WHERE a<10);
         DROP INDEX i1;
         DELETE FROM t1;
         COMMIT;
       }} msg]


































     }
     set leftover [lindex [sqlite_malloc_stat] 2]
     if {$leftover>0} {
       if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v  Message=$msg"}
       set ::go 0
       set v {1 1}
     } else {







|







 







<
<
<
<







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
60
61
62
63
64
65
66




67
68
69
70
71
72
73
...
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
#***********************************************************************
# This file attempts to check the library in an out-of-memory situation.
# When compiled with -DMEMORY_DEBUG=1, the SQLite library accepts a special
# command (sqlite_malloc_fail N) which causes the N-th malloc to fail.  This
# special feature is used to see what happens in the library if a malloc
# were to really fail due to an out-of-memory situation.
#
# $Id: malloc.test,v 1.5 2002/05/23 02:09:05 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Only run these tests if memory debugging is turned on.
#
if {[info command sqlite_malloc_fail]==""} {
................................................................................
     } else {
       set v2 [expr {$msg=="" || $msg=="out of memory"}]
       if {!$v2} {puts "\nError message returned: $msg"}
       lappend v $v2
     }
  } {1 1}
}





set fd [open ./data.tmp w]
for {set i 1} {$i<=20} {incr i} {
  puts $fd "$i\t[expr {$i*$i}]\t[expr {100-$i}] abcdefghijklmnopqrstuvwxyz"
}
close $fd

................................................................................
         UPDATE t1 SET b=a WHERE a in (10,12,22);
         INSERT INTO t1 SELECT * FROM t1
             WHERE a IN (SELECT a FROM t1 WHERE a<10);
         DROP INDEX i1;
         DELETE FROM t1;
         COMMIT;
       }} msg]
     }
     set leftover [lindex [sqlite_malloc_stat] 2]
     if {$leftover>0} {
       if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v  Message=$msg"}
       set ::go 0
       set v {1 1}
     } else {
       set v2 [expr {$msg=="" || $msg=="out of memory"}]
       if {!$v2} {puts "\nError message returned: $msg"}
       lappend v $v2
     }
  } {1 1}
}
for {set go 1; set i 1} {$go} {incr i} {
  do_test malloc-5.$i {
     sqlite_malloc_fail 0
     catch {db close}
     catch {file delete -force test.db}
     catch {file delete -force test.db-journal}
     sqlite_malloc_fail $i
     set v [catch {sqlite db test.db} msg]
     if {$v} {
       set msg ""
     } else {
       set v [catch {execsql {
         BEGIN TRANSACTION;
         CREATE TABLE t1(a,b);
         CREATE TABLE t2(x,y);
         CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
           INSERT INTO t2(x,y) VALUES(new.rowid,1);
         END;
         INSERT INTO t1(a,b) VALUES(2,3);
         COMMIT;
       }} msg]
     }
     set leftover [lindex [sqlite_malloc_stat] 2]
     if {$leftover>0} {
       if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v  Message=$msg"}
       set ::go 0
       set v {1 1}
     } else {