/ Check-in [4ae21e34]
Login

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

Overview
Comment:Move (almost all) malloc failure test logic from fault.c to test_malloc.c. (CVS 5253)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 4ae21e3419ad7e69dd735ca45fdc5a2de93d1840
User & Date: danielk1977 2008-06-20 11:05:38
Context
2008-06-20
14:59
Add a mode to the sqlite3_test_control() interface to register hooks called at the beginning and end of "benign malloc failure" blocks. This allows malloc() failure testing to be done using public APIs only. (CVS 5254) check-in: 56c8af14 user: danielk1977 tags: trunk
11:05
Move (almost all) malloc failure test logic from fault.c to test_malloc.c. (CVS 5253) check-in: 4ae21e34 user: danielk1977 tags: trunk
00:03
Patch to memsubsys1.test in order to avoid a segfault in tableapi.test. (CVS 5252) check-in: 62411a6e user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/fault.c.

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
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
93
94
95
96
97
98
99
100
101
102

103
104
105
106
107
108
109

110
111
112
113
114
115

116
117
118

119
120
121
122
123
124
125
126
127
128
129
130
131

132
133
134
135
136
137
138
139
140
141
142
143
144




145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
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
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code to implement a fault-injector used for
** testing and verification of SQLite.
**
** Subsystems within SQLite can call sqlite3FaultStep() to see if
** they should simulate a fault.  sqlite3FaultStep() normally returns
** zero but will return non-zero if a fault should be simulated.
** Fault injectors can be used, for example, to simulate memory
** allocation failures or I/O errors.
**
** The fault injector is omitted from the code if SQLite is
** compiled with -DSQLITE_OMIT_BUILTIN_TEST=1.  There is a very
** small performance hit for leaving the fault injector in the code.
** Commerical products will probably want to omit the fault injector
** from production builds.  But safety-critical systems who work
** under the motto "fly what you test and test what you fly" may
** choose to leave the fault injector enabled even in production.
**
** $Id: fault.c,v 1.7 2008/06/19 18:17:50 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** There can be various kinds of faults.  For example, there can be
** a memory allocation failure.  Or an I/O failure.  For each different
** fault type, there is a separate FaultInjector structure to keep track
** of the status of that fault.
*/
static struct MemFault {
  int iCountdown;   /* Number of pending successes before we hit a failure */
  int nRepeat;      /* Number of times to repeat the failure */
  int nBenign;      /* Number of benign failures seen since last config */
  int nFail;        /* Number of failures seen since last config */
  u8 enable;        /* True if enabled */
  i16 benign;       /* Positive if next failure will be benign */

  int isInstalled;
  sqlite3_mem_methods m;         /* 'Real' malloc implementation */
} memfault;

/*
** This routine exists as a place to set a breakpoint that will
** fire on any simulated malloc() failure.
*/
static void sqlite3Fault(void){
  static int cnt = 0;
  cnt++;
}

/*
** Check to see if a fault should be simulated.  Return true to simulate
** the fault.  Return false if the fault should not be simulated.
*/
static int faultsimStep(){
  if( likely(!memfault.enable) ){
    return 0;
  }
  if( memfault.iCountdown>0 ){
    memfault.iCountdown--;
    return 0;
  }
  sqlite3Fault();
  memfault.nFail++;
  if( memfault.benign>0 ){
    memfault.nBenign++;
  }
  memfault.nRepeat--;
  if( memfault.nRepeat<=0 ){
    memfault.enable = 0;
  }
  return 1;  
}

static void *faultsimMalloc(int n){
  void *p = 0;
  if( !faultsimStep() ){
    p = memfault.m.xMalloc(n);
  }
  return p;
}


static void *faultsimRealloc(void *pOld, int n){
  void *p = 0;
  if( !faultsimStep() ){
    p = memfault.m.xRealloc(pOld, n);
  }
  return p;
}

/* 
** The following method calls are passed directly through to the underlying

** malloc system:
**
**     xFree
**     xSize
**     xRoundup
**     xInit
**     xShutdown

*/
static void faultsimFree(void *p){
  memfault.m.xFree(p);
}
static int faultsimSize(void *p){
  return memfault.m.xSize(p);

}
static int faultsimRoundup(int n){
  return memfault.m.xRoundup(n);

}
static int faultsimInit(void *p){
  return memfault.m.xInit(memfault.m.pAppData);
}
static void faultsimShutdown(void *p){
  memfault.m.xShutdown(memfault.m.pAppData);
}

