SQLite

Check-in [d55a5e1c11]
Login

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

Overview
Comment:Add the ability to simulate out-of-memory errors when using the default memory allocator, mem1.c. Fix a bug that this enhancement revealed. (CVS 4875)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: d55a5e1c11ef90534abd2e5f18d06dd4739ade70
User & Date: drh 2008-03-18 00:07:11.000
Context
2008-03-18
00:54
Fix a memory leak introduced by the previous bug fix. (CVS 4876) (check-in: b9c5dce349 user: drh tags: trunk)
00:07
Add the ability to simulate out-of-memory errors when using the default memory allocator, mem1.c. Fix a bug that this enhancement revealed. (CVS 4875) (check-in: d55a5e1c11 user: drh tags: trunk)
2008-03-17
19:03
Version 3.5.7 (CVS 4874) (check-in: 9a6583d375 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/mem1.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the C functions that implement a memory
** allocation subsystem for use by SQLite.  
**
** $Id: mem1.c,v 1.16 2008/02/14 23:26:56 drh Exp $
*/
#include "sqliteInt.h"

/*
** This version of the memory allocator is the default.  It is
** used when no other memory allocator is specified using compile-time
** macros.







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the C functions that implement a memory
** allocation subsystem for use by SQLite.  
**
** $Id: mem1.c,v 1.17 2008/03/18 00:07:11 drh Exp $
*/
#include "sqliteInt.h"

/*
** This version of the memory allocator is the default.  It is
** used when no other memory allocator is specified using compile-time
** macros.
133
134
135
136
137
138
139



140
141
142
143

144
145
146
147
148
149
150
void *sqlite3_malloc(int nBytes){
  sqlite3_int64 *p = 0;
  if( nBytes>0 ){
    enterMem();
    if( mem.alarmCallback!=0 && mem.nowUsed+nBytes>=mem.alarmThreshold ){
      sqlite3MemsysAlarm(nBytes);
    }



    p = malloc(nBytes+8);
    if( p==0 ){
      sqlite3MemsysAlarm(nBytes);
      p = malloc(nBytes+8);

    }
    if( p ){
      p[0] = nBytes;
      p++;
      mem.nowUsed += nBytes;
      if( mem.nowUsed>mem.mxUsed ){
        mem.mxUsed = mem.nowUsed;







>
>
>
|
|
|
|
>







133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
void *sqlite3_malloc(int nBytes){
  sqlite3_int64 *p = 0;
  if( nBytes>0 ){
    enterMem();
    if( mem.alarmCallback!=0 && mem.nowUsed+nBytes>=mem.alarmThreshold ){
      sqlite3MemsysAlarm(nBytes);
    }
    if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){
      p = 0;
    }else{
      p = malloc(nBytes+8);
      if( p==0 ){
        sqlite3MemsysAlarm(nBytes);
        p = malloc(nBytes+8);
      }
    }
    if( p ){
      p[0] = nBytes;
      p++;
      mem.nowUsed += nBytes;
      if( mem.nowUsed>mem.mxUsed ){
        mem.mxUsed = mem.nowUsed;
201
202
203
204
205
206
207



208
209
210
211
212
213

214
215
216
217
218
219
220
  p--;
  nOld = (int)p[0];
  assert( mem.mutex!=0 );
  sqlite3_mutex_enter(mem.mutex);
  if( mem.nowUsed+nBytes-nOld>=mem.alarmThreshold ){
    sqlite3MemsysAlarm(nBytes-nOld);
  }



  p = realloc(p, nBytes+8);
  if( p==0 ){
    sqlite3MemsysAlarm(nBytes);
    p = pPrior;
    p--;
    p = realloc(p, nBytes+8);

  }
  if( p ){
    p[0] = nBytes;
    p++;
    mem.nowUsed += nBytes-nOld;
    if( mem.nowUsed>mem.mxUsed ){
      mem.mxUsed = mem.nowUsed;







>
>
>
|
|
|
|
|
|
>







205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
  p--;
  nOld = (int)p[0];
  assert( mem.mutex!=0 );
  sqlite3_mutex_enter(mem.mutex);
  if( mem.nowUsed+nBytes-nOld>=mem.alarmThreshold ){
    sqlite3MemsysAlarm(nBytes-nOld);
  }
  if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){
    p = 0;
  }else{
    p = realloc(p, nBytes+8);
    if( p==0 ){
      sqlite3MemsysAlarm(nBytes);
      p = pPrior;
      p--;
      p = realloc(p, nBytes+8);
    }
  }
  if( p ){
    p[0] = nBytes;
    p++;
    mem.nowUsed += nBytes-nOld;
    if( mem.nowUsed>mem.mxUsed ){
      mem.mxUsed = mem.nowUsed;
Changes to src/test_malloc.c.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains code used to implement test interfaces to the
** memory allocation subsystem.
**
** $Id: test_malloc.c,v 1.15 2008/02/19 15:15:16 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>








|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains code used to implement test interfaces to the
** memory allocation subsystem.
**
** $Id: test_malloc.c,v 1.16 2008/03/18 00:07:11 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>

459
460
461
462
463
464
465

466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
*/
static int test_memdebug_pending(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){

  if( objc!=1 ){
    Tcl_WrongNumArgs(interp, 1, objv, "");
    return TCL_ERROR;
  }

#if defined(SQLITE_MEMDEBUG) || defined(SQLITE_POW2_MEMORY_SIZE)
  {
    int nPending = sqlite3_test_control(SQLITE_TESTCTRL_FAULT_PENDING,
                                        SQLITE_FAULTINJECTOR_MALLOC);
    Tcl_SetObjResult(interp, Tcl_NewIntObj(nPending));
  }
#endif
  return TCL_OK;
}


/*
** Usage:    sqlite3_memdebug_settitle TITLE
**







>




<
<
<
|
|
|
<
<







459
460
461
462
463
464
465
466
467
468
469
470



471
472
473


474
475
476
477
478
479
480
*/
static int test_memdebug_pending(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  int nPending;
  if( objc!=1 ){
    Tcl_WrongNumArgs(interp, 1, objv, "");
    return TCL_ERROR;
  }



  nPending = sqlite3_test_control(SQLITE_TESTCTRL_FAULT_PENDING,
                                  SQLITE_FAULTINJECTOR_MALLOC);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(nPending));


  return TCL_OK;
}


