xref: /sqlite-3.40.0/src/test_malloc.c (revision 643167ff)
12f999a67Sdrh /*
22f999a67Sdrh ** 2007 August 15
32f999a67Sdrh **
42f999a67Sdrh ** The author disclaims copyright to this source code.  In place of
52f999a67Sdrh ** a legal notice, here is a blessing:
62f999a67Sdrh **
72f999a67Sdrh **    May you do good and not evil.
82f999a67Sdrh **    May you find forgiveness for yourself and forgive others.
92f999a67Sdrh **    May you share freely, never taking more than you give.
102f999a67Sdrh **
112f999a67Sdrh *************************************************************************
122f999a67Sdrh **
132f999a67Sdrh ** This file contains code used to implement test interfaces to the
142f999a67Sdrh ** memory allocation subsystem.
152f999a67Sdrh **
16*643167ffSdrh ** $Id: test_malloc.c,v 1.10 2008/01/22 21:30:53 drh Exp $
172f999a67Sdrh */
182f999a67Sdrh #include "sqliteInt.h"
192f999a67Sdrh #include "tcl.h"
202f999a67Sdrh #include <stdlib.h>
212f999a67Sdrh #include <string.h>
222f999a67Sdrh #include <assert.h>
232f999a67Sdrh 
242f999a67Sdrh /*
252f999a67Sdrh ** Transform pointers to text and back again
262f999a67Sdrh */
272f999a67Sdrh static void pointerToText(void *p, char *z){
282f999a67Sdrh   static const char zHex[] = "0123456789abcdef";
292f999a67Sdrh   int i, k;
304a50aac5Sdrh   unsigned int u;
314a50aac5Sdrh   sqlite3_uint64 n;
324a50aac5Sdrh   if( sizeof(n)==sizeof(p) ){
334a50aac5Sdrh     memcpy(&n, &p, sizeof(p));
344a50aac5Sdrh   }else if( sizeof(u)==sizeof(p) ){
354a50aac5Sdrh     memcpy(&u, &p, sizeof(u));
364a50aac5Sdrh     n = u;
374a50aac5Sdrh   }else{
384a50aac5Sdrh     assert( 0 );
394a50aac5Sdrh   }
402f999a67Sdrh   for(i=0, k=sizeof(p)*2-1; i<sizeof(p)*2; i++, k--){
412f999a67Sdrh     z[k] = zHex[n&0xf];
422f999a67Sdrh     n >>= 4;
432f999a67Sdrh   }
442f999a67Sdrh   z[sizeof(p)*2] = 0;
452f999a67Sdrh }
462f999a67Sdrh static int hexToInt(int h){
472f999a67Sdrh   if( h>='0' && h<='9' ){
482f999a67Sdrh     return h - '0';
492f999a67Sdrh   }else if( h>='a' && h<='f' ){
502f999a67Sdrh     return h - 'a' + 10;
512f999a67Sdrh   }else{
522f999a67Sdrh     return -1;
532f999a67Sdrh   }
542f999a67Sdrh }
552f999a67Sdrh static int textToPointer(const char *z, void **pp){
562f999a67Sdrh   sqlite3_uint64 n = 0;
572f999a67Sdrh   int i;
584a50aac5Sdrh   unsigned int u;
592f999a67Sdrh   for(i=0; i<sizeof(void*)*2 && z[0]; i++){
602f999a67Sdrh     int v;
612f999a67Sdrh     v = hexToInt(*z++);
622f999a67Sdrh     if( v<0 ) return TCL_ERROR;
632f999a67Sdrh     n = n*16 + v;
642f999a67Sdrh   }
652f999a67Sdrh   if( *z!=0 ) return TCL_ERROR;
664a50aac5Sdrh   if( sizeof(n)==sizeof(*pp) ){
674a50aac5Sdrh     memcpy(pp, &n, sizeof(n));
684a50aac5Sdrh   }else if( sizeof(u)==sizeof(*pp) ){
694a50aac5Sdrh     u = (unsigned int)n;
704a50aac5Sdrh     memcpy(pp, &u, sizeof(u));
714a50aac5Sdrh   }else{
724a50aac5Sdrh     assert( 0 );
734a50aac5Sdrh   }
742f999a67Sdrh   return TCL_OK;
752f999a67Sdrh }
762f999a67Sdrh 
772f999a67Sdrh /*
782f999a67Sdrh ** Usage:    sqlite3_malloc  NBYTES
792f999a67Sdrh **
802f999a67Sdrh ** Raw test interface for sqlite3_malloc().
812f999a67Sdrh */
822f999a67Sdrh static int test_malloc(
832f999a67Sdrh   void * clientData,
842f999a67Sdrh   Tcl_Interp *interp,
852f999a67Sdrh   int objc,
862f999a67Sdrh   Tcl_Obj *CONST objv[]
872f999a67Sdrh ){
882f999a67Sdrh   int nByte;
892f999a67Sdrh   void *p;
902f999a67Sdrh   char zOut[100];
912f999a67Sdrh   if( objc!=2 ){
922f999a67Sdrh     Tcl_WrongNumArgs(interp, 1, objv, "NBYTES");
932f999a67Sdrh     return TCL_ERROR;
942f999a67Sdrh   }
952f999a67Sdrh   if( Tcl_GetIntFromObj(interp, objv[1], &nByte) ) return TCL_ERROR;
962f999a67Sdrh   p = sqlite3_malloc((unsigned)nByte);
972f999a67Sdrh   pointerToText(p, zOut);
982f999a67Sdrh   Tcl_AppendResult(interp, zOut, NULL);
992f999a67Sdrh   return TCL_OK;
1002f999a67Sdrh }
1012f999a67Sdrh 
1022f999a67Sdrh /*
1032f999a67Sdrh ** Usage:    sqlite3_realloc  PRIOR  NBYTES
1042f999a67Sdrh **
1052f999a67Sdrh ** Raw test interface for sqlite3_realloc().
1062f999a67Sdrh */
1072f999a67Sdrh static int test_realloc(
1082f999a67Sdrh   void * clientData,
1092f999a67Sdrh   Tcl_Interp *interp,
1102f999a67Sdrh   int objc,
1112f999a67Sdrh   Tcl_Obj *CONST objv[]
1122f999a67Sdrh ){
1132f999a67Sdrh   int nByte;
1142f999a67Sdrh   void *pPrior, *p;
1152f999a67Sdrh   char zOut[100];
1162f999a67Sdrh   if( objc!=3 ){
1172f999a67Sdrh     Tcl_WrongNumArgs(interp, 1, objv, "PRIOR NBYTES");
1182f999a67Sdrh     return TCL_ERROR;
1192f999a67Sdrh   }
1202f999a67Sdrh   if( Tcl_GetIntFromObj(interp, objv[2], &nByte) ) return TCL_ERROR;
1212f999a67Sdrh   if( textToPointer(Tcl_GetString(objv[1]), &pPrior) ){
1222f999a67Sdrh     Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);
1232f999a67Sdrh     return TCL_ERROR;
1242f999a67Sdrh   }
1252f999a67Sdrh   p = sqlite3_realloc(pPrior, (unsigned)nByte);
1262f999a67Sdrh   pointerToText(p, zOut);
1272f999a67Sdrh   Tcl_AppendResult(interp, zOut, NULL);
1282f999a67Sdrh   return TCL_OK;
1292f999a67Sdrh }
1302f999a67Sdrh 
1312f999a67Sdrh 
1322f999a67Sdrh /*
1332f999a67Sdrh ** Usage:    sqlite3_free  PRIOR
1342f999a67Sdrh **
1352f999a67Sdrh ** Raw test interface for sqlite3_free().
1362f999a67Sdrh */
1372f999a67Sdrh static int test_free(
1382f999a67Sdrh   void * clientData,
1392f999a67Sdrh   Tcl_Interp *interp,
1402f999a67Sdrh   int objc,
1412f999a67Sdrh   Tcl_Obj *CONST objv[]
1422f999a67Sdrh ){
1432f999a67Sdrh   void *pPrior;
1442f999a67Sdrh   if( objc!=2 ){
1452f999a67Sdrh     Tcl_WrongNumArgs(interp, 1, objv, "PRIOR");
1462f999a67Sdrh     return TCL_ERROR;
1472f999a67Sdrh   }
1482f999a67Sdrh   if( textToPointer(Tcl_GetString(objv[1]), &pPrior) ){
1492f999a67Sdrh     Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);
1502f999a67Sdrh     return TCL_ERROR;
1512f999a67Sdrh   }
1522f999a67Sdrh   sqlite3_free(pPrior);
1532f999a67Sdrh   return TCL_OK;
1542f999a67Sdrh }
1552f999a67Sdrh 
1562f999a67Sdrh /*
1579c7a60dfSdrh ** These routines are in test_hexio.c
1589c7a60dfSdrh */
1599c7a60dfSdrh int sqlite3TestHexToBin(const char *, int, char *);
1609c7a60dfSdrh int sqlite3TestBinToHex(char*,int);
1619c7a60dfSdrh 
1629c7a60dfSdrh /*
1639c7a60dfSdrh ** Usage:    memset  ADDRESS  SIZE  HEX
1649c7a60dfSdrh **
1659c7a60dfSdrh ** Set a chunk of memory (obtained from malloc, probably) to a
1669c7a60dfSdrh ** specified hex pattern.
1679c7a60dfSdrh */
1689c7a60dfSdrh static int test_memset(
1699c7a60dfSdrh   void * clientData,
1709c7a60dfSdrh   Tcl_Interp *interp,
1719c7a60dfSdrh   int objc,
1729c7a60dfSdrh   Tcl_Obj *CONST objv[]
1739c7a60dfSdrh ){
1749c7a60dfSdrh   void *p;
1759c7a60dfSdrh   int size, n, i;
1769c7a60dfSdrh   char *zHex;
1779c7a60dfSdrh   char *zOut;
1789c7a60dfSdrh   char zBin[100];
1799c7a60dfSdrh 
1809c7a60dfSdrh   if( objc!=4 ){
1819c7a60dfSdrh     Tcl_WrongNumArgs(interp, 1, objv, "ADDRESS SIZE HEX");
1829c7a60dfSdrh     return TCL_ERROR;
1839c7a60dfSdrh   }
1849c7a60dfSdrh   if( textToPointer(Tcl_GetString(objv[1]), &p) ){
1859c7a60dfSdrh     Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);
1869c7a60dfSdrh     return TCL_ERROR;
1879c7a60dfSdrh   }
1889c7a60dfSdrh   if( Tcl_GetIntFromObj(interp, objv[2], &size) ){
1899c7a60dfSdrh     return TCL_ERROR;
1909c7a60dfSdrh   }
1919c7a60dfSdrh   if( size<=0 ){
1929c7a60dfSdrh     Tcl_AppendResult(interp, "size must be positive", (char*)0);
1939c7a60dfSdrh     return TCL_ERROR;
1949c7a60dfSdrh   }
1959c7a60dfSdrh   zHex = Tcl_GetStringFromObj(objv[3], &n);
1969c7a60dfSdrh   if( n>sizeof(zBin)*2 ) n = sizeof(zBin)*2;
1979c7a60dfSdrh   n = sqlite3TestHexToBin(zHex, n, zBin);
1989c7a60dfSdrh   if( n==0 ){
1999c7a60dfSdrh     Tcl_AppendResult(interp, "no data", (char*)0);
2009c7a60dfSdrh     return TCL_ERROR;
2019c7a60dfSdrh   }
2029c7a60dfSdrh   zOut = p;
2039c7a60dfSdrh   for(i=0; i<size; i++){
2049c7a60dfSdrh     zOut[i] = zBin[i%n];
2059c7a60dfSdrh   }
2069c7a60dfSdrh   return TCL_OK;
2079c7a60dfSdrh }
2089c7a60dfSdrh 
2099c7a60dfSdrh /*
2109c7a60dfSdrh ** Usage:    memget  ADDRESS  SIZE
2119c7a60dfSdrh **
2129c7a60dfSdrh ** Return memory as hexadecimal text.
2139c7a60dfSdrh */
2149c7a60dfSdrh static int test_memget(
2159c7a60dfSdrh   void * clientData,
2169c7a60dfSdrh   Tcl_Interp *interp,
2179c7a60dfSdrh   int objc,
2189c7a60dfSdrh   Tcl_Obj *CONST objv[]
2199c7a60dfSdrh ){
2209c7a60dfSdrh   void *p;
2219c7a60dfSdrh   int size, n;
2229c7a60dfSdrh   char *zBin;
2239c7a60dfSdrh   char zHex[100];
2249c7a60dfSdrh 
2259c7a60dfSdrh   if( objc!=3 ){
2269c7a60dfSdrh     Tcl_WrongNumArgs(interp, 1, objv, "ADDRESS SIZE");
2279c7a60dfSdrh     return TCL_ERROR;
2289c7a60dfSdrh   }
2299c7a60dfSdrh   if( textToPointer(Tcl_GetString(objv[1]), &p) ){
2309c7a60dfSdrh     Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);
2319c7a60dfSdrh     return TCL_ERROR;
2329c7a60dfSdrh   }
2339c7a60dfSdrh   if( Tcl_GetIntFromObj(interp, objv[2], &size) ){
2349c7a60dfSdrh     return TCL_ERROR;
2359c7a60dfSdrh   }
2369c7a60dfSdrh   if( size<=0 ){
2379c7a60dfSdrh     Tcl_AppendResult(interp, "size must be positive", (char*)0);
2389c7a60dfSdrh     return TCL_ERROR;
2399c7a60dfSdrh   }
2409c7a60dfSdrh   zBin = p;
2419c7a60dfSdrh   while( size>0 ){
2429c7a60dfSdrh     if( size>(sizeof(zHex)-1)/2 ){
2439c7a60dfSdrh       n = (sizeof(zHex)-1)/2;
2449c7a60dfSdrh     }else{
2459c7a60dfSdrh       n = size;
2469c7a60dfSdrh     }
2479c7a60dfSdrh     memcpy(zHex, zBin, n);
2489c7a60dfSdrh     zBin += n;
2499c7a60dfSdrh     size -= n;
2509c7a60dfSdrh     sqlite3TestBinToHex(zHex, n);
2519c7a60dfSdrh     Tcl_AppendResult(interp, zHex, (char*)0);
2529c7a60dfSdrh   }
2539c7a60dfSdrh   return TCL_OK;
2549c7a60dfSdrh }
2559c7a60dfSdrh 
2569c7a60dfSdrh /*
2572f999a67Sdrh ** Usage:    sqlite3_memory_used
2582f999a67Sdrh **
2592f999a67Sdrh ** Raw test interface for sqlite3_memory_used().
2602f999a67Sdrh */
2612f999a67Sdrh static int test_memory_used(
2622f999a67Sdrh   void * clientData,
2632f999a67Sdrh   Tcl_Interp *interp,
2642f999a67Sdrh   int objc,
2652f999a67Sdrh   Tcl_Obj *CONST objv[]
2662f999a67Sdrh ){
2672f999a67Sdrh   Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sqlite3_memory_used()));
2682f999a67Sdrh   return TCL_OK;
2692f999a67Sdrh }
2702f999a67Sdrh 
2712f999a67Sdrh /*
2722f999a67Sdrh ** Usage:    sqlite3_memory_highwater ?RESETFLAG?
2732f999a67Sdrh **
2742f999a67Sdrh ** Raw test interface for sqlite3_memory_highwater().
2752f999a67Sdrh */
2762f999a67Sdrh static int test_memory_highwater(
2772f999a67Sdrh   void * clientData,
2782f999a67Sdrh   Tcl_Interp *interp,
2792f999a67Sdrh   int objc,
2802f999a67Sdrh   Tcl_Obj *CONST objv[]
2812f999a67Sdrh ){
2822f999a67Sdrh   int resetFlag = 0;
2832f999a67Sdrh   if( objc!=1 && objc!=2 ){
2842f999a67Sdrh     Tcl_WrongNumArgs(interp, 1, objv, "?RESET?");
2852f999a67Sdrh     return TCL_ERROR;
2862f999a67Sdrh   }
2872f999a67Sdrh   if( objc==2 ){
2882f999a67Sdrh     if( Tcl_GetBooleanFromObj(interp, objv[1], &resetFlag) ) return TCL_ERROR;
2892f999a67Sdrh   }
2902f999a67Sdrh   Tcl_SetObjResult(interp,
2912f999a67Sdrh      Tcl_NewWideIntObj(sqlite3_memory_highwater(resetFlag)));
2922f999a67Sdrh   return TCL_OK;
2932f999a67Sdrh }
2942f999a67Sdrh 
2952f999a67Sdrh /*
2962f999a67Sdrh ** Usage:    sqlite3_memdebug_backtrace DEPTH
2972f999a67Sdrh **
2982f999a67Sdrh ** Set the depth of backtracing.  If SQLITE_MEMDEBUG is not defined
2992f999a67Sdrh ** then this routine is a no-op.
3002f999a67Sdrh */
3012f999a67Sdrh static int test_memdebug_backtrace(
3022f999a67Sdrh   void * clientData,
3032f999a67Sdrh   Tcl_Interp *interp,
3042f999a67Sdrh   int objc,
3052f999a67Sdrh   Tcl_Obj *CONST objv[]
3062f999a67Sdrh ){
3072f999a67Sdrh   int depth;
3082f999a67Sdrh   if( objc!=2 ){
3092f999a67Sdrh     Tcl_WrongNumArgs(interp, 1, objv, "DEPT");
3102f999a67Sdrh     return TCL_ERROR;
3112f999a67Sdrh   }
3122f999a67Sdrh   if( Tcl_GetIntFromObj(interp, objv[1], &depth) ) return TCL_ERROR;
3132f999a67Sdrh #ifdef SQLITE_MEMDEBUG
3142f999a67Sdrh   {
3152f999a67Sdrh     extern void sqlite3_memdebug_backtrace(int);
3162f999a67Sdrh     sqlite3_memdebug_backtrace(depth);
3172f999a67Sdrh   }
3182f999a67Sdrh #endif
3192f999a67Sdrh   return TCL_OK;
3202f999a67Sdrh }
3212f999a67Sdrh 
3222f999a67Sdrh /*
3232f999a67Sdrh ** Usage:    sqlite3_memdebug_dump  FILENAME
3242f999a67Sdrh **
3252f999a67Sdrh ** Write a summary of unfreed memory to FILENAME.
3262f999a67Sdrh */
3272f999a67Sdrh static int test_memdebug_dump(
3282f999a67Sdrh   void * clientData,
3292f999a67Sdrh   Tcl_Interp *interp,
3302f999a67Sdrh   int objc,
3312f999a67Sdrh   Tcl_Obj *CONST objv[]
3322f999a67Sdrh ){
3332f999a67Sdrh   if( objc!=2 ){
3342f999a67Sdrh     Tcl_WrongNumArgs(interp, 1, objv, "FILENAME");
3352f999a67Sdrh     return TCL_ERROR;
3362f999a67Sdrh   }
3379c7a60dfSdrh #if defined(SQLITE_MEMDEBUG) || defined(SQLITE_MEMORY_SIZE)
3382f999a67Sdrh   {
3392f999a67Sdrh     extern void sqlite3_memdebug_dump(const char*);
3402f999a67Sdrh     sqlite3_memdebug_dump(Tcl_GetString(objv[1]));
3412f999a67Sdrh   }
3422f999a67Sdrh #endif
3432f999a67Sdrh   return TCL_OK;
3442f999a67Sdrh }
3452f999a67Sdrh 
3462f999a67Sdrh 
3472f999a67Sdrh /*
348a1644fd8Sdanielk1977 ** Usage:    sqlite3_memdebug_fail  COUNTER  ?OPTIONS?
349a1644fd8Sdanielk1977 **
350a1644fd8Sdanielk1977 ** where options are:
351a1644fd8Sdanielk1977 **
352*643167ffSdrh **     -repeat    <count>
353a1644fd8Sdanielk1977 **     -benigncnt <varname>
3540e6f1546Sdrh **
3550e6f1546Sdrh ** Arrange for a simulated malloc() failure after COUNTER successes.
356*643167ffSdrh ** If a repeat count is specified, the fault is repeated that many
357*643167ffSdrh ** times.
3580e6f1546Sdrh **
3590e6f1546Sdrh ** Each call to this routine overrides the prior counter value.
3600e6f1546Sdrh ** This routine returns the number of simulated failures that have
3610e6f1546Sdrh ** happened since the previous call to this routine.
3620e6f1546Sdrh **
3630e6f1546Sdrh ** To disable simulated failures, use a COUNTER of -1.
3640e6f1546Sdrh */
3650e6f1546Sdrh static int test_memdebug_fail(
3660e6f1546Sdrh   void * clientData,
3670e6f1546Sdrh   Tcl_Interp *interp,
3680e6f1546Sdrh   int objc,
3690e6f1546Sdrh   Tcl_Obj *CONST objv[]
3700e6f1546Sdrh ){
371a1644fd8Sdanielk1977   int ii;
3720e6f1546Sdrh   int iFail;
373*643167ffSdrh   int nRepeat = 1;
374a1644fd8Sdanielk1977   Tcl_Obj *pBenignCnt = 0;
375*643167ffSdrh   int nBenign;
3760e6f1546Sdrh   int nFail = 0;
377a1644fd8Sdanielk1977 
378a1644fd8Sdanielk1977   if( objc<2 ){
379a1644fd8Sdanielk1977     Tcl_WrongNumArgs(interp, 1, objv, "COUNTER ?OPTIONS?");
3800e6f1546Sdrh     return TCL_ERROR;
3810e6f1546Sdrh   }
3820e6f1546Sdrh   if( Tcl_GetIntFromObj(interp, objv[1], &iFail) ) return TCL_ERROR;
383a1644fd8Sdanielk1977 
384a1644fd8Sdanielk1977   for(ii=2; ii<objc; ii+=2){
385a1644fd8Sdanielk1977     int nOption;
386a1644fd8Sdanielk1977     char *zOption = Tcl_GetStringFromObj(objv[ii], &nOption);
387a1644fd8Sdanielk1977     char *zErr = 0;
388a1644fd8Sdanielk1977 
389a1644fd8Sdanielk1977     if( nOption>1 && strncmp(zOption, "-repeat", nOption)==0 ){
390a1644fd8Sdanielk1977       if( ii==(objc-1) ){
391a1644fd8Sdanielk1977         zErr = "option requires an argument: ";
392ed138fb3Sdrh       }else{
393*643167ffSdrh         if( Tcl_GetIntFromObj(interp, objv[ii+1], &nRepeat) ){
394a1644fd8Sdanielk1977           return TCL_ERROR;
395ed138fb3Sdrh         }
396a1644fd8Sdanielk1977       }
397a1644fd8Sdanielk1977     }else if( nOption>1 && strncmp(zOption, "-benigncnt", nOption)==0 ){
398a1644fd8Sdanielk1977       if( ii==(objc-1) ){
399a1644fd8Sdanielk1977         zErr = "option requires an argument: ";
400a1644fd8Sdanielk1977       }else{
401a1644fd8Sdanielk1977         pBenignCnt = objv[ii+1];
402a1644fd8Sdanielk1977       }
403a1644fd8Sdanielk1977     }else{
404a1644fd8Sdanielk1977       zErr = "unknown option: ";
405a1644fd8Sdanielk1977     }
406a1644fd8Sdanielk1977 
407a1644fd8Sdanielk1977     if( zErr ){
408a1644fd8Sdanielk1977       Tcl_AppendResult(interp, zErr, zOption, 0);
409a1644fd8Sdanielk1977       return TCL_ERROR;
410a1644fd8Sdanielk1977     }
411a1644fd8Sdanielk1977   }
412a1644fd8Sdanielk1977 
413*643167ffSdrh   nBenign = sqlite3FaultBenignFailures(SQLITE_FAULTINJECTOR_MALLOC);
414*643167ffSdrh   nFail = sqlite3FaultFailures(SQLITE_FAULTINJECTOR_MALLOC);
415*643167ffSdrh   sqlite3FaultConfig(SQLITE_FAULTINJECTOR_MALLOC, iFail, nRepeat);
416a1644fd8Sdanielk1977   if( pBenignCnt ){
417*643167ffSdrh     Tcl_ObjSetVar2(interp, pBenignCnt, 0, Tcl_NewIntObj(nBenign), 0);
418a1644fd8Sdanielk1977   }
4190e6f1546Sdrh   Tcl_SetObjResult(interp, Tcl_NewIntObj(nFail));
4200e6f1546Sdrh   return TCL_OK;
4210e6f1546Sdrh }
4220e6f1546Sdrh 
423cd03724cSdanielk1977 /*
424cd03724cSdanielk1977 ** Usage:    sqlite3_memdebug_pending
425cd03724cSdanielk1977 **
426cd03724cSdanielk1977 ** Return the number of malloc() calls that will succeed before a
427cd03724cSdanielk1977 ** simulated failure occurs. A negative return value indicates that
428cd03724cSdanielk1977 ** no malloc() failure is scheduled.
429cd03724cSdanielk1977 */
430cd03724cSdanielk1977 static int test_memdebug_pending(
431cd03724cSdanielk1977   void * clientData,
432cd03724cSdanielk1977   Tcl_Interp *interp,
433cd03724cSdanielk1977   int objc,
434cd03724cSdanielk1977   Tcl_Obj *CONST objv[]
435cd03724cSdanielk1977 ){
436cd03724cSdanielk1977   if( objc!=1 ){
437cd03724cSdanielk1977     Tcl_WrongNumArgs(interp, 1, objv, "");
438cd03724cSdanielk1977     return TCL_ERROR;
439cd03724cSdanielk1977   }
440cd03724cSdanielk1977 
441cd03724cSdanielk1977 #ifdef SQLITE_MEMDEBUG
442cd03724cSdanielk1977   {
443*643167ffSdrh     Tcl_SetObjResult(interp,
444*643167ffSdrh        Tcl_NewIntObj(sqlite3FaultPending(SQLITE_FAULTINJECTOR_MALLOC))
445*643167ffSdrh     );
446cd03724cSdanielk1977   }
447cd03724cSdanielk1977 #endif
448cd03724cSdanielk1977   return TCL_OK;
449cd03724cSdanielk1977 }
450cd03724cSdanielk1977 
4510e6f1546Sdrh 
4520e6f1546Sdrh /*
4534a50aac5Sdrh ** Usage:    sqlite3_memdebug_settitle TITLE
4544a50aac5Sdrh **
4554a50aac5Sdrh ** Set a title string stored with each allocation.  The TITLE is
4564a50aac5Sdrh ** typically the name of the test that was running when the
4574a50aac5Sdrh ** allocation occurred.  The TITLE is stored with the allocation
4584a50aac5Sdrh ** and can be used to figure out which tests are leaking memory.
4594a50aac5Sdrh **
4604a50aac5Sdrh ** Each title overwrite the previous.
4614a50aac5Sdrh */
4624a50aac5Sdrh static int test_memdebug_settitle(
4634a50aac5Sdrh   void * clientData,
4644a50aac5Sdrh   Tcl_Interp *interp,
4654a50aac5Sdrh   int objc,
4664a50aac5Sdrh   Tcl_Obj *CONST objv[]
4674a50aac5Sdrh ){
4684a50aac5Sdrh   const char *zTitle;
4694a50aac5Sdrh   if( objc!=2 ){
4704a50aac5Sdrh     Tcl_WrongNumArgs(interp, 1, objv, "TITLE");
4714a50aac5Sdrh     return TCL_ERROR;
4724a50aac5Sdrh   }
4734a50aac5Sdrh   zTitle = Tcl_GetString(objv[1]);
4744a50aac5Sdrh #ifdef SQLITE_MEMDEBUG
4754a50aac5Sdrh   {
4764a50aac5Sdrh     extern int sqlite3_memdebug_settitle(const char*);
4774a50aac5Sdrh     sqlite3_memdebug_settitle(zTitle);
4784a50aac5Sdrh   }
4794a50aac5Sdrh #endif
4804a50aac5Sdrh   return TCL_OK;
4814a50aac5Sdrh }
4824a50aac5Sdrh 
4834a50aac5Sdrh 
4844a50aac5Sdrh /*
4852f999a67Sdrh ** Register commands with the TCL interpreter.
4862f999a67Sdrh */
4872f999a67Sdrh int Sqlitetest_malloc_Init(Tcl_Interp *interp){
4882f999a67Sdrh   static struct {
4892f999a67Sdrh      char *zName;
4902f999a67Sdrh      Tcl_ObjCmdProc *xProc;
4912f999a67Sdrh   } aObjCmd[] = {
4922f999a67Sdrh      { "sqlite3_malloc",             test_malloc                   },
4932f999a67Sdrh      { "sqlite3_realloc",            test_realloc                  },
4942f999a67Sdrh      { "sqlite3_free",               test_free                     },
4959c7a60dfSdrh      { "memset",                     test_memset                   },
4969c7a60dfSdrh      { "memget",                     test_memget                   },
4972f999a67Sdrh      { "sqlite3_memory_used",        test_memory_used              },
4982f999a67Sdrh      { "sqlite3_memory_highwater",   test_memory_highwater         },
4992f999a67Sdrh      { "sqlite3_memdebug_backtrace", test_memdebug_backtrace       },
5002f999a67Sdrh      { "sqlite3_memdebug_dump",      test_memdebug_dump            },
5010e6f1546Sdrh      { "sqlite3_memdebug_fail",      test_memdebug_fail            },
502cd03724cSdanielk1977      { "sqlite3_memdebug_pending",   test_memdebug_pending         },
5034a50aac5Sdrh      { "sqlite3_memdebug_settitle",  test_memdebug_settitle        },
5042f999a67Sdrh   };
5052f999a67Sdrh   int i;
5062f999a67Sdrh   for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
5072f999a67Sdrh     Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
5082f999a67Sdrh   }
5092f999a67Sdrh   return TCL_OK;
5102f999a67Sdrh }
511