/*
** This routine configures and enables a fault injector.  After
** calling this routine, a FaultStep() will return false (zero)
** nDelay times, then it will return true nRepeat times,
** then it will again begin returning false.

*/
void sqlite3FaultConfig(int id, int nDelay, int nRepeat){
  memfault.iCountdown = nDelay;
  memfault.nRepeat = nRepeat;
  memfault.nBenign = 0;
  memfault.nFail = 0;
  memfault.enable = nDelay>=0;
  memfault.benign = 0;
}

/*
** Return the number of faults (both hard and benign faults) that have
** occurred since the injector was last configured.




*/
int sqlite3FaultFailures(int id){
  assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT );
  return memfault.nFail;
}

/*
** Return the number of benign faults that have occurred since the
** injector was last configured.
*/
int sqlite3FaultBenignFailures(int id){
  return memfault.nBenign;
}

/*
** Return the number of successes that will occur before the next failure.
** If no failures are scheduled, return -1.
*/
int sqlite3FaultPending(int id){
  if( memfault.enable ){
    return memfault.iCountdown;
  }else{
    return -1;
  }
}

/* 
** After this routine causes subsequent faults to be either benign
** or hard (not benign), according to the "enable" parameter.
**
** Most faults are hard.  In other words, most faults cause
** an error to be propagated back up to the application interface.
** However, sometimes a fault is easily recoverable.  For example,
** if a malloc fails while resizing a hash table, this is completely
** recoverable simply by not carrying out the resize.  The hash table
** will continue to function normally.  So a malloc failure during
** a hash table resize is a benign fault.  
*/
void sqlite3FaultBeginBenign(int id){
  if( id<0 ){
    for(id=0; id<SQLITE_FAULTINJECTOR_COUNT; id++){
      memfault.benign++;
    }
  }else{
    assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT );
    memfault.benign++;
  }
}
void sqlite3FaultEndBenign(int id){
  if( id<0 ){
    for(id=0; id<SQLITE_FAULTINJECTOR_COUNT; id++){
      assert( memfault.benign>0 );
      memfault.benign--;
    }
  }else{
    assert( memfault.benign>0 );
    memfault.benign--;
  }

}

int sqlite3FaultsimInstall(int install){
  static struct sqlite3_mem_methods m = {
    faultsimMalloc,                   /* xMalloc */
    faultsimFree,                     /* xFree */
    faultsimRealloc,                  /* xRealloc */
    faultsimSize,                     /* xSize */
    faultsimRoundup,                  /* xRoundup */
    faultsimInit,                     /* xInit */
    faultsimShutdown,                 /* xShutdown */
    0                                 /* pAppData */
  };
  int rc;

  assert(install==1 || install==0);
  assert(memfault.isInstalled==1 || memfault.isInstalled==0);

  if( install==memfault.isInstalled ){
    return SQLITE_ERROR;
  }

  rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memfault.m);
  assert(memfault.m.xMalloc);
  if( rc==SQLITE_OK ){
    rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &m);
  }

  if( rc==SQLITE_OK ){
    memfault.isInstalled = 1;
  }
  return rc;
}








<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>
|

<
<
<
<
<
>

<
<
|
<
<
>
|
<
<
>
|
<
<
<
<
<
<
<

<
<
<
<
>

<
<
<
<
<
<
|
|
<

<
<
>
>
>
>

|
<
|


|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|










<
<
|
|
<
<
<
<
<

<
<
<
|
|
<
<
<
|
>
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
5
6
7
8
9
10
11


12
























































































13
14
15





16
17


18


19
20


21
22







23




24
25






26
27

28


29
30
31
32
33
34

35
36
37
38




















39
40
41
42
43
44
45
46
47
48
49
50


51
52





53



54
55



56
57
58

































** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************


**
























































































** This file contains code to support the concept of "benign" 
** malloc failures. 
**





** $Id: fault.c,v 1.8 2008/06/20 11:05:38 danielk1977 Exp $
*/





