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)
FossilOrigin-Name: d55a5e1c11ef90534abd2e5f18d06dd4739ade70
diff --git a/src/mem1.c b/src/mem1.c
index 2b28a8c..87dd41a 100644
--- a/src/mem1.c
+++ b/src/mem1.c
@@ -12,7 +12,7 @@
** 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 $
+** $Id: mem1.c,v 1.17 2008/03/18 00:07:11 drh Exp $
*/
#include "sqliteInt.h"
@@ -137,10 +137,14 @@
if( mem.alarmCallback!=0 && mem.nowUsed+nBytes>=mem.alarmThreshold ){
sqlite3MemsysAlarm(nBytes);
}
- p = malloc(nBytes+8);
- if( p==0 ){
- 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;
@@ -205,12 +209,16 @@
if( mem.nowUsed+nBytes-nOld>=mem.alarmThreshold ){
sqlite3MemsysAlarm(nBytes-nOld);
}
- p = realloc(p, nBytes+8);
- if( p==0 ){
- sqlite3MemsysAlarm(nBytes);
- p = pPrior;
- p--;
+ 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;
diff --git a/src/test_malloc.c b/src/test_malloc.c
index 86a3205..3870800 100644
--- a/src/test_malloc.c
+++ b/src/test_malloc.c
@@ -13,7 +13,7 @@
** 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 $
+** $Id: test_malloc.c,v 1.16 2008/03/18 00:07:11 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
@@ -463,18 +463,14 @@
int objc,
Tcl_Obj *CONST objv[]
){
+ int nPending;
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
+ nPending = sqlite3_test_control(SQLITE_TESTCTRL_FAULT_PENDING,
+ SQLITE_FAULTINJECTOR_MALLOC);
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(nPending));
return TCL_OK;
}
diff --git a/src/vdbemem.c b/src/vdbemem.c
index 632151c..1c72cb3 100644
--- a/src/vdbemem.c
+++ b/src/vdbemem.c
@@ -81,7 +81,7 @@
|| (f & (MEM_Dyn|MEM_Static|MEM_Ephem))==MEM_Static
);
- if( ((f&MEM_Dyn)==0 || pMem->xDel || sqlite3MallocSize(pMem->z)<n) ){
+ 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;
@@ -94,6 +94,7 @@
z = sqlite3DbMallocRaw(pMem->db, (n>32?n:32));
}
if( !z ){
+ pMem->flags = MEM_Null;
return SQLITE_NOMEM;
}
}