/ Check-in [5e02dbab]
Login

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

Overview
Comment:Additional out-of-memory testing. Fix bugs caused by malloc failures in where.c. Tickets #2794, #2795, #2796, and #2797. (CVS 4560)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 5e02dbabcfa42173adff234c086df1e962824c92
User & Date: drh 2007-11-26 13:36:00
Context
2007-11-26
22:54
Use macro __DARWIN__ rather than __MACOS__ for conditional compilation of MacOSX specific features. Ticket #2780. (CVS 4561) check-in: d0a4c2a3 user: drh tags: trunk
13:36
Additional out-of-memory testing. Fix bugs caused by malloc failures in where.c. Tickets #2794, #2795, #2796, and #2797. (CVS 4560) check-in: 5e02dbab user: drh tags: trunk
2007-11-24
10:23
Declare the invalidateCursorsOnModifiedBtrees function to be static. Ticket #2792. (CVS 4559) check-in: 94f25fc1 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/where.c.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
230
231
232
233
234
235
236

237
238
239
240
241
242
243
...
548
549
550
551
552
553
554


555

556
557
558
559
560
561
562
...
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721





722
723
724
725
726
727
728
...
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  This module is reponsible for
** generating the code that loops through a table looking for applicable
** rows.  Indices are selected and used to speed the search when doing
** so is applicable.  Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
** $Id: where.c,v 1.262 2007/11/05 05:12:53 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** The number of bits in a Bitmask.  "BMS" means "BitMask Size".
*/
#define BMS  (sizeof(Bitmask)*8)
................................................................................
    WhereTerm *pOld = pWC->a;
    pWC->a = sqlite3_malloc( sizeof(pWC->a[0])*pWC->nSlot*2 );
    if( pWC->a==0 ){
      pWC->pParse->db->mallocFailed = 1;
      if( flags & TERM_DYNAMIC ){
        sqlite3ExprDelete(p);
      }

      return 0;
    }
    memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm);
    if( pOld!=pWC->aStatic ){
      sqlite3_free(pOld);
    }
    pWC->nSlot *= 2;
................................................................................
  }
  if( (pColl->type!=SQLITE_COLL_BINARY || noCase) &&
      (pColl->type!=SQLITE_COLL_NOCASE || !noCase) ){
    return 0;
  }
  sqlite3DequoteExpr(db, pRight);
  z = (char *)pRight->token.z;


  for(cnt=0; (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2]; cnt++){}

  if( cnt==0 || 255==(u8)z[cnt] ){
    return 0;
  }
  *pisComplete = z[cnt]==wc[0] && z[cnt+1]==0;
  *pnPattern = cnt;
  return 1;
}
................................................................................
** "Y <op> X" is added to the WHERE clause and analyzed separately.
*/
static void exprAnalyze(
  SrcList *pSrc,            /* the FROM clause */
  WhereClause *pWC,         /* the WHERE clause */
  int idxTerm               /* Index of the term to be analyzed */
){
  WhereTerm *pTerm = &pWC->a[idxTerm];
  ExprMaskSet *pMaskSet = pWC->pMaskSet;
  Expr *pExpr = pTerm->pExpr;
  Bitmask prereqLeft;
  Bitmask prereqAll;
  int nPattern;
  int isComplete;
  int op;
  Parse *pParse = pWC->pParse;
  sqlite3 *db = pParse->db;

  if( db->mallocFailed ) return;





  prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft);
  op = pExpr->op;
  if( op==TK_IN ){
    assert( pExpr->pRight==0 );
    pTerm->prereqRight = exprListTableUsage(pMaskSet, pExpr->pList)
                          | exprSelectTableUsage(pMaskSet, pExpr->pSelect);
  }else if( op==TK_ISNULL ){
................................................................................
    pStr1 = sqlite3PExpr(pParse, TK_STRING, 0, 0, 0);
    if( pStr1 ){
      sqlite3TokenCopy(db, &pStr1->token, &pRight->token);
      pStr1->token.n = nPattern;
      pStr1->flags = EP_Dequoted;
    }
    pStr2 = sqlite3ExprDup(db, pStr1);
    if( pStr2 ){
      assert( pStr2->token.dyn );
      ++*(u8*)&pStr2->token.z[nPattern-1];
    }
    pNewExpr1 = sqlite3PExpr(pParse, TK_GE, sqlite3ExprDup(db,pLeft), pStr1, 0);
    idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
    exprAnalyze(pSrc, pWC, idxNew1);
    pNewExpr2 = sqlite3PExpr(pParse, TK_LT, sqlite3ExprDup(db,pLeft), pStr2, 0);







|







 







>







 







>
>
|
>







 







|
|
|








|
>
>
>
>
>







 







|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
...
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
...
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
...
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  This module is reponsible for
** generating the code that loops through a table looking for applicable
** rows.  Indices are selected and used to speed the search when doing
** so is applicable.  Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
** $Id: where.c,v 1.263 2007/11/26 13:36:00 drh Exp $
*/
#include "sqliteInt.h"

/*
** The number of bits in a Bitmask.  "BMS" means "BitMask Size".
*/
#define BMS  (sizeof(Bitmask)*8)
................................................................................
    WhereTerm *pOld = pWC->a;
    pWC->a = sqlite3_malloc( sizeof(pWC->a[0])*pWC->nSlot*2 );
    if( pWC->a==0 ){
      pWC->pParse->db->mallocFailed = 1;
      if( flags & TERM_DYNAMIC ){
        sqlite3ExprDelete(p);
      }
      pWC->a = pOld;
      return 0;
    }
    memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm);
    if( pOld!=pWC->aStatic ){
      sqlite3_free(pOld);
    }
    pWC->nSlot *= 2;