#include "sqliteInt.h"



#ifndef SQLITE_OMIT_BUILTIN_TEST








/*




** If zero, malloc() failures are non-benign. If non-zero, benign.
*/






static int memfault_is_benign = 0;


/*


** Return true if a malloc failures are currently considered to be
** benign. A benign fault does not affect the operation of sqlite.
** By constrast a non-benign fault causes sqlite to fail the current 
** operation and return SQLITE_NOMEM to the user.
*/
int sqlite3FaultIsBenign(void){

  return memfault_is_benign;
}

/* 




















** After this routine causes subsequent malloc faults to be either 
** benign or hard (not benign), according to the "enable" parameter.
**
** Most faults are hard.  In other words, most faults cause
** an error to be propagated back up to the application interface.
** However, sometimes a fault is easily recoverable.  For example,
** if a malloc fails while resizing a hash table, this is completely
** recoverable simply by not carrying out the resize.  The hash table
** will continue to function normally.  So a malloc failure during
** a hash table resize is a benign fault.  
*/
void sqlite3FaultBeginBenign(int id){


  memfault_is_benign++;
}





void sqlite3FaultEndBenign(int id){



  memfault_is_benign--;
}




#endif   /* #ifndef SQLITE_OMIT_BUILTIN_TEST */


































Changes to src/main.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
....
1759
1760
1761
1762
1763
1764
1765

1766
1767
1768
1769
1770
1771
1772
....
1823
1824
1825
1826
1827
1828
1829

1830
1831
1832
1833
1834
1835
1836
**
*************************************************************************
** 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.453 2008/06/19 18:17:50 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

