/ Check-in [c0ce6319]
Login

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

Overview
Comment:Handle transient malloc() failures in sqlite3CreateFunc(). (CVS 4371)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: c0ce63196458c81e0859fc8a38f2dd2145a580bc
User & Date: danielk1977 2007-09-03 11:04:22
Context
2007-09-03
11:51
Add a module-destructor to the echo module (test8.c) to improve code coverage. (CVS 4372) check-in: e3dd3651 user: danielk1977 tags: trunk
11:04
Handle transient malloc() failures in sqlite3CreateFunc(). (CVS 4371) check-in: c0ce6319 user: danielk1977 tags: trunk
07:31
Fixes to test code so that the test suite passes without SQLITE_MEMDEBUG defined. (CVS 4370) check-in: ed2a2e01 user: danielk1977 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/func.c.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
....
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141


1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
** This file contains the C functions that implement various SQL
** functions of SQLite.  
**
** There is only one exported symbol in this file - the function
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: func.c,v 1.173 2007/09/01 17:00:13 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include <stdlib.h>
#include <assert.h>
#include "vdbeInt.h"

................................................................................
  for(i=0; i<nArg; i++){
    char const *z = (char*)sqlite3_value_text(argv[i]);
    if( z ){
      char *zAux = sqlite3_get_auxdata(pCtx, i);
      if( zAux ){
        zRet[i*2] = '1';
        if( strcmp(zAux, z) ){
          free_test_auxdata((void *)zRet);
          sqlite3_result_error(pCtx, "Auxilary data corruption", -1);
          return;
        }
      }else{
        zRet[i*2] = '0';


        zAux = contextMalloc(pCtx, strlen(z)+1);
        if( zAux ){
          strcpy(zAux, z);
          sqlite3_set_auxdata(pCtx, i, zAux, free_test_auxdata);
        }
      }
      zRet[i*2+1] = ' ';
    }
  }
  sqlite3_result_text(pCtx, zRet, 2*nArg-1, free_test_auxdata);
}
#endif /* SQLITE_TEST */







|







 







<



|

>
>
|
|
|
|
<







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
....
1129
1130
1131
1132
1133
1134
1135

1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146

1147
1148
1149
1150
1151
1152
1153
** This file contains the C functions that implement various SQL
** functions of SQLite.  
**
** There is only one exported symbol in this file - the function
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: func.c,v 1.174 2007/09/03 11:04:22 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include <stdlib.h>
#include <assert.h>
#include "vdbeInt.h"

................................................................................
  for(i=0; i<nArg; i++){
    char const *z = (char*)sqlite3_value_text(argv[i]);
    if( z ){
      char *zAux = sqlite3_get_auxdata(pCtx, i);
      if( zAux ){
        zRet[i*2] = '1';
        if( strcmp(zAux, z) ){

          sqlite3_result_error(pCtx, "Auxilary data corruption", -1);
          return;
        }
      }else {
        zRet[i*2] = '0';
      }

      zAux = contextMalloc(pCtx, strlen(z)+1);
      if( zAux ){
        strcpy(zAux, z);
        sqlite3_set_auxdata(pCtx, i, zAux, free_test_auxdata);

      }
      zRet[i*2+1] = ' ';
    }
  }
  sqlite3_result_text(pCtx, zRet, 2*nArg-1, free_test_auxdata);
}
#endif /* SQLITE_TEST */

Changes to src/main.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
507
508
509
510
511
512
513

514


515
516
517
518
519
520
521
522
523
524
525
526
527
528
**
*************************************************************************
** 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.402 2007/09/01 06:51:28 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** The version of the library
*/
................................................................................
      return SQLITE_BUSY;
    }else{
      sqlite3ExpirePreparedStatements(db);
    }
  }

  p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 1);

  if( p ){


    p->flags = 0;
    p->xFunc = xFunc;
    p->xStep = xStep;
    p->xFinalize = xFinal;
    p->pUserData = pUserData;
    p->nArg = nArg;
  }
  return SQLITE_OK;
}

/*
** Create new user functions.
*/
int sqlite3_create_function(







|







 







>
|
>
>
|
|
|
|
|
|
<







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523

524
525
526
527
528
529
530
**
*************************************************************************
** 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.403 2007/09/03 11:04:22 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** The version of the library
*/
................................................................................
      return SQLITE_BUSY;
    }else{
      sqlite3ExpirePreparedStatements(db);
    }
  }

  p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 1);
  assert(p || db->mallocFailed);
  if( !p ){
    return SQLITE_NOMEM;
  }
  p->flags = 0;
  p->xFunc = xFunc;
  p->xStep = xStep;
  p->xFinalize = xFinal;
  p->pUserData = pUserData;
  p->nArg = nArg;

  return SQLITE_OK;
}

