Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
d8da047b90 |
292
sqlite-3.26.0-fts_corrupt_db.patch
Normal file
292
sqlite-3.26.0-fts_corrupt_db.patch
Normal file
@ -0,0 +1,292 @@
|
||||
Index: ext/fts3/fts3.c
|
||||
==================================================================
|
||||
--- ext/fts3/fts3.c
|
||||
+++ ext/fts3/fts3.c
|
||||
@@ -1819,11 +1819,11 @@
|
||||
){
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
const char *zCsr = zNode; /* Cursor to iterate through node */
|
||||
const char *zEnd = &zCsr[nNode];/* End of interior node buffer */
|
||||
char *zBuffer = 0; /* Buffer to load terms into */
|
||||
- int nAlloc = 0; /* Size of allocated buffer */
|
||||
+ i64 nAlloc = 0; /* Size of allocated buffer */
|
||||
int isFirstTerm = 1; /* True when processing first term on page */
|
||||
sqlite3_int64 iChild; /* Block id of child node to descend to */
|
||||
|
||||
/* Skip over the 'height' varint that occurs at the start of every
|
||||
** interior node. Then load the blockid of the left-child of the b-tree
|
||||
@@ -1857,18 +1857,18 @@
|
||||
}
|
||||
isFirstTerm = 0;
|
||||
zCsr += fts3GetVarint32(zCsr, &nSuffix);
|
||||
|
||||
assert( nPrefix>=0 && nSuffix>=0 );
|
||||
- if( &zCsr[nSuffix]>zEnd ){
|
||||
+ if( nPrefix>zCsr-zNode || nSuffix>zEnd-zCsr ){
|
||||
rc = FTS_CORRUPT_VTAB;
|
||||
goto finish_scan;
|
||||
}
|
||||
- if( nPrefix+nSuffix>nAlloc ){
|
||||
+ if( (i64)nPrefix+nSuffix>nAlloc ){
|
||||
char *zNew;
|
||||
- nAlloc = (nPrefix+nSuffix) * 2;
|
||||
- zNew = (char *)sqlite3_realloc(zBuffer, nAlloc);
|
||||
+ nAlloc = ((i64)nPrefix+nSuffix) * 2;
|
||||
+ zNew = (char *)sqlite3_realloc64(zBuffer, nAlloc);
|
||||
if( !zNew ){
|
||||
rc = SQLITE_NOMEM;
|
||||
goto finish_scan;
|
||||
}
|
||||
zBuffer = zNew;
|
||||
|
||||
Index: ext/fts3/fts3_write.c
|
||||
==================================================================
|
||||
--- ext/fts3/fts3_write.c
|
||||
+++ ext/fts3/fts3_write.c
|
||||
@@ -1372,19 +1372,23 @@
|
||||
|
||||
/* Because of the FTS3_NODE_PADDING bytes of padding, the following is
|
||||
** safe (no risk of overread) even if the node data is corrupted. */
|
||||
pNext += fts3GetVarint32(pNext, &nPrefix);
|
||||
pNext += fts3GetVarint32(pNext, &nSuffix);
|
||||
- if( nPrefix<0 || nSuffix<=0
|
||||
- || &pNext[nSuffix]>&pReader->aNode[pReader->nNode]
|
||||
+ if( nSuffix<=0
|
||||
+ || (&pReader->aNode[pReader->nNode] - pNext)<nSuffix
|
||||
+ || nPrefix>pReader->nTermAlloc
|
||||
){
|
||||
return FTS_CORRUPT_VTAB;
|
||||
}
|
||||
|
||||
- if( nPrefix+nSuffix>pReader->nTermAlloc ){
|
||||
- int nNew = (nPrefix+nSuffix)*2;
|
||||
- char *zNew = sqlite3_realloc(pReader->zTerm, nNew);
|
||||
+ /* Both nPrefix and nSuffix were read by fts3GetVarint32() and so are
|
||||
+ ** between 0 and 0x7FFFFFFF. But the sum of the two may cause integer
|
||||
+ ** overflow - hence the (i64) casts. */
|
||||
+ if( (i64)nPrefix+nSuffix>(i64)pReader->nTermAlloc ){
|
||||
+ i64 nNew = ((i64)nPrefix+nSuffix)*2;
|
||||
+ char *zNew = sqlite3_realloc64(pReader->zTerm, nNew);
|
||||
if( !zNew ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
pReader->zTerm = zNew;
|
||||
pReader->nTermAlloc = nNew;
|
||||
@@ -1402,11 +1406,11 @@
|
||||
|
||||
/* Check that the doclist does not appear to extend past the end of the
|
||||
** b-tree node. And that the final byte of the doclist is 0x00. If either
|
||||
** of these statements is untrue, then the data structure is corrupt.
|
||||
*/
|
||||
- if( &pReader->aDoclist[pReader->nDoclist]>&pReader->aNode[pReader->nNode]
|
||||
+ if( (&pReader->aNode[pReader->nNode] - pReader->aDoclist)<pReader->nDoclist
|
||||
|| (pReader->nPopulate==0 && pReader->aDoclist[pReader->nDoclist-1])
|
||||
){
|
||||
return FTS_CORRUPT_VTAB;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
@@ -3728,25 +3732,30 @@
|
||||
if( bFirst==0 ){
|
||||
p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nPrefix);
|
||||
}
|
||||
p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nSuffix);
|
||||
|
||||
+ if( nPrefix>p->iOff || nSuffix>p->nNode-p->iOff ){
|
||||
+ return SQLITE_CORRUPT_VTAB;
|
||||
+ }
|
||||
blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc);
|
||||
if( rc==SQLITE_OK ){
|
||||
memcpy(&p->term.a[nPrefix], &p->aNode[p->iOff], nSuffix);
|
||||
p->term.n = nPrefix+nSuffix;
|
||||
p->iOff += nSuffix;
|
||||
if( p->iChild==0 ){
|
||||
p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &p->nDoclist);
|
||||
+ if( (p->nNode-p->iOff)<p->nDoclist ){
|
||||
+ return SQLITE_CORRUPT_VTAB;
|
||||
+ }
|
||||
p->aDoclist = &p->aNode[p->iOff];
|
||||
p->iOff += p->nDoclist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert( p->iOff<=p->nNode );
|
||||
-
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Release all dynamic resources held by node-reader object *p.
|
||||
|
||||
ADDED test/fts3corrupt4.test
|
||||
Index: test/fts3corrupt4.test
|
||||
==================================================================
|
||||
--- test/fts3corrupt4.test
|
||||
+++ test/fts3corrupt4.test
|
||||
@@ -0,0 +1,147 @@
|
||||
+# 2006 September 9
|
||||
+#
|
||||
+# 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. The
|
||||
+# focus of this script is testing the FTS3 module.
|
||||
+#
|
||||
+# $Id: fts3aa.test,v 1.1 2007/08/20 17:38:42 shess Exp $
|
||||
+#
|
||||
+
|
||||
+set testdir [file dirname $argv0]
|
||||
+source $testdir/tester.tcl
|
||||
+set testprefix fts3corrupt4
|
||||
+
|
||||
+# If SQLITE_ENABLE_FTS3 is defined, omit this file.
|
||||
+ifcapable !fts3 {
|
||||
+ finish_test
|
||||
+ return
|
||||
+}
|
||||
+
|
||||
+do_execsql_test 1.0 {
|
||||
+ BEGIN;
|
||||
+ CREATE VIRTUAL TABLE ft USING fts3;
|
||||
+ INSERT INTO ft VALUES('aback');
|
||||
+ INSERT INTO ft VALUES('abaft');
|
||||
+ INSERT INTO ft VALUES('abandon');
|
||||
+ COMMIT;
|
||||
+}
|
||||
+
|
||||
+proc blob {a} { binary decode hex $a }
|
||||
+db func blob blob
|
||||
+
|
||||
+do_execsql_test 1.1 {
|
||||
+ SELECT quote(root) FROM ft_segdir;
|
||||
+} {X'0005616261636B03010200030266740302020003046E646F6E03030200'}
|
||||
+
|
||||
+do_execsql_test 1.2 {
|
||||
+ UPDATE ft_segdir SET root = blob(
|
||||
+ '0005616261636B03010200 FFFFFFFF0702 66740302020003046E646F6E03030200'
|
||||
+ );
|
||||
+}
|
||||
+
|
||||
+do_catchsql_test 1.3 {
|
||||
+ SELECT * FROM ft WHERE ft MATCH 'abandon';
|
||||
+} {1 {database disk image is malformed}}
|
||||
+
|
||||
+#-------------------------------------------------------------------------
|
||||
+reset_db
|
||||
+do_execsql_test 2.0.0 {
|
||||
+ CREATE VIRTUAL TABLE ft USING fts3;
|
||||
+ INSERT INTO ft(ft) VALUES('nodesize=32');
|
||||
+}
|
||||
+do_test 2.0.1 {
|
||||
+ for {set i 0} {$i < 12} {incr i} {
|
||||
+ execsql {
|
||||
+ BEGIN;
|
||||
+ INSERT INTO ft VALUES('abc' || $i);
|
||||
+ INSERT INTO ft VALUES('abc' || $i || 'x' );
|
||||
+ INSERT INTO ft VALUES('abc' || $i || 'xx' );
|
||||
+ COMMIT
|
||||
+ }
|
||||
+ }
|
||||
+ execsql {
|
||||
+ SELECT count(*) FROM ft_segdir;
|
||||
+ SELECT count(*) FROM ft_segments;
|
||||
+ }
|
||||
+} {12 0}
|
||||
+
|
||||
+do_execsql_test 2.1 {
|
||||
+ INSERT INTO ft(ft) VALUES('merge=1,4');
|
||||
+ SELECT count(*) FROM ft_segdir;
|
||||
+ SELECT count(*) FROM ft_segments;
|
||||
+} {12 3}
|
||||
+
|
||||
+do_execsql_test 2.2 {
|
||||
+ SELECT quote(block) FROM ft_segments WHERE blockid=2
|
||||
+} {X'00056162633130031F0200'}
|
||||
+
|
||||
+db func blob blob
|
||||
+do_execsql_test 2.3.1 {
|
||||
+ UPDATE ft_segments SET block =
|
||||
+ blob('00056162633130031F0200 FFFFFFFF07FF55 66740302020003046E646F6E03030200')
|
||||
+ WHERE blockid=2;
|
||||
+} {}
|
||||
+do_catchsql_test 2.3.2 {
|
||||
+ INSERT INTO ft(ft) VALUES('merge=1,4');
|
||||
+} {1 {database disk image is malformed}}
|
||||
+
|
||||
+do_execsql_test 2.4.1 {
|
||||
+ UPDATE ft_segments SET block =
|
||||
+ blob('00056162633130031F0200 02FFFFFFFF07 66740302020003046E646F6E03030200')
|
||||
+ WHERE blockid=2;
|
||||
+} {}
|
||||
+do_catchsql_test 2.4.2 {
|
||||
+ INSERT INTO ft(ft) VALUES('merge=1,4');
|
||||
+} {1 {database disk image is malformed}}
|
||||
+
|
||||
+do_execsql_test 2.5.1 {
|
||||
+ UPDATE ft_segments SET block =
|
||||
+ blob('00056162633130031F0200 0202 6674 FFFFFF070302020003046E646F6E030200')
|
||||
+ WHERE blockid=2;
|
||||
+} {}
|
||||
+do_catchsql_test 2.5.2 {
|
||||
+ INSERT INTO ft(ft) VALUES('merge=1,4');
|
||||
+} {1 {database disk image is malformed}}
|
||||
+
|
||||
+#-------------------------------------------------------------------------
|
||||
+reset_db
|
||||
+do_execsql_test 3.0.0 {
|
||||
+ CREATE VIRTUAL TABLE ft USING fts3;
|
||||
+ INSERT INTO ft(ft) VALUES('nodesize=32');
|
||||
+}
|
||||
+do_test 3.0.1 {
|
||||
+ execsql BEGIN
|
||||
+ for {set i 0} {$i < 20} {incr i} {
|
||||
+ execsql { INSERT INTO ft VALUES('abc' || $i) }
|
||||
+ }
|
||||
+ execsql {
|
||||
+ COMMIT;
|
||||
+ SELECT count(*) FROM ft_segdir;
|
||||
+ SELECT count(*) FROM ft_segments;
|
||||
+ }
|
||||
+} {1 5}
|
||||
+
|
||||
+do_execsql_test 3.1 {
|
||||
+ SELECT quote(root) FROM ft_segdir
|
||||
+} {X'0101056162633132040136030132030136'}
|
||||
+
|
||||
+db func blob blob
|
||||
+do_execsql_test 3.2 {
|
||||
+ UPDATE ft_segdir
|
||||
+ SET root = blob('0101056162633132FFFFFFFF070236030132030136');
|
||||
+}
|
||||
+
|
||||
+do_catchsql_test 3.1 {
|
||||
+ SELECT * FROM ft WHERE ft MATCH 'abc20'
|
||||
+} {1 {database disk image is malformed}}
|
||||
+
|
||||
+finish_test
|
||||
+
|
||||
+
|
||||
|
||||
Index: test/permutations.test
|
||||
==================================================================
|
||||
--- test/permutations.test
|
||||
+++ test/permutations.test
|
||||
@@ -260,10 +260,11 @@
|
||||
fts3ae.test fts3af.test fts3ag.test fts3ah.test
|
||||
fts3ai.test fts3aj.test fts3ak.test fts3al.test
|
||||
fts3am.test fts3an.test fts3ao.test fts3atoken.test
|
||||
fts3auto.test fts3aux1.test fts3aux2.test fts3b.test
|
||||
fts3comp1.test fts3conf.test fts3corrupt2.test fts3corrupt.test
|
||||
+ fts3corrupt4.test
|
||||
fts3cov.test fts3c.test fts3defer2.test fts3defer3.test
|
||||
fts3defer.test fts3drop.test fts3d.test fts3e.test
|
||||
fts3expr2.test fts3expr3.test fts3expr4.test fts3expr5.test
|
||||
fts3expr.test fts3fault2.test fts3fault.test fts3first.test
|
||||
fts3join.test fts3malloc.test fts3matchinfo.test fts3near.test
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
Summary: Library that implements an embeddable SQL database engine
|
||||
Name: sqlite
|
||||
Version: %{rpmver}
|
||||
Release: 4%{?dist}
|
||||
Release: 5%{?dist}
|
||||
License: Public Domain
|
||||
Group: Applications/Databases
|
||||
URL: http://www.sqlite.org/
|
||||
@ -43,6 +43,8 @@ Patch10: sqlite-3.22.0-fts3rank-big-endian.patch
|
||||
Patch11: sqlite-3.22.0-walro2-filesize.patch
|
||||
# Upstream: https://www.sqlite.org/cgi/src/timeline?r=corrupt-schema
|
||||
Patch12: sqlite-3.22.0-corrupt-schema.patch
|
||||
# Upstream: https://www.sqlite.org/src/info/d44318f59044162e
|
||||
Patch13: sqlite-3.26.0-fts_corrupt_db.patch
|
||||
|
||||
BuildRequires: ncurses-devel readline-devel glibc-devel
|
||||
BuildRequires: autoconf
|
||||
@ -150,6 +152,7 @@ This package contains the analysis program for %{name}.
|
||||
%patch10 -p0
|
||||
%patch11 -p0
|
||||
%patch12 -p0
|
||||
%patch13 -p0
|
||||
|
||||
autoconf # Rerun with new autoconf to add support for aarm64
|
||||
|
||||
@ -251,6 +254,9 @@ make test
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Mon Dec 17 2018 Petr Kubat <pkubat@redhat.com> - 3.22.0-5
|
||||
- Fixed fts3/4 corrupt database exploit (#1659677)
|
||||
|
||||
* Wed Mar 21 2018 Petr Kubat <pkubat@redhat.com> - 3.22.0-4
|
||||
- Fixed CVE-2018-8740 (#1558809)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user