#ifdef SQLITE_ENABLE_FTS3
# include "fts3.h"
#endif
................................................................................
*/
int sqlite3_test_control(int op, ...){
  int rc = 0;
#ifndef SQLITE_OMIT_BUILTIN_TEST
  va_list ap;
  va_start(ap, op);
  switch( op ){

    /*
    ** sqlite3_test_control(FAULT_CONFIG, fault_id, nDelay, nRepeat)
    **
    ** Configure a fault injector.  The specific fault injector is
    ** identified by the fault_id argument.  (ex: SQLITE_FAULTINJECTOR_MALLOC)
    ** The fault will occur after a delay of nDelay calls.  The fault
    ** will repeat nRepeat times.
................................................................................
    ** as a wrapper around the currently installed implementation.
    */
    case SQLITE_TESTCTRL_FAULT_INSTALL: {
      int isInstall = va_arg(ap, int);
      rc = sqlite3FaultsimInstall(isInstall);
      break;
    }


    /*
    ** Save the current state of the PRNG.
    */
    case SQLITE_TESTCTRL_PRNG_SAVE: {
      sqlite3PrngSaveState();
      break;







|







 







>







 







>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
....
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
....
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
**
*************************************************************************
** 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.454 2008/06/20 11:05:38 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

#ifdef SQLITE_ENABLE_FTS3
# include "fts3.h"
#endif
................................................................................
*/
int sqlite3_test_control(int op, ...){
  int rc = 0;
#ifndef SQLITE_OMIT_BUILTIN_TEST
  va_list ap;
  va_start(ap, op);
  switch( op ){
#if 0
    /*
    ** sqlite3_test_control(FAULT_CONFIG, fault_id, nDelay, nRepeat)
    **
    ** Configure a fault injector.  The specific fault injector is
    ** identified by the fault_id argument.  (ex: SQLITE_FAULTINJECTOR_MALLOC)
    ** The fault will occur after a delay of nDelay calls.  The fault
    ** will repeat nRepeat times.
................................................................................
    ** as a wrapper around the currently installed implementation.
    */
    case SQLITE_TESTCTRL_FAULT_INSTALL: {
      int isInstall = va_arg(ap, int);
      rc = sqlite3FaultsimInstall(isInstall);
      break;
    }
#endif

    /*
    ** Save the current state of the PRNG.
    */
    case SQLITE_TESTCTRL_PRNG_SAVE: {
      sqlite3PrngSaveState();
      break;

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
....
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.718 2008/06/19 18:17:50 danielk1977 Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build
................................................................................
/*
** Available fault injectors.  Should be numbered beginning with 0.
*/
#define SQLITE_FAULTINJECTOR_MALLOC     0
#define SQLITE_FAULTINJECTOR_COUNT      1

/*
** The interface to the fault injector subsystem.  If the fault injector
** mechanism is disabled at compile-time then set up macros so that no
** unnecessary code is generated.
*/
#ifndef SQLITE_OMIT_BUILTIN_TEST
  void sqlite3FaultConfig(int,int,int);
  int sqlite3FaultFailures(int);
  int sqlite3FaultBenignFailures(int);
  int sqlite3FaultPending(int);
  void sqlite3FaultBeginBenign(int);
  void sqlite3FaultEndBenign(int);
  int sqlite3FaultStep(int);
  int sqlite3FaultsimInstall(int);
#else
# define sqlite3FaultConfig(A,B,C)
# define sqlite3FaultFailures(A)         0
# define sqlite3FaultBenignFailures(A)   0
# define sqlite3FaultPending(A)          (-1)
# define sqlite3FaultBeginBenign(A)
# define sqlite3FaultEndBenign(A)
# define sqlite3FaultStep(A)             0
#endif
  
  

#define IN_INDEX_ROWID           1
#define IN_INDEX_EPH             2
#define IN_INDEX_INDEX           3
int sqlite3FindInIndex(Parse *, Expr *, int);

#ifdef SQLITE_ENABLE_ATOMIC_WRITE







|







 







|
|
|


<
<
<
<


|
<

<
<
<
<
|
|
<

<
<







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
....
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210




2211
2212
2213

2214




2215
2216

2217


2218
2219
2220
2221
2222
2223
2224
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.719 2008/06/20 11:05:38 danielk1977 Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build
................................................................................
/*
** Available fault injectors.  Should be numbered beginning with 0.
*/
#define SQLITE_FAULTINJECTOR_MALLOC     0
#define SQLITE_FAULTINJECTOR_COUNT      1

/*
** The interface to the code in fault.c used for identifying "benign"
** malloc failures. This is only present if SQLITE_OMIT_BUILTIN_TEST
** is not defined.
*/
#ifndef SQLITE_OMIT_BUILTIN_TEST




  void sqlite3FaultBeginBenign(int);
  void sqlite3FaultEndBenign(int);
  int sqlite3FaultIsBenign(void);

#else




  #define sqlite3FaultBeginBenign()
  #define sqlite3FaultEndBenign()

#endif



#define IN_INDEX_ROWID           1
#define IN_INDEX_EPH             2
#define IN_INDEX_INDEX           3
int sqlite3FindInIndex(Parse *, Expr *, int);

#ifdef SQLITE_ENABLE_ATOMIC_WRITE

Changes to src/test_malloc.c.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23


























































































































































































24
25
26
27
28
29
30
...
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
...
435
436
437
438
439
440
441
442
443
444
445
446
447
448

449
450
451
452
453
454
455
...
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
...
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
...
836
837
838
839
840
841
842

**    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.26 2008/06/19 18:17:50 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>



























































































































































































const char *sqlite3TestErrorName(int);

/*
** Transform pointers to text and back again
*/
static void pointerToText(void *p, char *z){
  static const char zHex[] = "0123456789abcdef";
................................................................................
    return TCL_ERROR;
  }
  p = sqlite3_realloc(pPrior, (unsigned)nByte);
  pointerToText(p, zOut);
  Tcl_AppendResult(interp, zOut, NULL);
  return TCL_OK;
}


/*
** Usage:    sqlite3_free  PRIOR
**
** Raw test interface for sqlite3_free().
*/
static int test_free(
................................................................................

    if( zErr ){
      Tcl_AppendResult(interp, zErr, zOption, 0);
      return TCL_ERROR;
    }
  }
  
  sqlite3_test_control(-12345); /* Just to stress the test_control interface */
  nBenign = sqlite3_test_control(SQLITE_TESTCTRL_FAULT_BENIGN_FAILURES,
                                 SQLITE_FAULTINJECTOR_MALLOC);
  nFail = sqlite3_test_control(SQLITE_TESTCTRL_FAULT_FAILURES,
                               SQLITE_FAULTINJECTOR_MALLOC);
  sqlite3_test_control(SQLITE_TESTCTRL_FAULT_CONFIG,
                       SQLITE_FAULTINJECTOR_MALLOC, iFail, nRepeat);

  if( pBenignCnt ){
    Tcl_ObjSetVar2(interp, pBenignCnt, 0, Tcl_NewIntObj(nBenign), 0);
  }
  Tcl_SetObjResult(interp, Tcl_NewIntObj(nFail));
  return TCL_OK;
}

................................................................................
  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
................................................................................
  if( objc!=2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
    return TCL_ERROR;
  }
  if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[1], &isInstall) ){
    return TCL_ERROR;
  }
  rc = sqlite3_test_control(SQLITE_TESTCTRL_FAULT_INSTALL, isInstall);
  Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
  return TCL_OK;
}

/*
** Register commands with the TCL interpreter.
*/
................................................................................
  };
  int i;
  for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
    Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
  }
  return TCL_OK;
}