................................................................................
  }
  if( (pColl->type!=SQLITE_COLL_BINARY || noCase) &&
      (pColl->type!=SQLITE_COLL_NOCASE || !noCase) ){
    return 0;
  }
  sqlite3DequoteExpr(db, pRight);
  z = (char *)pRight->token.z;
  cnt = 0;
  if( z ){
    while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){ cnt++; }
  }
  if( cnt==0 || 255==(u8)z[cnt] ){
    return 0;
  }
  *pisComplete = z[cnt]==wc[0] && z[cnt+1]==0;
  *pnPattern = cnt;
  return 1;
}
................................................................................
** "Y <op> X" is added to the WHERE clause and analyzed separately.
*/
static void exprAnalyze(
  SrcList *pSrc,            /* the FROM clause */
  WhereClause *pWC,         /* the WHERE clause */
  int idxTerm               /* Index of the term to be analyzed */
){
  WhereTerm *pTerm;
  ExprMaskSet *pMaskSet;
  Expr *pExpr;
  Bitmask prereqLeft;
  Bitmask prereqAll;
  int nPattern;
  int isComplete;
  int op;
  Parse *pParse = pWC->pParse;
  sqlite3 *db = pParse->db;

  if( db->mallocFailed ){
    return;
  }
  pTerm = &pWC->a[idxTerm];
  pMaskSet = pWC->pMaskSet;
  pExpr = pTerm->pExpr;
  prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft);
  op = pExpr->op;
  if( op==TK_IN ){
    assert( pExpr->pRight==0 );
    pTerm->prereqRight = exprListTableUsage(pMaskSet, pExpr->pList)
                          | exprSelectTableUsage(pMaskSet, pExpr->pSelect);
  }else if( op==TK_ISNULL ){
................................................................................
    pStr1 = sqlite3PExpr(pParse, TK_STRING, 0, 0, 0);
    if( pStr1 ){
      sqlite3TokenCopy(db, &pStr1->token, &pRight->token);
      pStr1->token.n = nPattern;
      pStr1->flags = EP_Dequoted;
    }
    pStr2 = sqlite3ExprDup(db, pStr1);
    if( !db->mallocFailed ){
      assert( pStr2->token.dyn );
      ++*(u8*)&pStr2->token.z[nPattern-1];
    }
    pNewExpr1 = sqlite3PExpr(pParse, TK_GE, sqlite3ExprDup(db,pLeft), pStr1, 0);
    idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
    exprAnalyze(pSrc, pWC, idxNew1);
    pNewExpr2 = sqlite3PExpr(pParse, TK_LT, sqlite3ExprDup(db,pLeft), pStr2, 0);

Changes to test/all.test.

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
..
61
62
63
64
65
66
67

68
69
70
71
72
73
74
#    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 runs all tests.
#
# $Id: all.test,v 1.50 2007/11/23 18:19:22 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
rename finish_test really_finish_test
proc finish_test {} {
  # no-op
}
................................................................................
lappend EXCLUDE quick.test             ;# Alternate test driver script
lappend EXCLUDE malloc.test            ;# Run seperately later.
lappend EXCLUDE misuse.test            ;# Run seperately later.
lappend EXCLUDE memleak.test           ;# Alternate test driver script
lappend EXCLUDE fuzz.test
lappend EXCLUDE soak.test              ;# Takes a very long time (default 1 hr)
lappend EXCLUDE fts3.test              ;# Wrapper for muliple fts3*.tests


# Files to include in the test.  If this list is empty then everything
# that is not in the EXCLUDE list is run.
#
set INCLUDE {
}








|







 







>







6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
..
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#    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 runs all tests.
#
# $Id: all.test,v 1.51 2007/11/26 13:36:00 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
rename finish_test really_finish_test
proc finish_test {} {
  # no-op
}
................................................................................
lappend EXCLUDE quick.test             ;# Alternate test driver script
lappend EXCLUDE malloc.test            ;# Run seperately later.
lappend EXCLUDE misuse.test            ;# Run seperately later.
lappend EXCLUDE memleak.test           ;# Alternate test driver script
lappend EXCLUDE fuzz.test
lappend EXCLUDE soak.test              ;# Takes a very long time (default 1 hr)
lappend EXCLUDE fts3.test              ;# Wrapper for muliple fts3*.tests
lappend EXCLUSE mallocAll.test         ;# Wrapper for running all malloc tests

# Files to include in the test.  If this list is empty then everything
# that is not in the EXCLUDE list is run.
#
set INCLUDE {
}

Added test/mallocAll.test.







































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
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
#
#    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 runs all out-of-memory tests.
#
# $Id: mallocAll.test,v 1.1 2007/11/26 13:36:00 drh Exp $

proc lshift {lvar} {
  upvar $lvar l
  set ret [lindex $l 0]
  set l [lrange $l 1 end]
  return $ret
}
while {[set arg [lshift argv]] != ""} {
  switch -- $arg {
    -sharedpagercache {
      sqlite3_enable_shared_cache 1
    }
    default {
      set argv [linsert $argv 0 $arg]
      break
    }
  }
}

set testdir [file dirname $argv0]
source $testdir/tester.tcl
rename finish_test really_finish_test
proc finish_test {} {}
set ISQUICK 1

set EXCLUDE {
  mallocAll.test
}

if {[sqlite3 -has-codec]} {
  # lappend EXCLUDE \
  #  conflict.test
}


# Files to include in the test.  If this list is empty then everything
# that is not in the EXCLUDE list is run.
#
set INCLUDE {
}

foreach testfile [lsort -dictionary [glob $testdir/*malloc*.test]] {
  set tail [file tail $testfile]
  if {[lsearch -exact $EXCLUDE $tail]>=0} continue
  if {[llength $INCLUDE]>0 && [lsearch -exact $INCLUDE $tail]<0} continue
  source $testfile
  catch {db close}
  if {$sqlite_open_file_count>0} {
    puts "$tail did not close all files: $sqlite_open_file_count"
    incr nErr
    lappend ::failList $tail
    set sqlite_open_file_count 0
  }
}
source $testdir/misuse.test

set sqlite_open_file_count 0
really_finish_test

Added test/mallocF.test.

































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
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
# 2007 Aug 29
#
# The author disclaims copyright to this source code.  In place of
# 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 test script checks that tickets #2794, #2795, #2796, and #2797
# have been fixed.
# 
# $Id: mallocF.test,v 1.1 2007/11/26 13:36:00 drh Exp $

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

# Only run these tests if memory debugging is turned on.
#
ifcapable !memdebug {
   puts "Skipping mallocE tests: not compiled with -DSQLITE_MEMDEBUG..."
   finish_test
   return
}
source $testdir/malloc_common.tcl

# tickets #2794 and #2795 and #2797
#
set PREP {
  CREATE TABLE t1(x,y);
  INSERT INTO t1 VALUES('abc123', 5);
  INSERT INTO t1 VALUES('xyz987', 42);
}
do_malloc_test malloeF-1 -sqlprep $PREP -sqlbody {
  SELECT * FROM t1 WHERE x GLOB 'abc*'
}

# ticket #2796
#
set PREP {
  CREATE TABLE t1(x PRIMARY KEY,y UNIQUE);
  INSERT INTO t1 VALUES('abc123', 5);
  INSERT INTO t1 VALUES('xyz987', 42);
}
do_malloc_test malloeF-2 -sqlprep $PREP -sqlbody {
  SELECT x FROM t1
   WHERE y=1 OR y=2 OR y=3 OR y=4 OR y=5
      OR y=6 OR y=7 OR y=8 OR y=9 OR y=10
      OR y=11 OR y=12 OR y=13 OR y=14 OR y=15
      OR y=x
}

set PREP {
  CREATE TABLE t1(x PRIMARY KEY,y UNIQUE);
  INSERT INTO t1 VALUES('abc123', 5);
  INSERT INTO t1 VALUES('xyz987', 42);
}
do_malloc_test malloeF-3 -sqlprep $PREP -sqlbody {
  SELECT x FROM t1 WHERE y BETWEEN 10 AND 29
}

finish_test

Changes to test/quick.test.

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
..
50
51
52
53
54
55
56

57
58
59
60
61
62
63
#    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 runs all tests.
#
# $Id: quick.test,v 1.66 2007/11/23 17:31:19 drh Exp $

proc lshift {lvar} {
  upvar $lvar l
  set ret [lindex $l 0]
  set l [lrange $l 1 end]
  return $ret
}
................................................................................
  crash3.test
  exclusive3.test
  fts3.test
  fuzz.test
  fuzz_malloc.test
  in2.test
  loadext.test

  malloc.test
  malloc2.test
  malloc3.test
  malloc4.test
  memleak.test
  misc7.test
  misuse.test







|







 







>







2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
..
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#    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 runs all tests.
#
# $Id: quick.test,v 1.67 2007/11/26 13:36:00 drh Exp $

proc lshift {lvar} {
  upvar $lvar l
  set ret [lindex $l 0]
  set l [lrange $l 1 end]
  return $ret
}
................................................................................
  crash3.test
  exclusive3.test
  fts3.test
  fuzz.test
  fuzz_malloc.test
  in2.test
  loadext.test
  mallocAll.test
  malloc.test
  malloc2.test
  malloc3.test
  malloc4.test
  memleak.test
  misc7.test
  misuse.test