Skip to content

Commit a8556ee

Browse files
author
drh
committed
In os_unix.c and os_win.c, do not allow xFetch() to return a pointer to a page buffer that is right at the end of the mapped region - if the database is corrupted in a specific way such a page buffer might be overread by several bytes.
FossilOrigin-Name: d131cab652ac11795322af13d0b330e7e44ab91587a1a3e73fe7b9a14b2dd531
1 parent e8df88e commit a8556ee

File tree

6 files changed

+80
-18
lines changed

6 files changed

+80
-18
lines changed

manifest

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
C Fix\sharmless\s"unused\sparameter"\scompiler\swarning\sin\sthe\snew\sfts3IntegrityMethod\nimplementation.
2-
D 2024-01-23T15:04:07.477
1+
C In\sos_unix.c\sand\sos_win.c,\sdo\snot\sallow\sxFetch()\sto\sreturn\sa\spointer\sto\sa\spage\sbuffer\sthat\sis\sright\sat\sthe\send\sof\sthe\smapped\sregion\s-\sif\sthe\sdatabase\sis\scorrupted\sin\sa\sspecific\sway\ssuch\sa\spage\sbuffer\smight\sbe\soverread\sby\sseveral\sbytes.
2+
D 2024-01-23T16:17:00.404
33
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
44
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
55
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -721,8 +721,8 @@ F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
721721
F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06
722722
F src/os_kv.c 4d39e1f1c180b11162c6dc4aa8ad34053873a639bac6baae23272fc03349986a
723723
F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d872107
724-
F src/os_unix.c 5dc41030cd5dfd99b907976b1725a4ed695566405d33744e4824c3d6aff245a3
725-
F src/os_win.c 4a50a154aeebc66a1f8fb79c1ff6dd5fe3d005556533361e0d460d41cb6a45a8
724+
F src/os_unix.c fa9b81b642e60e77ffaf98bd1a2e5fde16c1c2317614ec178bf3bd5864772356
725+
F src/os_win.c 6ff43bac175bd9ed79e7c0f96840b139f2f51d01689a638fd05128becf94908a
726726
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
727727
F src/pager.c ff60e98138d2499082ac6230f01ac508aba545315debccfca2fd6042f5f10fcd
728728
F src/pager.h 4b1140d691860de0be1347474c51fee07d5420bd7f802d38cbab8ea4ab9f538a
@@ -1417,10 +1417,11 @@ F test/misc7.test d912f3d45c2989191b797504a220ca225d6be80b21acad22ba0d35f4a9ee45
14171417
F test/misc8.test 4db9f8be59834cea08c87e9658014080efa02678ef54a088f84fa5647e81fee0
14181418
F test/misuse.test 9e7f78402005e833af71dcab32d048003869eca5abcaccc985d4f8dc1d86bcc7
14191419
F test/mjournal.test 28a08d5cb5fb5b5702a46e19176e45e964e0800d1f894677169e79f34030e152
1420-
F test/mmap1.test 5c1f768828094b0dd94e55ae7f10489a1ded74772682be2c4c78679d0acaf7ef
1420+
F test/mmap1.test e154d0442c9b43646f86b8ddc38b656bb8bc79284209a9367076473cec5d0eef
14211421
F test/mmap2.test 9d6dd9ddb4ad2379f29cc78f38ce1e63ed418022
14221422
F test/mmap3.test b3c297e78e6a8520aafcc1a8f140535594c9086e
14231423
F test/mmap4.test 2e2b4e32555b58da15176e6fe750f17c9dcf7f93
1424+
F test/mmapcorrupt.test 0d89724591f22a376019f3df60d075b838dd2ba6dae6effb0be465c49cf86d4a
14241425
F test/mmapfault.test d4c9eff9cd8c2dc14bc43e71e042f175b0a26fe3
14251426
F test/mmapwarm.test 2272005969cd17a910077bd5082f70bc1fefad9a875afec7fc9af483898ecaf3
14261427
F test/multiplex.test d74c034e52805f6de8cc5432cef8c9eb774bb64ec29b83a22effc8ca4dac1f08
@@ -2158,9 +2159,9 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
21582159
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
21592160
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
21602161
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
2161-
P 54d34edb89430b266221b7e6eea0afbd2c9dafbe774344469473abc8ad1e13fd
2162-
Q +bb1fe53a97672fc868e3f3897162ea0d714dc1da95187f9c7e35255049f2b0e7
2163-
R be8ef569a6982a529df53ff45211ffcb
2162+
P 9d459f6b50fb6f995e6284a0815c5e211cacac44aad0b96bf01ba68af97f51fc
2163+
Q +2684feac3bc9c5463604900d72710be861527614f4957224c74a16a3b3c702f5
2164+
R 67f5eab4d5717e38c7e831b7f85bd879
21642165
U drh
2165-
Z 52aa2adfde564692461c5347addf09a1
2166+
Z 6ff17935a15716d751ffab856ab7e6cc
21662167
# Remove this line to create a well-formed Fossil manifest.

manifest.uuid

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
9d459f6b50fb6f995e6284a0815c5e211cacac44aad0b96bf01ba68af97f51fc
1+
d131cab652ac11795322af13d0b330e7e44ab91587a1a3e73fe7b9a14b2dd531

src/os_unix.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5441,11 +5441,16 @@ static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
54415441

