]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Merge trunk changes. Fix a possible NULL-pointer deference in WITH clause
authordrh <drh@noemail.net>
Thu, 16 Jan 2014 04:37:13 +0000 (04:37 +0000)
committerdrh <drh@noemail.net>
Thu, 16 Jan 2014 04:37:13 +0000 (04:37 +0000)
name resolution.

FossilOrigin-Name: 7f953b568baa3eede0b9c144be0b9bc86496341a

1  2 
manifest
manifest.uuid
src/select.c

diff --cc manifest
index ddbc25013852693643c74c6dac0f64f7cfbe024c,b7d3993e06843164b61f0b91c6cc2937eb3620d6..dce447d221877063391d68f1633aeacf55b2ef2d
+++ 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 d95e8d3935c11ae7aa6c55a86260cf991f1093f3,d14b8afba5c0f9f21153282eb18e0d39fd813026..b6146d545b721bd57f50776851d3e7e00226f026
@@@ -1,1 -1,1 +1,1 @@@
- c95823cd451f7721174393817a801403647467db
 -f61a70589ac7e05008a362bd9d5b7bde5d07a758
++7f953b568baa3eede0b9c144be0b9bc86496341a
diff --cc src/select.c
index b4ce7be9ed0cfbe2f221206b347ef859d6b0540b,58458974091e0704e73b35746f1478ef57a038d5..96eae3ff6a9689f88658bdf14a1f4d2f17c5baa2
@@@ -3482,174 -3394,6 +3483,174 @@@ static int convertCompoundSelectToSubqu
    return WRC_Continue;
  }
  
-   if( pItem->zDatabase==0 ){
-     const char *zName = pItem->zName;
 +#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){
++  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; i<p->nCte; 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: