SQLite

Changes On Branch malloc-testing
Login

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

Changes In Branch malloc-testing Excluding Merge-Ins

This is equivalent to a diff from 6e4ac0be to 64f2cb8d

2015-09-25
20:49
Fix PRAGMA integrity_check so that it works with a UNIQUE index over expressions. (check-in: 113181ce user: drh tags: trunk)
20:18
Fix a faulty assert() on the benign-malloc controller callback in test_malloc.c. (Leaf check-in: 64f2cb8d user: drh tags: malloc-testing)
16:29
Disable the SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS mechanism and replace it with SQLITE_TESTCTRL_BENIGN_MALLOC_CTRL, which gives better control. (check-in: 2c57b2f3 user: drh tags: malloc-testing)
13:42
Report an error if the number of named columns in a VIEW is different from the number of result columns in the SELECT statement that implements the VIEW. (check-in: 6e4ac0be user: drh tags: trunk)
01:09
Fix a problem computing affinities for indexes during skip-scan code generation when SQLITE_ENABLE_STAT4 is on. Bug introduced by check-in [1ee089a72d789002]. (check-in: 1350dd42 user: drh tags: trunk)

Changes to src/fault.c.

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
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







-
+

-
-
-
-
+
+
-
-
-
-
-
+
+
+
+
+
+
+
-
-
+
+
+

-
-
-
+
-
-
-
-
+
-
-
+


+
+
+
-
-
+
+
+
+
-
-
-
-
+
-
-
-
-



-
+
-
-
+

-
-
-
-
-
-
-
+
-
-
-
+
-



*/

#include "sqliteInt.h"

#ifndef SQLITE_OMIT_BUILTIN_TEST

