SQLite

Check-in [cf5bf42c]
Login

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

Overview
Comment:Avoid an out-of-bounds read that can be caused by a specially constructed journal file.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: cf5bf42cad6e019a38dc0a36ff1f53ada619eef5259e175c3554a16669e03202
User & Date: dan 2017-09-14 20:41:17
Context
2017-09-14
21:12
Add another test case for the problem fixed by the previous commit. (check-in: 1a7e0b61 user: dan tags: trunk)
20:41
Avoid an out-of-bounds read that can be caused by a specially constructed journal file. (check-in: cf5bf42c user: dan tags: trunk)
02:36
Avoid an out-of-bounds read on a recovery attempt using a carefully crafted database and rollback journal with mismatched page sizes. The test case for this is in TH3. (check-in: 378afa16 user: drh tags: trunk)
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/os_unix.c.

5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
){
  const sqlite3_io_methods *pLockingStyle;
  unixFile *pNew = (unixFile *)pId;
  int rc = SQLITE_OK;

  assert( pNew->pInode==NULL );

  /* Usually the path zFilename should not be a relative pathname. The
  ** exception is when opening the proxy "conch" file in builds that
  ** include the special Apple locking styles.
  */
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
  assert( zFilename==0 || zFilename[0]=='/' 
    || pVfs->pAppData==(void*)&autolockIoFinder );
#else
  assert( zFilename==0 || zFilename[0]=='/' );
#endif

  /* No locking occurs in temporary files */
  assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 );

  OSTRACE(("OPEN    %-3d %s\n", h, zFilename));
  pNew->h = h;
  pNew->pVfs = pVfs;
  pNew->zPath = zFilename;







<
<
<
<
<
<
<
<
<
<
<







5296
5297
5298
5299
5300
5301
5302











5303
5304
5305
5306
5307
5308
5309
){
  const sqlite3_io_methods *pLockingStyle;
  unixFile *pNew = (unixFile *)pId;
  int rc = SQLITE_OK;

  assert( pNew->pInode==NULL );












  /* No locking occurs in temporary files */
  assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 );

  OSTRACE(("OPEN    %-3d %s\n", h, zFilename));
  pNew->h = h;
  pNew->pVfs = pVfs;
  pNew->zPath = zFilename;
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683

5684
5685
5686
5687
5688
5689
5690
5691
5692
    **   "<path to db>-walNN"
    **
    ** where NN is a decimal number. The NN naming schemes are 
    ** used by the test_multiplex.c module.
    */
    nDb = sqlite3Strlen30(zPath) - 1; 
    while( zPath[nDb]!='-' ){
#ifndef SQLITE_ENABLE_8_3_NAMES
      /* In the normal case (8+3 filenames disabled) the journal filename
      ** is guaranteed to contain a '-' character. */
      assert( nDb>0 );
      assert( sqlite3Isalnum(zPath[nDb]) );
#else
      /* If 8+3 names are possible, then the journal file might not contain
      ** a '-' character.  So check for that case and return early. */

      if( nDb==0 || zPath[nDb]=='.' ) return SQLITE_OK;
#endif
      nDb--;
    }
    memcpy(zDb, zPath, nDb);
    zDb[nDb] = '\0';

    rc = getFileMode(zDb, pMode, pUid, pGid);
  }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){







<
|
|
<
<
<
|
<
>

<







5658
5659
5660
5661
5662
5663
5664

5665
5666



5667

5668
5669

5670
5671
5672
5673
5674
5675
5676
    **   "<path to db>-walNN"
    **
    ** where NN is a decimal number. The NN naming schemes are 
    ** used by the test_multiplex.c module.
    */
    nDb = sqlite3Strlen30(zPath) - 1; 
    while( zPath[nDb]!='-' ){

      /* In normal operation, the journal file name will always contain
      ** a '-' character.  However in 8+3 filename mode, or if a corrupt



      ** rollback journal specifies a master journal with a goofy name, then

      ** the '-' might be missing. */
      if( nDb==0 || zPath[nDb]=='.' ) return SQLITE_OK;

      nDb--;
    }
    memcpy(zDb, zPath, nDb);
    zDb[nDb] = '\0';

    rc = getFileMode(zDb, pMode, pUid, pGid);
  }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
5964
5965
5966
5967
5968
5969
5970

5971
5972
5973
5974
5975
5976
5977
        }
      }
      goto open_finished;
    }
  }
#endif
  

  rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);

open_finished:
  if( rc!=SQLITE_OK ){
    sqlite3_free(p->pPreallocatedUnused);
  }
  return rc;







>







5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
        }
      }
      goto open_finished;
    }
  }
#endif
  
  assert( zPath==0 || zPath[0]=='/' || eType==SQLITE_OPEN_MASTER_JOURNAL );
  rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);

open_finished:
  if( rc!=SQLITE_OK ){
    sqlite3_free(p->pPreallocatedUnused);
  }
  return rc;

Added test/mjournal.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
# 2017 September 15
#
# 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 file implements regression tests for SQLite library.
#

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

# Test that nothing bad happens if a journal file contains a pointer to
# a master journal file that does not have a "-" in the name. At one point
# this was causing a segfault on unix.
#
do_execsql_test 1.0 {
  CREATE TABLE t1(a, b);
}

do_test 1.1 {
  forcedelete test.db2journal test.db-journal

  close [open test.db-journal w]
  
  hexio_write test.db-journal 0 746573742e6462326a6f75726e616c00
  hexio_write test.db-journal 16 00000010
  hexio_write test.db-journal 20 000005e1
  hexio_write test.db-journal 24 d9d505f920a163d7

  close [open test.db2journal w]
  hexio_write test.db2journal 0 abcd
} {2}

do_execsql_test 1.2 {
  SELECT * FROM t1;
}

do_test 1.3 {
  forcedelete test0db2journal test.db-journal
  close [open test.db-journal w]
  hexio_write test.db-journal 0 74657374306462326a6f75726e616c00
  hexio_write test.db-journal 16 00000010
  hexio_write test.db-journal 20 000005e3
  hexio_write test.db-journal 24 d9d505f920a163d7

  close [open test0db2journal w]
  hexio_write test0db2journal 0 abcd
} {2}

do_execsql_test 1.4 {
  SELECT * FROM t1;
}


  
finish_test