SQLite

Check-in [0f7fdb022c]
Login

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

Overview
Comment:Fix an memory allocation error revealed by malloc3.test. (CVS 3733)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 0f7fdb022ca7c94f7d264192e18b6e2bd1e8cff4
User & Date: drh 2007-03-28 01:59:34.000
Context
2007-03-28
13:07
Update comments in sqlite3.h. No changes to code. (CVS 3734) (check-in: 1c2656fdf6 user: drh tags: trunk)
01:59
Fix an memory allocation error revealed by malloc3.test. (CVS 3733) (check-in: 0f7fdb022c user: drh tags: trunk)
2007-03-27
22:24
The SQLITE_ENABLE_LOAD_EXTENSION macro enables the load_extension() SQL function by default without having to invoke sqlite3_enable_load_extension() first. (CVS 3732) (check-in: 113aab2cdf user: drh tags: trunk)
Changes
Side-by-Side Diff Ignore Whitespace Patch
Changes to src/pager.c.
14
15
16
17
18
19
20
21

22
23
24
25
26
27
28
14
15
16
17
18
19
20

21
22
23
24
25
26
27
28







-
+







** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.303 2007/03/27 17:37:32 danielk1977 Exp $
** @(#) $Id: pager.c,v 1.304 2007/03/28 01:59:34 drh Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
#include "os.h"
#include "pager.h"
#include <assert.h>
#include <string.h>
3056
3057
3058
3059
3060
3061
3062



3063
3064
3065
3066
3067
3068
3069
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072







+
+
+







  }
  rc = sqlite3OsOpenExclusive(pPager->zJournal, &pPager->jfd,
                                 pPager->tempFile);
  pPager->journalOff = 0;
  pPager->setMaster = 0;
  pPager->journalHdr = 0;
  if( rc!=SQLITE_OK ){
    if( rc==SQLITE_NOMEM ){
      sqlite3OsDelete(pPager->zJournal);
    }
    goto failed_to_open_journal;
  }
  sqlite3OsSetFullSync(pPager->jfd, pPager->full_fsync);
  sqlite3OsSetFullSync(pPager->fd, pPager->full_fsync);
  sqlite3OsOpenDirectory(pPager->jfd, pPager->zDirectory);
  pPager->journalOpen = 1;
  pPager->journalStarted = 0;
3088
3089
3090
3091
3092
3093
3094

3095
3096
3097
3098
3099
3100
3101
3102


3103

3104

3105
3106
3107
3108
3109
3110
3111
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108

3109
3110
3111
3112
3113
3114
3115
3116
3117
3118







+








+
+
-
+

+







    }
  }
  return rc;

failed_to_open_journal:
  sqliteFree(pPager->aInJournal);
  pPager->aInJournal = 0;
#if 0
  if( rc==SQLITE_NOMEM ){
    /* If this was a malloc() failure, then we will not be closing the pager
    ** file. So delete any journal file we may have just created. Otherwise,
    ** the system will get confused, we have a read-lock on the file and a
    ** mysterious journal has appeared in the filesystem.
    */
    /* sqlite3OsDelete(pPager->zJournal); */
  }else{
    /* If we reset the pager here, we will delete pages out from under
    ** various cursors and will ultimately segfault. */
    pager_reset(pPager);
    /* pager_reset(pPager); */
  }
#endif
  return rc;
}