/*
** Create new user functions.
*/
int sqlite3_create_function(

Changes to src/test1.c.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
....
1007
1008
1009
1010
1011
1012
1013
1014











1015
1016
1017
1018
1019
1020


1021
1022
1023
1024
1025
1026
1027




1028
1029
1030
1031
1032
1033
1034
....
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048





1049

1050
1051
1052
1053
1054
1055
1056
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing all sorts of SQLite interfaces.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.274 2007/09/01 11:04:26 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>

/*
................................................................................
    if( p->n==42 ){
      sqlite3_result_error(context, "x_count totals to 42", -1);
    }else{
      sqlite3_result_int(context, p ? p->n : 0);
    }
  }
}












/*
** Usage:  sqlite_test_create_aggregate DB
**
** Call the sqlite3_create_function API on the given database in order
** to create a function named "x_count".  This function does the same thing
** as the "md5sum" function.


**
** The original motivation for this routine was to be able to call the
** sqlite3_create_aggregate function while a query is in progress in order
** to test the SQLITE_MISUSE detection logic.  See misuse.test.
**
** This routine was later extended to test the use of sqlite3_result_error()
** within aggregate functions.




*/
static int test_create_aggregate(
  void *NotUsed,
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int argc,              /* Number of arguments */
  char **argv            /* Text of each argument */
){
................................................................................
       " FILENAME\"", 0);
    return TCL_ERROR;
  }
  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  rc = sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0,
      t1CountStep,t1CountFinalize);
  if( rc==SQLITE_OK ){
    sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0,
        t1CountStep,t1CountFinalize);
  }





  if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;

  return TCL_OK;
}


/*
** Usage:  printf TEXT
**







|







 








>
>
>
>
>
>
>
>
>
>
>

|


|
<
>
>







>
>
>
>







 







|


>
>
>
>
>

>







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
....
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030

1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
....
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing all sorts of SQLite interfaces.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.275 2007/09/03 11:04:22 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>

/*
................................................................................
    if( p->n==42 ){
      sqlite3_result_error(context, "x_count totals to 42", -1);
    }else{
      sqlite3_result_int(context, p ? p->n : 0);
    }
  }
}

static void legacyCountStep(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  /* no-op */
}
static void legacyCountFinalize(sqlite3_context *context){
  sqlite3_result_int(context, sqlite3_aggregate_count(context));
}

/*
** Usage:  sqlite3_create_aggregate DB
**
** Call the sqlite3_create_function API on the given database in order
** to create a function named "x_count".  This function is similar

** to the built-in count() function, with a few special quirks
** for testing the sqlite3_result_error() APIs.
**
** The original motivation for this routine was to be able to call the
** sqlite3_create_aggregate function while a query is in progress in order
** to test the SQLITE_MISUSE detection logic.  See misuse.test.
**
** This routine was later extended to test the use of sqlite3_result_error()
** within aggregate functions.
**
** Later: It is now also extended to register the aggregate function
** "legacy_count()" with the supplied database handle. This is used
** to test the deprecated sqlite3_aggregate_count() API.
*/
static int test_create_aggregate(
  void *NotUsed,
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int argc,              /* Number of arguments */
  char **argv            /* Text of each argument */
){
................................................................................
       " FILENAME\"", 0);
    return TCL_ERROR;
  }
  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  rc = sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0,
      t1CountStep,t1CountFinalize);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0,
        t1CountStep,t1CountFinalize);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "legacy_count", 0, SQLITE_ANY, 0, 0,
        legacyCountStep, legacyCountFinalize
    );
  }
  if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
  Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
  return TCL_OK;
}