54425442
#if SQLITE_MAX_MMAP_SIZE>0
54435443
if( pFd->mmapSizeMax>0 ){
5444+
/* Ensure that there is always at least a 256 byte buffer of addressable
5445+
** memory following the returned page. If the database is corrupt,
5446+
** SQLite may overread the page slightly (in practice only a few bytes,
5447+
** but 256 is safe, round, number). */
5448+
const int nEofBuffer = 256;
54445449
if( pFd->pMapRegion==0 ){
54455450
int rc = unixMapfile(pFd, -1);
54465451
if( rc!=SQLITE_OK ) return rc;
54475452
}
5448-
if( pFd->mmapSize >= iOff+nAmt ){
5453+
if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){
54495454
*pp = &((u8 *)pFd->pMapRegion)[iOff];
54505455
pFd->nFetchOut++;
54515456
}

src/os_win.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4521,6 +4521,11 @@ static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
45214521

45224522
#if SQLITE_MAX_MMAP_SIZE>0
45234523
if( pFd->mmapSizeMax>0 ){
4524+
/* Ensure that there is always at least a 256 byte buffer of addressable
4525+
** memory following the returned page. If the database is corrupt,
4526+
** SQLite may overread the page slightly (in practice only a few bytes,
4527+
** but 256 is safe, round, number). */
4528+
const int nEofBuffer = 256;
45244529
if( pFd->pMapRegion==0 ){
45254530
int rc = winMapfile(pFd, -1);
45264531
if( rc!=SQLITE_OK ){
@@ -4529,7 +4534,7 @@ static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
45294534
return rc;
45304535
}
45314536
}
4532-
if( pFd->mmapSize >= iOff+nAmt ){
4537+
if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){
45334538
assert( pFd->pMapRegion!=0 );
45344539
*pp = &((u8 *)pFd->pMapRegion)[iOff];
45354540
pFd->nFetchOut++;

test/mmap1.test

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,17 +45,17 @@ proc register_rblob_code {dbname seed} {
4545
}
4646

4747

48-
# For cases 1.1 and 1.4, the number of pages read using xRead() is 4 on
49-
# unix and 9 on windows. The difference is that windows only ever maps
48+
# For cases 1.1 and 1.4, the number of pages read using xRead() is 8 on
49+
# unix and 12 on windows. The difference is that windows only ever maps
5050
# an integer number of OS pages (i.e. creates mappings that are a multiple
5151
# of 4KB in size). Whereas on unix any sized mapping may be created.
5252
#
5353
foreach {t mmap_size nRead c2init} {
54-
1.1 { PRAGMA mmap_size = 67108864 } /[49]/ {PRAGMA mmap_size = 0}
55-
1.2 { PRAGMA mmap_size = 53248 } 150 {PRAGMA mmap_size = 0}
54+
1.1 { PRAGMA mmap_size = 67108864 } /8|12/ {PRAGMA mmap_size = 0}
55+
1.2 { PRAGMA mmap_size = 53248 } 154 {PRAGMA mmap_size = 0}
5656
1.3 { PRAGMA mmap_size = 0 } 344 {PRAGMA mmap_size = 0}
57-
1.4 { PRAGMA mmap_size = 67108864 } /[49]/ {PRAGMA mmap_size = 67108864 }
58-
1.5 { PRAGMA mmap_size = 53248 } 150 {PRAGMA mmap_size = 67108864 }
57+
1.4 { PRAGMA mmap_size = 67108864 } /12|8/ {PRAGMA mmap_size = 67108864 }
58+
1.5 { PRAGMA mmap_size = 53248 } 154 {PRAGMA mmap_size = 67108864 }
5959
1.6 { PRAGMA mmap_size = 0 } 344 {PRAGMA mmap_size = 67108864 }
6060
} {
6161

test/mmapcorrupt.test

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# 2024 January 23
2+
#
3+
# The author disclaims copyright to this source code. In place of
4+
# a legal notice, here is a blessing:
5+
#
6+
# May you do good and not evil.
7+
# May you find forgiveness for yourself and forgive others.
8+
# May you share freely, never taking more than you give.
9+
#
10+
#***********************************************************************
11+
#
12+
# Test special cases of corrupt database handling in mmap-mode.
13+
#
14+
15+
set testdir [file dirname $argv0]
16+
source $testdir/tester.tcl
17+
set testprefix mmapcorrupt
18+
19+
database_may_be_corrupt
20+
21+
db close
22+
sqlite3_shutdown
23+
sqlite3_config_lookaside 0 0
24+
sqlite3_initialize
25+
26+
reset_db
27+
do_execsql_test 1.0 {
28+
PRAGMA page_size = 16384;
29+
CREATE TABLE tn1(a PRIMARY KEY) WITHOUT ROWID;
30+
CREATE TABLE t0(a PRIMARY KEY) WITHOUT ROWID;
31+
CREATE TABLE t1(a PRIMARY KEY) WITHOUT ROWID;
32+
INSERT INTO t1 VALUES('B');
33+
}
34+
db close
35+
36+
set sz [file size test.db]
37+
hexio_write test.db [expr $sz-3] 800380
38+
39+
sqlite3 db test.db
40+
do_execsql_test 2.1 {
41+
PRAGMA mmap_size = 1000000;
42+
SELECT sql FROM sqlite_schema LIMIT 1;
43+
SELECT * FROM t0;
44+
} {1000000 {CREATE TABLE tn1(a PRIMARY KEY) WITHOUT ROWID}}
45+
46+
do_execsql_test 2.2 {
47+
INSERT INTO t0 SELECT * FROM t1;
48+
}
49+
50+
finish_test
51+

0 commit comments

Comments
 (0)