/*
** Usage:    sqlite3_memdebug_settitle TITLE
**
Changes to src/vdbemem.c.
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

97
98
99
100
101
102
103

  assert( (f & (MEM_Dyn|MEM_Static|MEM_Ephem))==0 
       || (f & (MEM_Dyn|MEM_Static|MEM_Ephem))==MEM_Dyn 
       || (f & (MEM_Dyn|MEM_Static|MEM_Ephem))==MEM_Ephem 
       || (f & (MEM_Dyn|MEM_Static|MEM_Ephem))==MEM_Static 
  );

  if( ((f&MEM_Dyn)==0 || pMem->xDel || sqlite3MallocSize(pMem->z)<n) ){

    /* Allocate the new buffer. The minimum allocation size is 32 bytes. */
    char *z = 0;
    if( n>0 ){
      if( preserve && (f&MEM_Dyn) && !pMem->xDel ){
        z = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
        pMem->z = 0;
        preserve = 0;
      }else{
        z = sqlite3DbMallocRaw(pMem->db, (n>32?n:32));
      }
      if( !z ){

        return SQLITE_NOMEM;
      }
    }

    /* If the value is currently a string or blob and the preserve flag
    ** is true, copy the content to the new buffer. 
    */







|












>







77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104

  assert( (f & (MEM_Dyn|MEM_Static|MEM_Ephem))==0 
       || (f & (MEM_Dyn|MEM_Static|MEM_Ephem))==MEM_Dyn 
       || (f & (MEM_Dyn|MEM_Static|MEM_Ephem))==MEM_Ephem 
       || (f & (MEM_Dyn|MEM_Static|MEM_Ephem))==MEM_Static 
  );

  if( (f&MEM_Dyn)==0 || pMem->xDel || sqlite3MallocSize(pMem->z)<n ){

    /* Allocate the new buffer. The minimum allocation size is 32 bytes. */
    char *z = 0;
    if( n>0 ){
      if( preserve && (f&MEM_Dyn) && !pMem->xDel ){
        z = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
        pMem->z = 0;
        preserve = 0;
      }else{
        z = sqlite3DbMallocRaw(pMem->db, (n>32?n:32));
      }
      if( !z ){
        pMem->flags = MEM_Null;
        return SQLITE_NOMEM;
      }
    }

    /* If the value is currently a string or blob and the preserve flag
    ** is true, copy the content to the new buffer. 
    */
Changes to test/malloc_common.tcl.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

24
25
26
27
28
29
30
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains common code used by many different malloc tests
# within the test suite.
#
# $Id: malloc_common.tcl,v 1.13 2008/02/18 22:24:58 drh Exp $

# If we did not compile with malloc testing enabled, then do nothing.
#
ifcapable !memdebug&&!mem5 {
  set MEMDEBUG 0
  return 0
} else {
  set MEMDEBUG 1

}

# Usage: do_malloc_test <test number> <options...>
#
# The first argument, <test number>, is an integer used to name the
# tests executed by this proc. Options are as follows:
#







|



|
|
<

|
>







8
9
10
11
12
13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
28
29
30
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains common code used by many different malloc tests
# within the test suite.
#
# $Id: malloc_common.tcl,v 1.14 2008/03/18 00:07:11 drh Exp $

# If we did not compile with malloc testing enabled, then do nothing.
#
ifcapable faultinjector {
  set MEMDEBUG 1

} else {
  set MEMDEBUG 0
  return 0
}

# Usage: do_malloc_test <test number> <options...>
#
# The first argument, <test number>, is an integer used to name the
# tests executed by this proc. Options are as follows:
#