From 327bd59216eda424653c1b2f97b70fc0952541f7 Mon Sep 17 00:00:00 2001 From: danielk1977 Date: Fri, 13 Jan 2006 13:01:19 +0000 Subject: [PATCH] Fix a vdbe stack overflow problem that could occur with a correlated sub-query. (CVS 2938) FossilOrigin-Name: caa7da807d6578f7d8848978a7d3175b6ea1743b --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/where.c | 26 ++++++++++++++++++-------- test/select1.test | 27 ++++++++++++++++++++++++++- 4 files changed, 52 insertions(+), 17 deletions(-) diff --git a/manifest b/manifest index 6818463651..f4d9f2d1f9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sa\sfew\sduplicate\svariable\sinitializations\sin\ssqlite3BtreeCursor().\s(CVS\s2937) -D 2006-01-13T11:22:07 +C Fix\sa\svdbe\sstack\soverflow\sproblem\sthat\scould\soccur\swith\sa\scorrelated\ssub-query.\s(CVS\s2938) +D 2006-01-13T13:01:19 F Makefile.in ab3ffd8d469cef4477257169b82810030a6bb967 F Makefile.linux-gcc aee18d8a05546dcf1888bd4547e442008a49a092 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -94,7 +94,7 @@ F src/vdbeapi.c afd3837cea0dec93dcb4724d073c84fa0da68e23 F src/vdbeaux.c 1d765d671ae31a067b2b064c3f193690f91eea62 F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5 F src/vdbemem.c dd08a0eea4868ac4a2d91fdec32424308b1db772 -F src/where.c a12b4542f6cee2f2180854c2e16bef84225866ec +F src/where.c 1e19c96cf8a55310118130ce251511be72e766f7 F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42 F test/all.test a23fcbbf1f53515bde840d78732a6d94c673b327 F test/alter.test b94b640063e725d062b2997bd2810ac39195c718 @@ -217,7 +217,7 @@ F test/rollback.test fc6be5a5e4b1347fd96777c65484a24fc75e8f0e F test/rowid.test 040a3bef06f970c45f5fcd14b2355f7f4d62f0cf F test/safety.test 4a06934e45d03b8b50ebcd8d174eb0367d2fd851 F test/schema.test 8a2ae440fb15f5798a68059e8746402f3137be46 -F test/select1.test 386cc42da2d0fade5dfb25c85118009c0ef26637 +F test/select1.test ed95ce4c27ab390bcd2d573a0c77ad42599b8a88 F test/select2.test f3c2678c3a9f3cf08ec4988a3845bda64be6d9e3 F test/select3.test 8fece41cd8f2955131b3f973a7123bec60b6e65e F test/select4.test c239f516aa31f42f2ef7c6d7cd01105f08f934ca @@ -340,7 +340,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513 -P dd705955429d847af85ffaf248976bcd1d861852 -R 40dd1503ed21c91f3caf35fc59e72104 +P 5e46ec01ff3fe8654fc267efbb12d2d1b01c48aa +R dcb9fd33555e157fe0ad7a05ab19e97e U danielk1977 -Z 69d38632915b9f5de07c1fb25a99a6fb +Z 81727b2a642e7063a9db6351127fac13 diff --git a/manifest.uuid b/manifest.uuid index d63270ee26..075157754c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5e46ec01ff3fe8654fc267efbb12d2d1b01c48aa \ No newline at end of file +caa7da807d6578f7d8848978a7d3175b6ea1743b \ No newline at end of file diff --git a/src/where.c b/src/where.c index 3c794672c1..207b4ebeff 100644 --- a/src/where.c +++ b/src/where.c @@ -16,7 +16,7 @@ ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** -** $Id: where.c,v 1.195 2006/01/13 06:33:25 danielk1977 Exp $ +** $Id: where.c,v 1.196 2006/01/13 13:01:19 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -1164,14 +1164,24 @@ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){ ** * Check the top nColumn entries on the stack. If any ** of those entries are NULL, jump immediately to brk, ** which is the loop exit, since no index entry will match -** if any part of the key is NULL. +** if any part of the key is NULL. Pop (nColumn+nExtra) +** elements from the stack. ** ** * Construct a probe entry from the top nColumn entries in -** the stack with affinities appropriate for index pIdx. +** the stack with affinities appropriate for index pIdx. +** Only nColumn elements are popped from the stack in this case +** (by OP_MakeRecord). +** */ -static void buildIndexProbe(Vdbe *v, int nColumn, int brk, Index *pIdx){ +static void buildIndexProbe( + Vdbe *v, + int nColumn, + int nExtra, + int brk, + Index *pIdx +){ sqlite3VdbeAddOp(v, OP_NotNull, -nColumn, sqlite3VdbeCurrentAddr(v)+3); - sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0); + sqlite3VdbeAddOp(v, OP_Pop, nColumn+nExtra, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, brk); sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); sqlite3IndexAffinityStr(v, pIdx); @@ -1783,7 +1793,7 @@ WhereInfo *sqlite3WhereBegin( if( testOp!=OP_Noop ){ int nCol = nEq + topLimit; pLevel->iMem = pParse->nMem++; - buildIndexProbe(v, nCol, brk, pIdx); + buildIndexProbe(v, nCol, nEq, brk, pIdx); if( bRev ){ int op = topEq ? OP_MoveLe : OP_MoveLt; sqlite3VdbeAddOp(v, op, iIdxCur, brk); @@ -1818,7 +1828,7 @@ WhereInfo *sqlite3WhereBegin( } if( nEq>0 || btmLimit ){ int nCol = nEq + btmLimit; - buildIndexProbe(v, nCol, brk, pIdx); + buildIndexProbe(v, nCol, 0, brk, pIdx); if( bRev ){ pLevel->iMem = pParse->nMem++; sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1); @@ -1872,7 +1882,7 @@ WhereInfo *sqlite3WhereBegin( /* Generate a single key that will be used to both start and terminate ** the search */ - buildIndexProbe(v, nEq, brk, pIdx); + buildIndexProbe(v, nEq, 0, brk, pIdx); sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 0); /* Generate code (1) to move to the first matching element of the table. diff --git a/test/select1.test b/test/select1.test index c51cbe14df..4998866b03 100644 --- a/test/select1.test +++ b/test/select1.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this file is testing the SELECT statement. # -# $Id: select1.test,v 1.45 2005/12/15 10:11:32 danielk1977 Exp $ +# $Id: select1.test,v 1.46 2006/01/13 13:01:20 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -801,4 +801,29 @@ ifcapable {compound && subquery} { } ;# ifcapable compound +# Check for a VDBE stack growth problem that existed at one point. +# +do_test select1-13.1 { + execsql { + BEGIN; + create TABLE abc(a, b, c, PRIMARY KEY(a, b)); + INSERT INTO abc VALUES(1, 1, 1); + } + for {set i 0} {$i<10} {incr i} { + execsql { + INSERT INTO abc SELECT a+(select max(a) FROM abc), + b+(select max(a) FROM abc), c+(select max(a) FROM abc) FROM abc; + } + } + execsql {COMMIT} + + # This used to seg-fault when the problem existed. + execsql { + SELECT count( + (SELECT a FROM abc WHERE a = NULL AND b >= upper.c) + ) FROM abc AS upper; + } +} {0} + finish_test + -- 2.39.5