/*
** Acquire a write-lock on the database.  The lock is removed when
** the any of the following happen:
**
Changes to test/malloc3.test.
9
10
11
12
13
14
15
16

17
18
19
20
21
22
23
9
10
11
12
13
14
15

16
17
18
19
20
21
22
23







-
+







#
#***********************************************************************
#
# This file contains tests to ensure that the library handles malloc() failures
# correctly. The emphasis of these tests are the _prepare(), _step() and
# _finalize() calls.
#
# $Id: malloc3.test,v 1.9 2006/01/23 07:52:41 danielk1977 Exp $
# $Id: malloc3.test,v 1.10 2007/03/28 01:59:34 drh Exp $

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

# Only run these tests if memory debugging is turned on.
if {[info command sqlite_malloc_stat]==""} {
   puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..."
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
523
524
525
526
527
528
529

530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545

546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562

563

564
565
566
567
568
569
570







-
















-

















-

-







    error "Uneven number of arguments to TEST"
  }

  for {set i 0} {$i < $pcstart} {incr i} {
    set k2 [lindex $arglist [expr 2 * $i]]
    set v2 [lindex $arglist [expr 2 * $i + 1]]
    set ac [sqlite3_get_autocommit $::DB]        ;# Auto-Commit
# puts "STARTUP"
    switch -- $k2 {
      -sql  {db eval [lindex $v2 1]}
      -prep {db eval $v2}
    }
    set nac [sqlite3_get_autocommit $::DB]       ;# New Auto-Commit 
    if {$ac && !$nac} {set begin_pc $i}
  }

  db rollback_hook [list incr ::rollback_hook_count]

  set iFail $iFailStart
  set pc $pcstart
  while {$pc*2 < [llength $arglist]} {

    # Id of this iteration:
    set iterid "(pc $pc).(iFail $iFail)"

    set k [lindex $arglist [expr 2 * $pc]]
    set v [lindex $arglist [expr 2 * $pc + 1]]

    switch -- $k {

      -test { 
        foreach {id script} $v {}
        set testid "malloc3-(test $id).$iterid"
        eval $script
        incr pc
      }

      -sql {
        set ::rollback_hook_count 0

        set ac [sqlite3_get_autocommit $::DB]        ;# Auto-Commit
        sqlite_malloc_fail $iFail
# puts "SQL $iterid [lindex $v 1]"
        set rc [catch {db eval [lindex $v 1]} msg]   ;# True error occurs
# puts "rc = $rc msg = \"$msg\""
        set nac [sqlite3_get_autocommit $::DB]       ;# New Auto-Commit 


        if {$rc != 0 && $nac && !$ac} {
          # Before [db eval] the auto-commit flag was clear. Now it
          # is set. Since an error occured we assume this was not a
	  # commit - therefore a rollback occured. Check that the
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
599
600
601
602
603
604
605

606
607
608
609
610
611
612
613

614
615
616
617
618
619
620
621
622
623
624
625
626

627
628
629
630
631
632

633
634
635
636
637
638
639
640
641
642
643
644
645
646








-








-













-






-














-
            incr iFail
            if {$nac && !$ac} {

              if {![lindex $v 0]} {
                error "Statement \"[lindex $v 1]\" caused a rollback"
              }

# puts "Statement \"[lindex $v 1]\" caused a rollback"
              for {set i $begin_pc} {$i < $pc} {incr i} {
                set k2 [lindex $arglist [expr 2 * $i]]
                set v2 [lindex $arglist [expr 2 * $i + 1]]
                set catchupsql ""
                switch -- $k2 {
                  -sql  {set catchupsql [lindex $v2 1]}
                  -prep {set catchupsql $v2}
                }
# puts "CATCHUP $iterid $i $catchupsql"
                db eval $catchupsql
              }
            }
        } else {
            error $msg
        }

        while {[lindex $arglist [expr 2 * ($pc -1)]] == "-test"} {
          incr pc -1
        }
      }

      -prep {
# puts "PREP $iterid $v"
        db eval $v
        incr pc
      }

      default { error "Unknown switch: $k" }
    }
# if {$iFail > ($iFailStart+1)} return
  }
}

# Turn of the Tcl interface's prepared statement caching facility.
db cache size 0

run_test $::run_test_script 9 1
# run_test [lrange $::run_test_script 0 3] 0 63
sqlite_malloc_fail 0
db close

pp_check_for_leaks

finish_test