/*
** Usage:  printf TEXT
**

Changes to test/func.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
865
866
867
868
869
870
871
872









873
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing built-in functions.
#
# $Id: func.test,v 1.67 2007/05/15 18:35:21 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a table to work with.
#
do_test func-0.0 {
................................................................................
} {null}
do_test func-22.21 {
  execsql {SELECT typeof(trim(NULL,'xyz'));}
} {null}
do_test func-22.22 {
  execsql {SELECT typeof(trim('hello',NULL));}
} {null}










finish_test







|







 








>
>
>
>
>
>
>
>
>

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing built-in functions.
#
# $Id: func.test,v 1.68 2007/09/03 11:04:22 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a table to work with.
#
do_test func-0.0 {
................................................................................
} {null}
do_test func-22.21 {
  execsql {SELECT typeof(trim(NULL,'xyz'));}
} {null}
do_test func-22.22 {
  execsql {SELECT typeof(trim('hello',NULL));}
} {null}

# This is to test the deprecated sqlite3_aggregate_count() API.
#
do_test func-23.1 {
  sqlite3_create_aggregate db
  execsql {
    SELECT legacy_count() FROM t6;
  }
} {3}

finish_test

Changes to test/malloc.test.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
255
256
257
258
259
260
261



262
263
264
265
266
267
268
# This file attempts to check the behavior of the SQLite library in 
# an out-of-memory situation. When compiled with -DSQLITE_DEBUG=1, 
# the SQLite library accepts a special command (sqlite3_memdebug_fail N C)
# which causes the N-th malloc to fail.  This special feature is used
# to see what happens in the library if a malloc were to really fail
# due to an out-of-memory situation.
#
# $Id: malloc.test,v 1.45 2007/08/29 12:31:29 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Only run these tests if memory debugging is turned on.
#
ifcapable !memdebug {
................................................................................
  db2 close
} 

# This block tests malloc() failures that occur within calls to
# sqlite3_create_function().
do_malloc_test 11 -tclbody {
  set rc [sqlite3_create_function db]



  if {[string match $rc SQLITE_NOMEM]} {
    error "out of memory"
  }
}

do_malloc_test 12 -tclbody {
  set sql16 [encoding convertto unicode "SELECT * FROM sqlite_master"]







|







 







>
>
>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# This file attempts to check the behavior of the SQLite library in 
# an out-of-memory situation. When compiled with -DSQLITE_DEBUG=1, 
# the SQLite library accepts a special command (sqlite3_memdebug_fail N C)
# which causes the N-th malloc to fail.  This special feature is used
# to see what happens in the library if a malloc were to really fail
# due to an out-of-memory situation.
#
# $Id: malloc.test,v 1.46 2007/09/03 11:04:22 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Only run these tests if memory debugging is turned on.
#
ifcapable !memdebug {
................................................................................
  db2 close
} 

# This block tests malloc() failures that occur within calls to
# sqlite3_create_function().
do_malloc_test 11 -tclbody {
  set rc [sqlite3_create_function db]
  if {[string match $rc SQLITE_OK]} {
    set rc [sqlite3_create_aggregate db]
  }
  if {[string match $rc SQLITE_NOMEM]} {
    error "out of memory"
  }
}

do_malloc_test 12 -tclbody {
  set sql16 [encoding convertto unicode "SELECT * FROM sqlite_master"]

Changes to test/malloc5.test.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
294
295
296
297
298
299
300
301

302
303
304
305
306
307
308
309
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains test cases focused on the two memory-management APIs, 
# sqlite3_soft_heap_limit() and sqlite3_release_memory().
#
# $Id: malloc5.test,v 1.14 2007/08/28 08:00:18 danielk1977 Exp $

#---------------------------------------------------------------------------
# NOTES ON EXPECTED BEHAVIOUR
#
#---------------------------------------------------------------------------


................................................................................
        SELECT randstr(50,50), randstr(75,75), randstr(100,100) FROM abc;
    INSERT INTO abc 
        SELECT randstr(50,50), randstr(75,75), randstr(100,100) FROM abc;
    COMMIT;
  } 
  copy_file test.db test2.db
  sqlite3 db2 test2.db
  list [expr [file size test.db]/1024] [expr [file size test2.db]/1024]

} {23 23}
do_test malloc5-6.1.2 {
  list [execsql {PRAGMA cache_size}] [execsql {PRAGMA cache_size} db2]
} {10 10}

do_test malloc5-6.2.1 {
  execsql { SELECT * FROM abc } db2
  execsql {SELECT * FROM abc} db







|







 







|
>
|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains test cases focused on the two memory-management APIs, 
# sqlite3_soft_heap_limit() and sqlite3_release_memory().
#
# $Id: malloc5.test,v 1.15 2007/09/03 11:04:22 danielk1977 Exp $

#---------------------------------------------------------------------------
# NOTES ON EXPECTED BEHAVIOUR
#
#---------------------------------------------------------------------------


................................................................................
        SELECT randstr(50,50), randstr(75,75), randstr(100,100) FROM abc;
    INSERT INTO abc 
        SELECT randstr(50,50), randstr(75,75), randstr(100,100) FROM abc;
    COMMIT;
  } 
  copy_file test.db test2.db
  sqlite3 db2 test2.db
  list \
    [expr ([file size test.db]/1024)>20] [expr ([file size test2.db]/1024)>20]
} {1 1}
do_test malloc5-6.1.2 {
  list [execsql {PRAGMA cache_size}] [execsql {PRAGMA cache_size} db2]
} {10 10}

do_test malloc5-6.2.1 {
  execsql { SELECT * FROM abc } db2
  execsql {SELECT * FROM abc} db