|







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







 







<







 







|
|
<
<
<
<
|
>







 







|
<







 







|







 







>
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
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
...
311
312
313
314
315
316
317

318
319
320
321
322
323
324
...
620
621
622
623
624
625
626
627
628




629
630
631
632
633
634
635
636
637
...
649
650
651
652
653
654
655
656

657
658
659
660
661
662
663
...
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
....
1017
1018
1019
1020
1021
1022
1023
1024
**    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.27 2008/06/20 11:05:38 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>

/*
** This structure is used to encapsulate the global state variables used 
** by malloc() fault simulation.
*/
static struct MemFault {
  int iCountdown;         /* Number of pending successes before a failure */
  int nRepeat;            /* Number of times to repeat the failure */
  int nBenign;            /* Number of benign failures seen since last config */
  int nFail;              /* Number of failures seen since last config */
  u8 enable;              /* True if enabled */
  int isInstalled;        /* True if the fault simulation layer is installed */
  sqlite3_mem_methods m;  /* 'Real' malloc implementation */
} memfault;

/*
** This routine exists as a place to set a breakpoint that will
** fire on any simulated malloc() failure.
*/
static void sqlite3Fault(void){
  static int cnt = 0;
  cnt++;
}

/*
** Check to see if a fault should be simulated.  Return true to simulate
** the fault.  Return false if the fault should not be simulated.
*/
static int faultsimStep(){
  if( likely(!memfault.enable) ){
    return 0;
  }
  if( memfault.iCountdown>0 ){
    memfault.iCountdown--;
    return 0;
  }
  sqlite3Fault();
  memfault.nFail++;
  if( sqlite3FaultIsBenign()>0 ){
    memfault.nBenign++;
  }
  memfault.nRepeat--;
  if( memfault.nRepeat<=0 ){
    memfault.enable = 0;
  }
  return 1;  
}

/*
** A version of sqlite3_mem_methods.xMalloc() that includes fault simulation
** logic.
*/
static void *faultsimMalloc(int n){
  void *p = 0;
  if( !faultsimStep() ){
    p = memfault.m.xMalloc(n);
  }
  return p;
}


/*
** A version of sqlite3_mem_methods.xRealloc() that includes fault simulation
** logic.
*/
static void *faultsimRealloc(void *pOld, int n){
  void *p = 0;
  if( !faultsimStep() ){
    p = memfault.m.xRealloc(pOld, n);
  }
  return p;
}

/* 
** The following method calls are passed directly through to the underlying
** malloc system:
**
**     xFree
**     xSize
**     xRoundup
**     xInit
**     xShutdown
*/
static void faultsimFree(void *p){
  memfault.m.xFree(p);
}
static int faultsimSize(void *p){
  return memfault.m.xSize(p);
}
static int faultsimRoundup(int n){
  return memfault.m.xRoundup(n);
}
static int faultsimInit(void *p){
  return memfault.m.xInit(memfault.m.pAppData);
}
static void faultsimShutdown(void *p){
  memfault.m.xShutdown(memfault.m.pAppData);
}

