From: drh Date: Thu, 16 Jan 2014 04:37:13 +0000 (+0000) Subject: Merge trunk changes. Fix a possible NULL-pointer deference in WITH clause X-Git-Tag: version-3.8.3~45^2~7 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7b19f252475ed3636e0d14d8843f33192b9c1a04;p=thirdparty%2Fsqlite.git Merge trunk changes. Fix a possible NULL-pointer deference in WITH clause name resolution. FossilOrigin-Name: 7f953b568baa3eede0b9c144be0b9bc86496341a --- 7b19f252475ed3636e0d14d8843f33192b9c1a04 diff --cc manifest index ddbc250138,b7d3993e06..dce447d221 --- a/manifest +++ b/manifest @@@ -1,5 -1,5 +1,5 @@@ - C Remove\san\sALWAYS()\sthat\sis\sno\slonger\salways\strue. - D 2014-01-15T20:10:15.729 -C Fix\sharmless\scompiler\swarning\sin\sLEMON. -D 2014-01-14T10:17:21.693 ++C Merge\strunk\schanges.\s\sFix\sa\spossible\sNULL-pointer\sdeference\sin\sWITH\sclause\nname\sresolution. ++D 2014-01-16T04:37:13.145 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@@ -206,10 -206,10 +206,10 @@@ F src/os.c 1b147e4cf7cc39e618115c14a086 F src/os.h 4a46270a64e9193af4a0aaa3bc2c66dc07c29b3f F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04 F src/os_unix.c 3a4dcb554d3c915075766162f28c3fd4cdb75968 - F src/os_win.c 16eac0961603182ffc10c02b39fe830126538e07 + F src/os_win.c 1b21af72c5fa6f9e519a5fcab33e80d182b1aedb F src/pager.c efa923693e958696eee69b205a20bfbc402c8480 F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428 -F src/parse.y 3c5384533a8bfce5abd256cc9cb2c38bec05ad61 +F src/parse.y 824eeb752c026b551bda2b66163889d7664b42e4 F src/pcache.c f8043b433a57aba85384a531e3937a804432a346 F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222 F src/pcache1.c 57fee9a9a617218f5037afbbe49b09da65bde56b @@@ -217,10 -217,10 +217,10 @@@ F src/pragma.c ed409ce4104cf4d9de6ead40 F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337 F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269 F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece -F src/resolve.c 7eda9097b29fcf3d2b42fdc17d1de672134e09b6 +F src/resolve.c ae278d8ce037883323f677e78c241f64289f12ec F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 - F src/select.c ab437f252415754963b1adfa501120d5364da3ef - F src/shell.c a3541193d5fce37e91dad8ef46a9505aa7c9b344 -F src/select.c 996d8b88603edbd478aaa70b75d535a3ddea933d ++F src/select.c c9af659146dd1fe924fbfb14a7477f6b2b90f03b + F src/shell.c 9f3bc02a658b8f61d2cbe60cfc482f660c1c6c48 F src/sqlite.h.in d94a8b89522f526ba711182ee161e06f8669bcc9 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc @@@ -1150,7 -1148,7 +1150,7 @@@ F tool/vdbe-compress.tcl 0cf56e9263a152 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff - P 3908e2ea2e7e5f466cbbbffdc27e0fe8dc9751ac - R ec33026d9a1a4e4ae1384253da1cbe65 -P 1e131094b522103a0829f72193b067b04e42ce82 -R fe4a4148cfbc4d588ee2679597656da4 -U mistachkin -Z d589f5ec7c09b4ac8c97497c20166016 ++P c95823cd451f7721174393817a801403647467db f61a70589ac7e05008a362bd9d5b7bde5d07a758 ++R 8a379a80b7992f91c6a6d54869d6bc5d +U drh - Z d40f91394b02fb8b902b74395abcc185 ++Z 69979a1b738527f03c61f40bf3b0d3cb diff --cc manifest.uuid index d95e8d3935,d14b8afba5..b6146d545b --- a/manifest.uuid +++ b/manifest.uuid @@@ -1,1 -1,1 +1,1 @@@ - c95823cd451f7721174393817a801403647467db -f61a70589ac7e05008a362bd9d5b7bde5d07a758 ++7f953b568baa3eede0b9c144be0b9bc86496341a diff --cc src/select.c index b4ce7be9ed,5845897409..96eae3ff6a --- a/src/select.c +++ b/src/select.c @@@ -3482,174 -3394,6 +3483,174 @@@ static int convertCompoundSelectToSubqu return WRC_Continue; } +#ifndef SQLITE_OMIT_CTE +/* +** Argument pWith (which may be NULL) points to a linked list of nested +** WITH contexts, from inner to outermost. If the table identified by +** FROM clause element pItem is really a common-table-expression (CTE) +** then return a pointer to the CTE definition for that table. Otherwise +** return NULL. +*/ +static struct Cte *searchWith(With *pWith, struct SrcList_item *pItem){ - if( pItem->zDatabase==0 ){ - const char *zName = pItem->zName; ++ const char *zName; ++ if( pItem->zDatabase==0 && (zName = pItem->zName)!=0 ){ + With *p; + for(p=pWith; p; p=p->pOuter){ + int i; + for(i=0; inCte; i++){ + if( sqlite3StrICmp(zName, p->a[i].zName)==0 ){ + return &p->a[i]; + } + } + } + } + return 0; +} + +/* The code generator maintains a stack of active WITH clauses +** with the inner-most WITH clause being at the top of the stack. +** +** These routines push and pull WITH clauses on the stack. +*/ +void sqlite3WithPush(Parse *pParse, With *pWith){ + if( pWith ){ + pWith->pOuter = pParse->pWith; + pParse->pWith = pWith; + } +} + +/* +** If argument pCte is not NULL, check if it is already a part of the +** stack of CTEs stored by the parser. If so, this indicates an illegal +** recursive reference in a CTE, set of mutually recursive CTEs. Store +** an error in the parser and return SQLITE_ERROR if this is the case. +** +** Otherwise, if pCte is not already part of the stack of CTEs stored +** in the parser, push it onto the stop of that stack. +*/ +static int ctePush(Parse *pParse, struct Cte *pCte){ + if( pCte ){ + struct Cte *p; + for(p=pParse->pCte; p; p=p->pOuterCte){ + if( p==pCte ){ + sqlite3ErrorMsg( + pParse, "illegal recursive defininition in cte: %s", pCte->zName + ); + return SQLITE_ERROR; + } + } + + pCte->pOuterCte = pParse->pCte; + pParse->pCte = pCte; + } + return SQLITE_OK; +} +/* +** If argument pCte is not NULL, it must be a pointer to the CTE currently +** on top of the stack of CTEs stored in the parser. Remove it from that +** stack. +*/ +static void ctePop(Parse *pParse, struct Cte *pCte){ + if( pCte ){ + assert( pParse->pCte==pCte ); + pParse->pCte = pCte->pOuterCte; + } +} + +/* +** This function checks if argument pFrom refers to a CTE declared by +** a WITH clause on the stack currently maintained by the parser. And, +** if currently processing a CTE expression, if it is a recursive +** reference to the current CTE. +** +** If pFrom falls into either of the two categories above, pFrom->pTab +** and other fields are populated accordingly. The caller should check +** (pFrom->pTab!=0) to determine whether or not a successful match +** was found. +** +** Whether or not a match is found, SQLITE_OK is returned if no error +** occurs. If an error does occur, an error message is stored in the +** parser and some error code other than SQLITE_OK returned. +*/ +static int withExpand( + Walker *pWalker, + struct SrcList_item *pFrom +){ + Table *pTab; + Parse *pParse = pWalker->pParse; + sqlite3 *db = pParse->db; + struct Cte *pCte; + + assert( pFrom->pTab==0 ); + + pCte = searchWith(pParse->pWith, pFrom); + if( pCte==0 ){ + /* no-op */ + }else if( pCte==pParse->pCte && (pTab = pCte->pTab) ){ + /* This is the recursive part of a recursive CTE */ + assert( pFrom->pTab==0 && pFrom->isRecursive==0 && pFrom->pSelect==0 ); + pFrom->pTab = pTab; + pFrom->isRecursive = 1; + pTab->nRef++; + }else{ + ExprList *pEList; + Select *pSel; + Select *pLeft; /* Left-most SELECT statement */ + int bRecursive; + + pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table)); + if( pTab==0 ) return WRC_Abort; + pTab->nRef = 1; + pTab->zName = sqlite3MPrintf(db, "%s", pCte->zName); + pTab->iPKey = -1; + pTab->nRowEst = 1048576; + pTab->tabFlags |= TF_Ephemeral; + pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0); + if( db->mallocFailed ) return SQLITE_NOMEM; + assert( pFrom->pSelect ); + + if( ctePush(pParse, pCte) ) return WRC_Abort; + pSel = pFrom->pSelect; + bRecursive = (pSel->op==TK_ALL || pSel->op==TK_UNION); + if( bRecursive ){ + assert( pSel->pPrior ); + sqlite3WalkSelect(pWalker, pSel->pPrior); + }else{ + sqlite3WalkSelect(pWalker, pSel); + } + + for(pLeft=pSel; pLeft->pPrior; pLeft=pLeft->pPrior); + pEList = pLeft->pEList; + if( pCte->pCols ){ + if( pEList->nExpr!=pCte->pCols->nExpr ){ + sqlite3ErrorMsg(pParse, "cte \"%s\" returns %d values for %d columns", + pCte->zName, pEList->nExpr, pCte->pCols->nExpr + ); + return WRC_Abort; + } + pEList = pCte->pCols; + } + + selectColumnsFromExprList(pParse, pEList, &pTab->nCol, &pTab->aCol); + + if( bRecursive ){ + int nRef = pTab->nRef; + pCte->pTab = pTab; + sqlite3WalkSelect(pWalker, pSel); + pCte->pTab = 0; + if( pTab->nRef > nRef){ + pSel->pRecurse = pTab; + assert( pTab->tnum==0 ); + } + } + + ctePop(pParse, pCte); + } + + return SQLITE_OK; +} +#endif + /* ** This routine is a Walker callback for "expanding" a SELECT statement. ** "Expanding" means to do the following: