· 7 years ago · Dec 15, 2018, 12:54 AM
1diff --git a/VERSION b/VERSION
2index 427f3464e..703e89e71 100644
3--- a/VERSION
4+++ b/VERSION
5@@ -1 +1 @@
6-3.25.2
7+3.25.3
8diff --git a/configure b/configure
9index 038abd43a..6dde74640 100755
10--- a/configure
11+++ b/configure
12@@ -1,6 +1,6 @@
13 #! /bin/sh
14 # Guess values for system-dependent variables and create Makefiles.
15-# Generated by GNU Autoconf 2.69 for sqlite 3.25.2.
16+# Generated by GNU Autoconf 2.69 for sqlite 3.25.3.
17 #
18 #
19 # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
20@@ -726,8 +726,8 @@ MAKEFLAGS=
21 # Identity of this package.
22 PACKAGE_NAME='sqlite'
23 PACKAGE_TARNAME='sqlite'
24-PACKAGE_VERSION='3.25.2'
25-PACKAGE_STRING='sqlite 3.25.2'
26+PACKAGE_VERSION='3.25.3'
27+PACKAGE_STRING='sqlite 3.25.3'
28 PACKAGE_BUGREPORT=''
29 PACKAGE_URL=''
30
31@@ -1466,7 +1466,7 @@ if test "$ac_init_help" = "long"; then
32 # Omit some internal or obsolete options to make the list less imposing.
33 # This message is too long to be a string in the A/UX 3.1 sh.
34 cat <<_ACEOF
35-\`configure' configures sqlite 3.25.2 to adapt to many kinds of systems.
36+\`configure' configures sqlite 3.25.3 to adapt to many kinds of systems.
37
38 Usage: $0 [OPTION]... [VAR=VALUE]...
39
40@@ -1531,7 +1531,7 @@ fi
41
42 if test -n "$ac_init_help"; then
43 case $ac_init_help in
44- short | recursive ) echo "Configuration of sqlite 3.25.2:";;
45+ short | recursive ) echo "Configuration of sqlite 3.25.3:";;
46 esac
47 cat <<\_ACEOF
48
49@@ -1657,7 +1657,7 @@ fi
50 test -n "$ac_init_help" && exit $ac_status
51 if $ac_init_version; then
52 cat <<\_ACEOF
53-sqlite configure 3.25.2
54+sqlite configure 3.25.3
55 generated by GNU Autoconf 2.69
56
57 Copyright (C) 2012 Free Software Foundation, Inc.
58@@ -2076,7 +2076,7 @@ cat >config.log <<_ACEOF
59 This file contains any messages produced by compilers while
60 running configure, to aid debugging if configure makes a mistake.
61
62-It was created by sqlite $as_me 3.25.2, which was
63+It was created by sqlite $as_me 3.25.3, which was
64 generated by GNU Autoconf 2.69. Invocation command line was
65
66 $ $0 $@
67@@ -12232,7 +12232,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
68 # report actual input values of CONFIG_FILES etc. instead of their
69 # values after options handling.
70 ac_log="
71-This file was extended by sqlite $as_me 3.25.2, which was
72+This file was extended by sqlite $as_me 3.25.3, which was
73 generated by GNU Autoconf 2.69. Invocation command line was
74
75 CONFIG_FILES = $CONFIG_FILES
76@@ -12298,7 +12298,7 @@ _ACEOF
77 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
78 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
79 ac_cs_version="\\
80-sqlite config.status 3.25.2
81+sqlite config.status 3.25.3
82 configured by $0, generated by GNU Autoconf 2.69,
83 with options \\"\$ac_cs_config\\"
84
85diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c
86index d0e6d9be2..3897054c7 100644
87--- a/ext/fts3/fts3.c
88+++ b/ext/fts3/fts3.c
89@@ -1821,7 +1821,7 @@ static int fts3ScanInteriorNode(
90 const char *zCsr = zNode; /* Cursor to iterate through node */
91 const char *zEnd = &zCsr[nNode];/* End of interior node buffer */
92 char *zBuffer = 0; /* Buffer to load terms into */
93- int nAlloc = 0; /* Size of allocated buffer */
94+ i64 nAlloc = 0; /* Size of allocated buffer */
95 int isFirstTerm = 1; /* True when processing first term on page */
96 sqlite3_int64 iChild; /* Block id of child node to descend to */
97
98@@ -1859,14 +1859,14 @@ static int fts3ScanInteriorNode(
99 zCsr += fts3GetVarint32(zCsr, &nSuffix);
100
101 assert( nPrefix>=0 && nSuffix>=0 );
102- if( &zCsr[nSuffix]>zEnd ){
103+ if( nPrefix>zCsr-zNode || nSuffix>zEnd-zCsr ){
104 rc = FTS_CORRUPT_VTAB;
105 goto finish_scan;
106 }
107- if( nPrefix+nSuffix>nAlloc ){
108+ if( (i64)nPrefix+nSuffix>nAlloc ){
109 char *zNew;
110- nAlloc = (nPrefix+nSuffix) * 2;
111- zNew = (char *)sqlite3_realloc(zBuffer, nAlloc);
112+ nAlloc = ((i64)nPrefix+nSuffix) * 2;
113+ zNew = (char *)sqlite3_realloc64(zBuffer, nAlloc);
114 if( !zNew ){
115 rc = SQLITE_NOMEM;
116 goto finish_scan;
117diff --git a/ext/fts3/fts3_write.c b/ext/fts3/fts3_write.c
118index 0baf82b76..8fc658912 100644
119--- a/ext/fts3/fts3_write.c
120+++ b/ext/fts3/fts3_write.c
121@@ -1374,15 +1374,19 @@ static int fts3SegReaderNext(
122 ** safe (no risk of overread) even if the node data is corrupted. */
123 pNext += fts3GetVarint32(pNext, &nPrefix);
124 pNext += fts3GetVarint32(pNext, &nSuffix);
125- if( nPrefix<0 || nSuffix<=0
126- || &pNext[nSuffix]>&pReader->aNode[pReader->nNode]
127+ if( nSuffix<=0
128+ || (&pReader->aNode[pReader->nNode] - pNext)<nSuffix
129+ || nPrefix>pReader->nTermAlloc
130 ){
131 return FTS_CORRUPT_VTAB;
132 }
133
134- if( nPrefix+nSuffix>pReader->nTermAlloc ){
135- int nNew = (nPrefix+nSuffix)*2;
136- char *zNew = sqlite3_realloc(pReader->zTerm, nNew);
137+ /* Both nPrefix and nSuffix were read by fts3GetVarint32() and so are
138+ ** between 0 and 0x7FFFFFFF. But the sum of the two may cause integer
139+ ** overflow - hence the (i64) casts. */
140+ if( (i64)nPrefix+nSuffix>(i64)pReader->nTermAlloc ){
141+ i64 nNew = ((i64)nPrefix+nSuffix)*2;
142+ char *zNew = sqlite3_realloc64(pReader->zTerm, nNew);
143 if( !zNew ){
144 return SQLITE_NOMEM;
145 }
146@@ -1404,7 +1408,7 @@ static int fts3SegReaderNext(
147 ** b-tree node. And that the final byte of the doclist is 0x00. If either
148 ** of these statements is untrue, then the data structure is corrupt.
149 */
150- if( &pReader->aDoclist[pReader->nDoclist]>&pReader->aNode[pReader->nNode]
151+ if( (&pReader->aNode[pReader->nNode] - pReader->aDoclist)<pReader->nDoclist
152 || (pReader->nPopulate==0 && pReader->aDoclist[pReader->nDoclist-1])
153 ){
154 return FTS_CORRUPT_VTAB;
155@@ -3730,6 +3734,9 @@ static int nodeReaderNext(NodeReader *p){
156 }
157 p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nSuffix);
158
159+ if( nPrefix>p->iOff || nSuffix>p->nNode-p->iOff ){
160+ return SQLITE_CORRUPT_VTAB;
161+ }
162 blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc);
163 if( rc==SQLITE_OK ){
164 memcpy(&p->term.a[nPrefix], &p->aNode[p->iOff], nSuffix);
165@@ -3737,6 +3744,9 @@ static int nodeReaderNext(NodeReader *p){
166 p->iOff += nSuffix;
167 if( p->iChild==0 ){
168 p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &p->nDoclist);
169+ if( (p->nNode-p->iOff)<p->nDoclist ){
170+ return SQLITE_CORRUPT_VTAB;
171+ }
172 p->aDoclist = &p->aNode[p->iOff];
173 p->iOff += p->nDoclist;
174 }
175@@ -3744,7 +3754,6 @@ static int nodeReaderNext(NodeReader *p){
176 }
177
178 assert( p->iOff<=p->nNode );
179-
180 return rc;
181 }
182
183diff --git a/src/select.c b/src/select.c
184index bc5960fe4..fd39cbc7f 100644
185--- a/src/select.c
186+++ b/src/select.c
187@@ -2318,6 +2318,13 @@ static void generateWithRecursiveQuery(
188 Expr *pLimit; /* Saved LIMIT and OFFSET */
189 int regLimit, regOffset; /* Registers used by LIMIT and OFFSET */
190
191+#ifndef SQLITE_OMIT_WINDOWFUNC
192+ if( p->pWin ){
193+ sqlite3ErrorMsg(pParse, "cannot use window functions in recursive queries");
194+ return;
195+ }
196+#endif
197+
198 /* Obtain authorization to do a recursive query */
199 if( sqlite3AuthCheck(pParse, SQLITE_RECURSIVE, 0, 0, 0) ) return;
200
201@@ -4067,7 +4074,7 @@ static int flattenSubquery(
202 #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
203
204 /*
205-** A structure to keep track of all of the column values that fixed to
206+** A structure to keep track of all of the column values that are fixed to
207 ** a known value due to WHERE clause constraints of the form COLUMN=VALUE.
208 */
209 typedef struct WhereConst WhereConst;
210@@ -4079,13 +4086,28 @@ struct WhereConst {
211 };
212
213 /*
214-** Add a new entry to the pConst object
215+** Add a new entry to the pConst object. Except, do not add duplicate
216+** pColumn entires.
217 */
218 static void constInsert(
219- WhereConst *pConst,
220- Expr *pColumn,
221- Expr *pValue
222+ WhereConst *pConst, /* The WhereConst into which we are inserting */
223+ Expr *pColumn, /* The COLUMN part of the constraint */
224+ Expr *pValue /* The VALUE part of the constraint */
225 ){
226+ int i;
227+ assert( pColumn->op==TK_COLUMN );
228+
229+ /* 2018-10-25 ticket [cf5ed20f]
230+ ** Make sure the same pColumn is not inserted more than once */
231+ for(i=0; i<pConst->nConst; i++){
232+ const Expr *pExpr = pConst->apExpr[i*2];
233+ assert( pExpr->op==TK_COLUMN );
234+ if( pExpr->iTable==pColumn->iTable
235+ && pExpr->iColumn==pColumn->iColumn
236+ ){
237+ return; /* Already present. Return without doing anything. */
238+ }
239+ }
240
241 pConst->nConst++;
242 pConst->apExpr = sqlite3DbReallocOrFree(pConst->pParse->db, pConst->apExpr,
243diff --git a/src/sqliteInt.h b/src/sqliteInt.h
244index 90d645680..b00b1482c 100644
245--- a/src/sqliteInt.h
246+++ b/src/sqliteInt.h
247@@ -3179,6 +3179,7 @@ struct AuthContext {
248 */
249 #define OPFLAG_NCHANGE 0x01 /* OP_Insert: Set to update db->nChange */
250 /* Also used in P2 (not P5) of OP_Delete */
251+#define OPFLAG_NOCHNG 0x01 /* OP_VColumn nochange for UPDATE */
252 #define OPFLAG_EPHEM 0x01 /* OP_Column: Ephemeral output is ok */
253 #define OPFLAG_LASTROWID 0x20 /* Set to update db->lastRowid */
254 #define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */
255diff --git a/src/update.c b/src/update.c
256index 94e169fd0..23756b3b1 100644
257--- a/src/update.c
258+++ b/src/update.c
259@@ -863,7 +863,7 @@ static void updateVirtualTable(
260 sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i);
261 }else{
262 sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i);
263- sqlite3VdbeChangeP5(v, 1); /* Enable sqlite3_vtab_nochange() */
264+ sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG);/* Enable sqlite3_vtab_nochange() */
265 }
266 }
267 if( HasRowid(pTab) ){
268diff --git a/src/vdbe.c b/src/vdbe.c
269index e57a19797..65d618cac 100644
270--- a/src/vdbe.c
271+++ b/src/vdbe.c
272@@ -6957,10 +6957,11 @@ case OP_VFilter: { /* jump */
273 **
274 ** If the VColumn opcode is being used to fetch the value of
275 ** an unchanging column during an UPDATE operation, then the P5
276-** value is 1. Otherwise, P5 is 0. The P5 value is returned
277-** by sqlite3_vtab_nochange() routine and can be used
278-** by virtual table implementations to return special "no-change"
279-** marks which can be more efficient, depending on the virtual table.
280+** value is OPFLAG_NOCHNG. This will cause the sqlite3_vtab_nochange()
281+** function to return true inside the xColumn method of the virtual
282+** table implementation. The P5 column might also contain other
283+** bits (OPFLAG_LENGTHARG or OPFLAG_TYPEOFARG) but those bits are
284+** unused by OP_VColumn.
285 */
286 case OP_VColumn: {
287 sqlite3_vtab *pVtab;
288@@ -6982,7 +6983,8 @@ case OP_VColumn: {
289 assert( pModule->xColumn );
290 memset(&sContext, 0, sizeof(sContext));
291 sContext.pOut = pDest;
292- if( pOp->p5 ){
293+ testcase( (pOp->p5 & OPFLAG_NOCHNG)==0 && pOp->p5!=0 );
294+ if( pOp->p5 & OPFLAG_NOCHNG ){
295 sqlite3VdbeMemSetNull(pDest);
296 pDest->flags = MEM_Null|MEM_Zero;
297 pDest->u.nZero = 0;
298diff --git a/src/vdbeaux.c b/src/vdbeaux.c
299index 5ec3d131e..99df43596 100644
300--- a/src/vdbeaux.c
301+++ b/src/vdbeaux.c
302@@ -4557,7 +4557,9 @@ int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){
303 (void)getVarint32((u8*)m.z, szHdr);
304 testcase( szHdr==3 );
305 testcase( szHdr==m.n );
306- if( unlikely(szHdr<3 || (int)szHdr>m.n) ){
307+ testcase( szHdr>0x7fffffff );
308+ assert( m.n>=0 );
309+ if( unlikely(szHdr<3 || szHdr>(unsigned)m.n) ){
310 goto idx_rowid_corruption;
311 }
312
313diff --git a/src/wherecode.c b/src/wherecode.c
314index 65cbc4ca2..f75c2b5d2 100644
315--- a/src/wherecode.c
316+++ b/src/wherecode.c
317@@ -425,7 +425,7 @@ static Expr *removeUnindexableInClauseTerms(
318 for(i=iEq; i<pLoop->nLTerm; i++){
319 if( pLoop->aLTerm[i]->pExpr==pX ){
320 int iField = pLoop->aLTerm[i]->iField - 1;
321- assert( pOrigRhs->a[iField].pExpr!=0 );
322+ if( pOrigRhs->a[iField].pExpr==0 ) continue; /* Duplicate PK column */
323 pRhs = sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr);
324 pOrigRhs->a[iField].pExpr = 0;
325 assert( pOrigLhs->a[iField].pExpr!=0 );
326diff --git a/src/whereexpr.c b/src/whereexpr.c
327index 808c0d21c..6786dcacb 100644
328--- a/src/whereexpr.c
329+++ b/src/whereexpr.c
330@@ -1382,6 +1382,7 @@ static void exprAnalyze(
331 if( pExpr->op==TK_NOTNULL
332 && pExpr->pLeft->op==TK_COLUMN
333 && pExpr->pLeft->iColumn>=0
334+ && !ExprHasProperty(pExpr, EP_FromJoin)
335 && OptimizationEnabled(db, SQLITE_Stat34)
336 ){
337 Expr *pNewExpr;
338diff --git a/test/fts3corrupt4.test b/test/fts3corrupt4.test
339new file mode 100644
340index 000000000..52c3d8caf
341--- /dev/null
342+++ b/test/fts3corrupt4.test
343@@ -0,0 +1,147 @@
344+# 2006 September 9
345+#
346+# The author disclaims copyright to this source code. In place of
347+# a legal notice, here is a blessing:
348+#
349+# May you do good and not evil.
350+# May you find forgiveness for yourself and forgive others.
351+# May you share freely, never taking more than you give.
352+#
353+#*************************************************************************
354+# This file implements regression tests for SQLite library. The
355+# focus of this script is testing the FTS3 module.
356+#
357+# $Id: fts3aa.test,v 1.1 2007/08/20 17:38:42 shess Exp $
358+#
359+
360+set testdir [file dirname $argv0]
361+source $testdir/tester.tcl
362+set testprefix fts3corrupt4
363+
364+# If SQLITE_ENABLE_FTS3 is defined, omit this file.
365+ifcapable !fts3 {
366+ finish_test
367+ return
368+}
369+
370+do_execsql_test 1.0 {
371+ BEGIN;
372+ CREATE VIRTUAL TABLE ft USING fts3;
373+ INSERT INTO ft VALUES('aback');
374+ INSERT INTO ft VALUES('abaft');
375+ INSERT INTO ft VALUES('abandon');
376+ COMMIT;
377+}
378+
379+proc blob {a} { binary decode hex $a }
380+db func blob blob
381+
382+do_execsql_test 1.1 {
383+ SELECT quote(root) FROM ft_segdir;
384+} {X'0005616261636B03010200030266740302020003046E646F6E03030200'}
385+
386+do_execsql_test 1.2 {
387+ UPDATE ft_segdir SET root = blob(
388+ '0005616261636B03010200 FFFFFFFF0702 66740302020003046E646F6E03030200'
389+ );
390+}
391+
392+do_catchsql_test 1.3 {
393+ SELECT * FROM ft WHERE ft MATCH 'abandon';
394+} {1 {database disk image is malformed}}
395+
396+#-------------------------------------------------------------------------
397+reset_db
398+do_execsql_test 2.0.0 {
399+ CREATE VIRTUAL TABLE ft USING fts3;
400+ INSERT INTO ft(ft) VALUES('nodesize=32');
401+}
402+do_test 2.0.1 {
403+ for {set i 0} {$i < 12} {incr i} {
404+ execsql {
405+ BEGIN;
406+ INSERT INTO ft VALUES('abc' || $i);
407+ INSERT INTO ft VALUES('abc' || $i || 'x' );
408+ INSERT INTO ft VALUES('abc' || $i || 'xx' );
409+ COMMIT
410+ }
411+ }
412+ execsql {
413+ SELECT count(*) FROM ft_segdir;
414+ SELECT count(*) FROM ft_segments;
415+ }
416+} {12 0}
417+
418+do_execsql_test 2.1 {
419+ INSERT INTO ft(ft) VALUES('merge=1,4');
420+ SELECT count(*) FROM ft_segdir;
421+ SELECT count(*) FROM ft_segments;
422+} {12 3}
423+
424+do_execsql_test 2.2 {
425+ SELECT quote(block) FROM ft_segments WHERE blockid=2
426+} {X'00056162633130031F0200'}
427+
428+db func blob blob
429+do_execsql_test 2.3.1 {
430+ UPDATE ft_segments SET block =
431+ blob('00056162633130031F0200 FFFFFFFF07FF55 66740302020003046E646F6E03030200')
432+ WHERE blockid=2;
433+} {}
434+do_catchsql_test 2.3.2 {
435+ INSERT INTO ft(ft) VALUES('merge=1,4');
436+} {1 {database disk image is malformed}}
437+
438+do_execsql_test 2.4.1 {
439+ UPDATE ft_segments SET block =
440+ blob('00056162633130031F0200 02FFFFFFFF07 66740302020003046E646F6E03030200')
441+ WHERE blockid=2;
442+} {}
443+do_catchsql_test 2.4.2 {
444+ INSERT INTO ft(ft) VALUES('merge=1,4');
445+} {1 {database disk image is malformed}}
446+
447+do_execsql_test 2.5.1 {
448+ UPDATE ft_segments SET block =
449+ blob('00056162633130031F0200 0202 6674 FFFFFF070302020003046E646F6E030200')
450+ WHERE blockid=2;
451+} {}
452+do_catchsql_test 2.5.2 {
453+ INSERT INTO ft(ft) VALUES('merge=1,4');
454+} {1 {database disk image is malformed}}
455+
456+#-------------------------------------------------------------------------
457+reset_db
458+do_execsql_test 3.0.0 {
459+ CREATE VIRTUAL TABLE ft USING fts3;
460+ INSERT INTO ft(ft) VALUES('nodesize=32');
461+}
462+do_test 3.0.1 {
463+ execsql BEGIN
464+ for {set i 0} {$i < 20} {incr i} {
465+ execsql { INSERT INTO ft VALUES('abc' || $i) }
466+ }
467+ execsql {
468+ COMMIT;
469+ SELECT count(*) FROM ft_segdir;
470+ SELECT count(*) FROM ft_segments;
471+ }
472+} {1 5}
473+
474+do_execsql_test 3.1 {
475+ SELECT quote(root) FROM ft_segdir
476+} {X'0101056162633132040136030132030136'}
477+
478+db func blob blob
479+do_execsql_test 3.2 {
480+ UPDATE ft_segdir
481+ SET root = blob('0101056162633132FFFFFFFF070236030132030136');
482+}
483+
484+do_catchsql_test 3.1 {
485+ SELECT * FROM ft WHERE ft MATCH 'abc20'
486+} {1 {database disk image is malformed}}
487+
488+finish_test
489+
490+
491diff --git a/test/permutations.test b/test/permutations.test
492index f71b0b88e..5631f64bc 100644
493--- a/test/permutations.test
494+++ b/test/permutations.test
495@@ -255,6 +255,7 @@ test_suite "fts3" -prefix "" -description {
496 fts3am.test fts3an.test fts3ao.test fts3atoken.test
497 fts3auto.test fts3aux1.test fts3aux2.test fts3b.test
498 fts3comp1.test fts3conf.test fts3corrupt2.test fts3corrupt.test
499+ fts3corrupt4.test
500 fts3cov.test fts3c.test fts3defer2.test fts3defer3.test
501 fts3defer.test fts3drop.test fts3d.test fts3e.test
502 fts3expr2.test fts3expr3.test fts3expr4.test fts3expr5.test
503diff --git a/test/rowvalue.test b/test/rowvalue.test
504index b8ba2e044..2a2f8a9d1 100644
505--- a/test/rowvalue.test
506+++ b/test/rowvalue.test
507@@ -546,4 +546,15 @@ do_catchsql_test 20.1 {
508 SELECT 1 WHERE (2,(2,0)) IS (2,(2,0));
509 } {0 1}
510
511+# 2018-11-03: Ticket https://www.sqlite.org/src/info/1a84668dcfdebaf1
512+# Assertion fault when doing row-value operations on a primary key
513+# containing duplicate columns.
514+#
515+do_execsql_test 21.0 {
516+ DROP TABLE IF EXISTS t1;
517+ CREATE TABLE t1(a,b,PRIMARY KEY(b,b));
518+ INSERT INTO t1 VALUES(1,2),(3,4),(5,6);
519+ SELECT * FROM t1 WHERE (a,b) IN (VALUES(1,2));
520+} {1 2}
521+
522 finish_test
523diff --git a/test/where.test b/test/where.test
524index db0bc47a7..1f38065c6 100644
525--- a/test/where.test
526+++ b/test/where.test
527@@ -1413,4 +1413,17 @@ do_execsql_test where-21.1 {
528 4 0 1
529 }
530
531+# 2018-11-05: ticket [https://www.sqlite.org/src/tktview/65eb38f6e46de8c75e188a]
532+# Incorrect result in LEFT JOIN when STAT4 is enabled.
533+#
534+sqlite3 db :memory:
535+do_execsql_test where-22.1 {
536+ CREATE TABLE t1(a INT);
537+ CREATE INDEX t1a ON t1(a);
538+ INSERT INTO t1(a) VALUES(NULL),(NULL),(42),(NULL),(NULL);
539+ CREATE TABLE t2(dummy INT);
540+ SELECT count(*) FROM t1 LEFT JOIN t2 ON a IS NOT NULL;
541+} {5}
542+
543+
544 finish_test
545diff --git a/test/whereL.test b/test/whereL.test
546index 3fe725b87..d0e5f0b60 100644
547--- a/test/whereL.test
548+++ b/test/whereL.test
549@@ -111,4 +111,15 @@ do_execsql_test 302 {
550 AND B.id=subq.zz;
551 } {1}
552
553+# 2018-10-25: Ticket [cf5ed20f]
554+# Incorrect join result with duplicate WHERE clause constraint.
555+#
556+do_execsql_test 400 {
557+ CREATE TABLE x(a, b, c);
558+ CREATE TABLE y(a, b);
559+ INSERT INTO x VALUES (1, 0, 1);
560+ INSERT INTO y VALUES (1, 2);
561+ SELECT x.a FROM x JOIN y ON x.c = y.a WHERE x.b = 1 AND x.b = 1;
562+} {}
563+
564 finish_test
565diff --git a/test/with1.test b/test/with1.test
566index f8965399f..f9b41ff61 100644
567--- a/test/with1.test
568+++ b/test/with1.test
569@@ -865,6 +865,27 @@ do_catchsql_test 16.1 {
570 SELECT * FROM i;
571 } {1 {recursive aggregate queries not supported}}
572
573+# Or window-function recursive queries. Ticket e8275b41.
574+#
575+ifcapable windowfunc {
576+ do_catchsql_test 16.2 {
577+ WITH RECURSIVE
578+ i(x) AS (VALUES(1) UNION SELECT count(*) OVER () FROM i)
579+ SELECT * FROM i;
580+ } {1 {cannot use window functions in recursive queries}}
581+ do_catchsql_test 16.3 {
582+ WITH RECURSIVE
583+ t(id, parent) AS (VALUES(1,2)),
584+ q(id, parent, rn) AS (
585+ VALUES(1,2,3)
586+ UNION ALL
587+ SELECT t.*, ROW_NUMBER() OVER (ORDER BY t.id) AS rn
588+ FROM q JOIN t ON t.parent = q.id
589+ )
590+ SELECT * FROM q;
591+ } {1 {cannot use window functions in recursive queries}}
592+}
593+
594 #-------------------------------------------------------------------------
595 do_execsql_test 17.1 {
596 WITH x(a) AS (