/*
** Global variables.
** The default xBenignCtrl function is a no-op
*/
typedef struct BenignMallocHooks BenignMallocHooks;
static SQLITE_WSD struct BenignMallocHooks {
  void (*xBenignBegin)(void);
  void (*xBenignEnd)(void);
static void sqlite3BenignCtrlNoop(int eOp){
  (void)eOp;
} sqlite3Hooks = { 0, 0 };

/* The "wsdHooks" macro will resolve to the appropriate BenignMallocHooks
** structure.  If writable static data is unsupported on the target,
** we have to locate the state vector at run-time.  In the more common
}

/*
** Global variable:  Pointer to the benign malloc control interface.
*/
static void (*sqlite3xBenignCtrl)(int) = sqlite3BenignCtrlNoop;

** case where writable static data is supported, wsdHooks can refer directly
** to the "sqlite3Hooks" state vector declared above.
/*
** Register a pointer to the benign-malloc control interface function.
** If the argument is a NULL pointer, register the default no-op controller.
*/
#ifdef SQLITE_OMIT_WSD
# define wsdHooksInit \
  BenignMallocHooks *x = &GLOBAL(BenignMallocHooks,sqlite3Hooks)
void sqlite3BenignMallocHooks(void (*xBenignCtrl)(int)){
# define wsdHooks x[0]
#else
# define wsdHooksInit
# define wsdHooks sqlite3Hooks
  sqlite3xBenignCtrl = xBenignCtrl ? xBenignCtrl : sqlite3BenignCtrlNoop;
#endif

}

/*
** The sqlite3BeginBenignMalloc() and sqlite3EndBenignMalloc() calls bracket
** sections of code for which malloc failures are non-fatal.  
*/
** Register hooks to call when sqlite3BeginBenignMalloc() and
** sqlite3EndBenignMalloc() are called, respectively.
void sqlite3BeginBenignMalloc(void){
  sqlite3xBenignCtrl(1);
}
void sqlite3EndBenignMalloc(void){
*/
void sqlite3BenignMallocHooks(
  void (*xBenignBegin)(void),
  void (*xBenignEnd)(void)
  sqlite3xBenignCtrl(0);
){
  wsdHooksInit;
  wsdHooks.xBenignBegin = xBenignBegin;
  wsdHooks.xBenignEnd = xBenignEnd;
}

/*
** This (sqlite3EndBenignMalloc()) is called by SQLite code to indicate that
** The sqlite3PreviousBenignMalloc() call indicates that the previous
** subsequent malloc failures are benign. A call to sqlite3EndBenignMalloc()
** indicates that subsequent malloc failures are non-benign.
** malloc call (which must have failed) was a benign failure.
*/
void sqlite3BeginBenignMalloc(void){
  wsdHooksInit;
  if( wsdHooks.xBenignBegin ){
    wsdHooks.xBenignBegin();
  }
}
void sqlite3EndBenignMalloc(void){
void sqlite3PreviousBenignMalloc(void){
  wsdHooksInit;
  if( wsdHooks.xBenignEnd ){
    wsdHooks.xBenignEnd();
  sqlite3xBenignCtrl(2);
  }
}

#endif   /* #ifndef SQLITE_OMIT_BUILTIN_TEST */

Changes to src/hash.c.

114
115
116
117
118
119
120
121
122

123
124



125
126
127
128
129
130
131
132
114
115
116
117
118
119
120

121
122


123
124
125

126
127
128
129
130
131
132







-

+
-
-
+
+
+
-







  ** a performance hit but it is not a fatal error.  So mark the
  ** allocation as a benign. Use sqlite3Malloc()/memset(0) instead of 
  ** sqlite3MallocZero() to make the allocation, as sqlite3MallocZero()
  ** only zeroes the requested number of bytes whereas this module will
  ** use the actual amount of space allocated for the hash table (which
  ** may be larger than the requested amount).
  */
  sqlite3BeginBenignMalloc();
  new_ht = (struct _ht *)sqlite3Malloc( new_size*sizeof(struct _ht) );
  if( new_ht==0 ){
  sqlite3EndBenignMalloc();

    sqlite3PreviousBenignMalloc();
    return 0;
  }
  if( new_ht==0 ) return 0;
  sqlite3_free(pH->ht);
  pH->ht = new_ht;
  pH->htsize = new_size = sqlite3MallocSize(new_ht)/sizeof(struct _ht);
  memset(new_ht, 0, new_size*sizeof(struct _ht));
  for(elem=pH->first, pH->first=0; elem; elem = next_elem){
    unsigned int h = strHash(elem->pKey) % new_size;
    next_elem = elem->next;

Changes to src/main.c.

660
661
662
663
664
665
666
667
668

669
670




671
672
673
674
675
676
677
660
661
662
663
664
665
666

667
668


669
670
671
672
673
674
675
676
677
678
679







-

+
-
-
+
+
+
+







  sz = ROUNDDOWN8(sz);  /* IMP: R-33038-09382 */
  if( sz<=(int)sizeof(LookasideSlot*) ) sz = 0;
  if( cnt<0 ) cnt = 0;
  if( sz==0 || cnt==0 ){
    sz = 0;
    pStart = 0;
  }else if( pBuf==0 ){
    sqlite3BeginBenignMalloc();
    pStart = sqlite3Malloc( sz*cnt );  /* IMP: R-61949-35727 */
    if( pStart==0 ){
    sqlite3EndBenignMalloc();
    if( pStart ) cnt = sqlite3MallocSize(pStart)/sz;
      sqlite3PreviousBenignMalloc();
    }else{
      cnt = sqlite3MallocSize(pStart)/sz;
    }
  }else{
    pStart = pBuf;
  }
  db->lookaside.pStart = pStart;
  db->lookaside.pFree = 0;
  db->lookaside.sz = (u16)sz;
  if( pStart ){
3436
3437
3438
3439
3440
3441
3442
3443

3444
3445
3446




3447
3448
3449
3450



3451
3452
3453
3454


3455
3456
3457
3458
3459
3460
3461
3438
3439
3440
3441
3442
3443
3444

3445
3446


3447
3448
3449
3450
3451



3452
3453
3454




3455
3456
3457
3458
3459
3460
3461
3462
3463







-
+

-
-
+
+
+
+

-
-
-
+
+
+
-
-
-
-
+
+







      typedef int(*TESTCALLBACKFUNC_t)(int);
      sqlite3GlobalConfig.xTestCallback = va_arg(ap, TESTCALLBACKFUNC_t);
      rc = sqlite3FaultSim(0);
      break;
    }

    /*
    **  sqlite3_test_control(BENIGN_MALLOC_HOOKS, xBegin, xEnd)
    **  sqlite3_test_control(BENIGN_MALLOC_CTRL, xCtrl)
    **
    ** Register hooks to call to indicate which malloc() failures 
    ** are benign.
    ** Register a callback function that will handle calls to
    ** sqlite3BeginBenignMalloc(), sqlite3EndBenignMalloc(), and
    ** sqlite3PreviousBenignMalloc().  If the callback function pointer
    ** is NULL, then a built-in default (no-op) handler is used.
    */
    case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: {
      typedef void (*void_function)(void);
      void_function xBenignBegin;
    case SQLITE_TESTCTRL_BENIGN_MALLOC_CTRL: {
      typedef void (*void_function)(int);
      void_function xBenignCtrl;
      void_function xBenignEnd;
      xBenignBegin = va_arg(ap, void_function);
      xBenignEnd = va_arg(ap, void_function);
      sqlite3BenignMallocHooks(xBenignBegin, xBenignEnd);
      xBenignCtrl = va_arg(ap, void_function);
      sqlite3BenignMallocHooks(xBenignCtrl);
      break;
    }

    /*
    **  sqlite3_test_control(SQLITE_TESTCTRL_PENDING_BYTE, unsigned int X)
    **
    ** Set the PENDING byte to the value in the argument, if X>0.

Changes to src/malloc.c.

522
523
524
525
526
527
528

529
530
531
532
533
534
535
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536







+







    nDiff = nNew - nOld;
    if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >= 
          mem0.alarmThreshold-nDiff ){
      sqlite3MallocAlarm(nDiff);
    }
    pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
    if( pNew==0 && mem0.alarmThreshold>0 ){
      sqlite3PreviousBenignMalloc();
      sqlite3MallocAlarm((int)nBytes);
      pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
    }
    if( pNew ){
      nNew = sqlite3MallocSize(pNew);
      sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
    }

Changes to src/pcache1.c.

268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286



287
288
289
290
291
292
293
268
269
270
271
272
273
274

275
276
277
278
279
280
281
282
283


284
285
286
287
288
289
290
291
292
293







-









-
-
+
+
+







*/
static int pcache1InitBulk(PCache1 *pCache){
  i64 szBulk;
  char *zBulk;
  if( pcache1.nInitPage==0 ) return 0;
  /* Do not bother with a bulk allocation if the cache size very small */
  if( pCache->nMax<3 ) return 0;
  sqlite3BeginBenignMalloc();
  if( pcache1.nInitPage>0 ){
    szBulk = pCache->szAlloc * (i64)pcache1.nInitPage;
  }else{
    szBulk = -1024 * (i64)pcache1.nInitPage;
  }
  if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){
    szBulk = pCache->szAlloc*pCache->nMax;
  }
  zBulk = pCache->pBulk = sqlite3Malloc( szBulk );
  sqlite3EndBenignMalloc();
  if( zBulk ){
  if( zBulk==0 ){
    sqlite3PreviousBenignMalloc();
  }else{
    int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
    int i;
    for(i=0; i<nBulk; i++){
      PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage];
      pX->page.pBuf = zBulk;
      pX->page.pExtra = &pX[1];
      pX->isBulkLocal = 1;

Changes to src/shell.c.

3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3795
3796
3797
3798
3799
3800
3801

3802
3803
3804
3805
3806
3807
3808







-







       int ctrlCode;            /* Integer code for that option */
    } aCtrl[] = {
      { "prng_save",             SQLITE_TESTCTRL_PRNG_SAVE              },
      { "prng_restore",          SQLITE_TESTCTRL_PRNG_RESTORE           },
      { "prng_reset",            SQLITE_TESTCTRL_PRNG_RESET             },
      { "bitvec_test",           SQLITE_TESTCTRL_BITVEC_TEST            },
      { "fault_install",         SQLITE_TESTCTRL_FAULT_INSTALL          },
      { "benign_malloc_hooks",   SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS    },
      { "pending_byte",          SQLITE_TESTCTRL_PENDING_BYTE           },
      { "assert",                SQLITE_TESTCTRL_ASSERT                 },
      { "always",                SQLITE_TESTCTRL_ALWAYS                 },
      { "reserve",               SQLITE_TESTCTRL_RESERVE                },
      { "optimizations",         SQLITE_TESTCTRL_OPTIMIZATIONS          },
      { "iskeyword",             SQLITE_TESTCTRL_ISKEYWORD              },
      { "scratchmalloc",         SQLITE_TESTCTRL_SCRATCHMALLOC          },
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3909
3910
3911
3912
3913
3914
3915




3916
3917
3918
3919
3920
3921
3922







-
-
-
-







                          integerValue(azArg[4]));
            fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
          }else{
            fprintf(stderr,"Usage: .testctrl imposter dbName onoff tnum\n");
          }
          break;

        case SQLITE_TESTCTRL_BITVEC_TEST:         
        case SQLITE_TESTCTRL_FAULT_INSTALL:       
        case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: 
        case SQLITE_TESTCTRL_SCRATCHMALLOC:       
        default:
          fprintf(stderr,"Error: CLI support for testctrl %s not implemented\n",
                  azArg[1]);
          break;
      }
    }
  }else

Changes to src/sqlite.h.in.

6414
6415
6416
6417
6418
6419
6420
6421

6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436

6437

6438
6439
6440
6441
6442
6443
6444
6414
6415
6416
6417
6418
6419
6420

6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437

6438
6439
6440
6441
6442
6443
6444
6445







-
+















+
-
+







*/
#define SQLITE_TESTCTRL_FIRST                    5
#define SQLITE_TESTCTRL_PRNG_SAVE                5
#define SQLITE_TESTCTRL_PRNG_RESTORE             6
#define SQLITE_TESTCTRL_PRNG_RESET               7
#define SQLITE_TESTCTRL_BITVEC_TEST              8
#define SQLITE_TESTCTRL_FAULT_INSTALL            9
#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS     10
#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS     10  /* NOT USED */
#define SQLITE_TESTCTRL_PENDING_BYTE            11
#define SQLITE_TESTCTRL_ASSERT                  12
#define SQLITE_TESTCTRL_ALWAYS                  13
#define SQLITE_TESTCTRL_RESERVE                 14
#define SQLITE_TESTCTRL_OPTIMIZATIONS           15
#define SQLITE_TESTCTRL_ISKEYWORD               16
#define SQLITE_TESTCTRL_SCRATCHMALLOC           17
#define SQLITE_TESTCTRL_LOCALTIME_FAULT         18
#define SQLITE_TESTCTRL_EXPLAIN_STMT            19  /* NOT USED */
#define SQLITE_TESTCTRL_NEVER_CORRUPT           20
#define SQLITE_TESTCTRL_VDBE_COVERAGE           21
#define SQLITE_TESTCTRL_BYTEORDER               22
#define SQLITE_TESTCTRL_ISINIT                  23
#define SQLITE_TESTCTRL_SORTER_MMAP             24
#define SQLITE_TESTCTRL_IMPOSTER                25
#define SQLITE_TESTCTRL_BENIGN_MALLOC_CTRL      26
#define SQLITE_TESTCTRL_LAST                    25
#define SQLITE_TESTCTRL_LAST                    26

/*
** CAPI3REF: SQLite Runtime Status
**
** ^These interfaces are used to retrieve runtime status information
** about the performance of SQLite, and optionally to reset various
** highwater marks.  ^The first argument is an integer code for

Changes to src/sqliteInt.h.

3152
3153
3154
3155
3156
3157
3158
3159

3160
3161
3162
3163
3164
3165
3166
3152
3153
3154
3155
3156
3157
3158

3159
3160
3161
3162
3163
3164
3165
3166







-
+







int sqlite3DbMallocSize(sqlite3*, void*);
void *sqlite3ScratchMalloc(int);
void sqlite3ScratchFree(void*);
void *sqlite3PageMalloc(int);
void sqlite3PageFree(void*);
void sqlite3MemSetDefault(void);
#ifndef SQLITE_OMIT_BUILTIN_TEST
void sqlite3BenignMallocHooks(void (*)(void), void (*)(void));
void sqlite3BenignMallocHooks(void (*)(int));
#endif
int sqlite3HeapNearlyFull(void);

/*
** On systems with ample stack space and that support alloca(), make
** use of alloca() to obtain space for large automatic objects.  By default,
** obtain space from malloc().
3832
3833
3834
3835
3836
3837
3838

3839
3840
3841

3842
3843
3844
3845
3846
3847
3848
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850







+



+







** 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 sqlite3BeginBenignMalloc(void);
  void sqlite3EndBenignMalloc(void);
  void sqlite3PreviousBenignMalloc(void);
#else
  #define sqlite3BeginBenignMalloc()
  #define sqlite3EndBenignMalloc()
  #define sqlite3PreviousBenignMalloc()
#endif

/*
** Allowed return values from sqlite3FindInIndex()
*/
#define IN_INDEX_ROWID        1   /* Search the rowid of the table */
#define IN_INDEX_EPH          2   /* Search an ephemeral b-tree */

Changes to src/test_malloc.c.

165
166
167
168
169
170
171
172
173
174
175





















176
177
178
179
180
181
182
183
184
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







-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-







  if( memfault.enable ){
    return memfault.iCountdown;
  }else{
    return -1;
  }
}


static void faultsimBeginBenign(void){
  memfault.isBenignMode++;
}
/*
** The SQLITE_TESTCTRL_BENIGN_MALLOC_CTRL callback.  The eOp argument means:
**
**     0:      Leave benign malloc mode
**     1:      Enter benign malloc mode (may be nested)
**     2:      Make the previous malloc failure benign if it was not already so
*/
static void faultsimBenignCtrl(int eOp){
  switch( eOp ){
    case 0:    /* Leave benign malloc mode */
      assert( memfault.isBenignMode>0 );
      memfault.isBenignMode--;
      break;
    case 1:    /* Enter benign malloc mode */
      memfault.isBenignMode++;
      break;
    case 2:    /* Previous failure is benign */
      assert( memfault.nFail>0 || memfault.enable==0 );
      if( memfault.isBenignMode==0 ) memfault.nBenign++;
      break;
  }
static void faultsimEndBenign(void){
  memfault.isBenignMode--;
}

/*
** Add or remove the fault-simulation layer using sqlite3_config(). If
** the argument is non-zero, the 
*/
static int faultsimInstall(int install){
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
218
219
220
221
222
223
224


225
226

227
228
229
230
231
232
233
234
235
236
237
238

239
240
241
242
243
244
245
246







-
-
+
+
-












-
+








  if( install ){
    rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memfault.m);
    assert(memfault.m.xMalloc);
    if( rc==SQLITE_OK ){
      rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &m);
    }
    sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, 
        faultsimBeginBenign, faultsimEndBenign
    sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_CTRL, 
                        faultsimBenignCtrl);
    );
  }else{
    sqlite3_mem_methods m2;
    assert(memfault.m.xMalloc);

    /* One should be able to reset the default memory allocator by storing
    ** a zeroed allocator then calling GETMALLOC. */
    memset(&m2, 0, sizeof(m2));
    sqlite3_config(SQLITE_CONFIG_MALLOC, &m2);
    sqlite3_config(SQLITE_CONFIG_GETMALLOC, &m2);
    assert( memcmp(&m2, &memfault.m, sizeof(m2))==0 );

    rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memfault.m);
    sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, 0, 0);
    sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_CTRL, 0);
  }

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