/*
** This routine configures the malloc failure simulation.  After
** calling this routine, the next nDelay mallocs will succeed, followed
** by a block of nRepeat failures, after which malloc() calls will begin
** to succeed again.
*/
static void faultsimConfig(int nDelay, int nRepeat){
  memfault.iCountdown = nDelay;
  memfault.nRepeat = nRepeat;
  memfault.nBenign = 0;
  memfault.nFail = 0;
  memfault.enable = nDelay>=0;
}

/*
** Return the number of faults (both hard and benign faults) that have
** occurred since the injector was last configured.
*/
static int faultsimFailures(void){
  return memfault.nFail;
}

/*
** Return the number of benign faults that have occurred since the
** injector was last configured.
*/
static int faultsimBenignFailures(void){
  return memfault.nBenign;
}

/*
** Return the number of successes that will occur before the next failure.
** If no failures are scheduled, return -1.
*/
static int faultsimPending(void){
  if( memfault.enable ){
    return memfault.iCountdown;
  }else{
    return -1;
  }
}

/*
** Add or remove the fault-simulation layer using sqlite3_config(). If
** the argument is non-zero, the 
*/
static int faultsimInstall(int install){
  static struct sqlite3_mem_methods m = {
    faultsimMalloc,                   /* xMalloc */
    faultsimFree,                     /* xFree */
    faultsimRealloc,                  /* xRealloc */
    faultsimSize,                     /* xSize */
    faultsimRoundup,                  /* xRoundup */
    faultsimInit,                     /* xInit */
    faultsimShutdown,                 /* xShutdown */
    0                                 /* pAppData */
  };
  int rc;

  install = (install ? 1 : 0);
  assert(memfault.isInstalled==1 || memfault.isInstalled==0);

  if( install==memfault.isInstalled ){
    return SQLITE_ERROR;
  }

  rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memfault.m);
  assert(memfault.m.xMalloc);
  if( rc==SQLITE_OK ){
    rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &m);
  }

  if( rc==SQLITE_OK ){
    memfault.isInstalled = 1;
  }
  return rc;
}

#ifdef SQLITE_TEST

/*
** This function is implemented in test1.c. Returns a pointer to a static
** buffer containing the symbolic SQLite error code that corresponds to
** the least-significant 8-bits of the integer passed as an argument.
** For example:
**
**   sqlite3TestErrorName(1) -> "SQLITE_ERROR"
*/
const char *sqlite3TestErrorName(int);

/*
** Transform pointers to text and back again
*/
static void pointerToText(void *p, char *z){
  static const char zHex[] = "0123456789abcdef";
................................................................................
    return TCL_ERROR;
  }
  p = sqlite3_realloc(pPrior, (unsigned)nByte);
  pointerToText(p, zOut);
  Tcl_AppendResult(interp, zOut, NULL);
  return TCL_OK;
}


/*
** Usage:    sqlite3_free  PRIOR
**
** Raw test interface for sqlite3_free().
*/
static int test_free(
................................................................................

    if( zErr ){
      Tcl_AppendResult(interp, zErr, zOption, 0);
      return TCL_ERROR;
    }
  }
  
  nBenign = faultsimBenignFailures();
  nFail = faultsimFailures();




  faultsimConfig(iFail, nRepeat);

  if( pBenignCnt ){
    Tcl_ObjSetVar2(interp, pBenignCnt, 0, Tcl_NewIntObj(nBenign), 0);
  }
  Tcl_SetObjResult(interp, Tcl_NewIntObj(nFail));
  return TCL_OK;
}

................................................................................
  Tcl_Obj *CONST objv[]
){
  int nPending;
  if( objc!=1 ){
    Tcl_WrongNumArgs(interp, 1, objv, "");
    return TCL_ERROR;
  }
  nPending = faultsimPending();

  Tcl_SetObjResult(interp, Tcl_NewIntObj(nPending));
  return TCL_OK;
}


/*
** Usage:    sqlite3_memdebug_settitle TITLE
................................................................................
  if( objc!=2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
    return TCL_ERROR;
  }
  if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[1], &isInstall) ){
    return TCL_ERROR;
  }
  rc = faultsimInstall(isInstall);
  Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
  return TCL_OK;
}

/*
** Register commands with the TCL interpreter.
*/
................................................................................
  };
  int i;
  for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
    Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
  }
  return TCL_OK;
}
#endif