/ Check-in [2ec7e50c]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Avoid comparing pointer values after the object that they point to has been deleted.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | alter-table-rename-column
Files: files | file ages | folders
SHA3-256: 2ec7e50cbc0e7a4308d51be3c9416229b187a6a8abdd982c154edc256cd6da1f
User & Date: dan 2018-09-05 14:36:05
Context
2018-09-05
17:45
Fix some test script errors. And an incorrect assert() in fts5. check-in: f804336f user: dan tags: alter-table-rename-column
14:36
Avoid comparing pointer values after the object that they point to has been deleted. check-in: 2ec7e50c user: dan tags: alter-table-rename-column
08:28
Fix minor code issues in alter.c. check-in: 18ba35b8 user: dan tags: alter-table-rename-column
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/alter.c.

   620    620     RenameToken *pList;             /* List of tokens to overwrite */
   621    621     int nList;                      /* Number of tokens in pList */
   622    622     int iCol;                       /* Index of column being renamed */
   623    623     Table *pTab;                    /* Table being ALTERed */ 
   624    624     const char *zOld;               /* Old column name */
   625    625   };
   626    626   
   627         -void renameTokenClear(Parse *pParse, void *pPtr){
   628         -  RenameToken *p;
   629         -  assert( pPtr || pParse->db->mallocFailed );
   630         -  for(p=pParse->pRename; p; p=p->pNext){
   631         -    if( p->p==pPtr ){
   632         -      p->p = 0;
          627  +#ifdef SQLITE_DEBUG
          628  +/*
          629  +** This function is only for debugging. It performs two tasks:
          630  +**
          631  +**   1. Checks that pointer pPtr does not already appear in the 
          632  +**      rename-token list.
          633  +**
          634  +**   2. Dereferences each pointer in the rename-token list.
          635  +**
          636  +** The second is most effective when debugging under valgrind or
          637  +** address-sanitizer or similar. If any of these pointers no longer 
          638  +** point to valid objects, an exception is raised by the memory-checking 
          639  +** tool.
          640  +**
          641  +** The point of this is to prevent comparisons of invalid pointer values.
          642  +** Even though this always seems to work, it is undefined according to the
          643  +** C standard. Example of undefined comparison:
          644  +**
          645  +**     sqlite3_free(x);
          646  +**     if( x==y ) ...
          647  +**
          648  +** Technically, as x no longer points into a valid object or to the byte
          649  +** following a valid object, it may not be used in comparison operations.
          650  +*/
          651  +void renameTokenCheckAll(Parse *pParse, void *pPtr){
          652  +  if( pParse->nErr==0 && pParse->db->mallocFailed==0 ){
          653  +    RenameToken *p;
          654  +    u8 i = 0;
          655  +    for(p=pParse->pRename; p; p=p->pNext){
          656  +      if( p->p ){
          657  +        assert( p->p!=pPtr );
          658  +        i += *(u8*)(p->p);
          659  +      }
   633    660       }
   634    661     }
   635    662   }
          663  +#else
          664  +# define renameTokenCheckAll(x,y)
          665  +#endif
   636    666   
   637    667   /*
   638    668   ** Add a new RenameToken object mapping parse tree element pPtr into
   639    669   ** token *pToken to the Parse object currently under construction.
   640    670   **
   641    671   ** Return a copy of pPtr.
   642    672   */
   643    673   void *sqlite3RenameTokenMap(Parse *pParse, void *pPtr, Token *pToken){
   644    674     RenameToken *pNew;
   645    675     assert( pPtr || pParse->db->mallocFailed );
   646         -
   647         -  renameTokenClear(pParse, pPtr);
          676  +  renameTokenCheckAll(pParse, pPtr);
   648    677     pNew = sqlite3DbMallocZero(pParse->db, sizeof(RenameToken));
   649    678     if( pNew ){
   650    679       pNew->p = pPtr;
   651    680       pNew->t = *pToken;
   652    681       pNew->pNext = pParse->pRename;
   653    682       pParse->pRename = pNew;
   654    683     }
................................................................................
   659    688   /*
   660    689   ** It is assumed that there is already a RenameToken object associated
   661    690   ** with parse tree element pFrom. This function remaps the associated token
   662    691   ** to parse tree element pTo.
   663    692   */
   664    693   void sqlite3RenameTokenRemap(Parse *pParse, void *pTo, void *pFrom){
   665    694     RenameToken *p;
   666         -  if( pTo ) renameTokenClear(pParse, pTo);
          695  +  renameTokenCheckAll(pParse, pTo);
   667    696     for(p=pParse->pRename; p; p=p->pNext){
   668    697       if( p->p==pFrom ){
   669    698         p->p = pTo;
   670    699         break;
   671    700       }
   672    701     }
   673    702   }
          703  +
          704  +/*
          705  +** Walker callback used by sqlite3RenameExprUnmap().
          706  +*/
          707  +static int renameUnmapExprCb(Walker *pWalker, Expr *pExpr){
          708  +  Parse *pParse = pWalker->pParse;
          709  +  sqlite3RenameTokenRemap(pParse, 0, (void*)pExpr);
          710  +  return WRC_Continue;
          711  +}
          712  +
          713  +/*
          714  +** Remove all nodes that are part of expression pExpr from the rename list.
          715  +*/
          716  +void sqlite3RenameExprUnmap(Parse *pParse, Expr *pExpr){
          717  +  Walker sWalker;
          718  +  memset(&sWalker, 0, sizeof(Walker));
          719  +  sWalker.pParse = pParse;
          720  +  sWalker.xExprCallback = renameUnmapExprCb;
          721  +  sqlite3WalkExpr(&sWalker, pExpr);
          722  +}
   674    723   
   675    724   /*
   676    725   ** Free the list of RenameToken objects given in the second argument
   677    726   */
   678    727   static void renameTokenFree(sqlite3 *db, RenameToken *pToken){
   679    728     RenameToken *pNext;
   680    729     RenameToken *p;

Changes to src/build.c.

  1278   1278         x.u.zToken = sqlite3DbSpanDup(db, zStart, zEnd);
  1279   1279         x.pLeft = pExpr;
  1280   1280         x.flags = EP_Skip;
  1281   1281         pCol->pDflt = sqlite3ExprDup(db, &x, EXPRDUP_REDUCE);
  1282   1282         sqlite3DbFree(db, x.u.zToken);
  1283   1283       }
  1284   1284     }
         1285  +  if( IN_RENAME_OBJECT ){
         1286  +    sqlite3RenameExprUnmap(pParse, pExpr);
         1287  +  }
  1285   1288     sqlite3ExprDelete(db, pExpr);
  1286   1289   }
  1287   1290   
  1288   1291   /*
  1289   1292   ** Backwards Compatibility Hack:
  1290   1293   ** 
  1291   1294   ** Historical versions of SQLite accepted strings as column names in

Changes to src/sqliteInt.h.

  4237   4237   void sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*);
  4238   4238   int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
  4239   4239   void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
  4240   4240   void sqlite3AlterFinishAddColumn(Parse *, Token *);
  4241   4241   void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
  4242   4242   void *sqlite3RenameTokenMap(Parse*, void*, Token*);
  4243   4243   void sqlite3RenameTokenRemap(Parse*, void *pTo, void *pFrom);
         4244  +void sqlite3RenameExprUnmap(Parse*, Expr*);
  4244   4245   CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
  4245   4246   char sqlite3AffinityType(const char*, Column*);
  4246   4247   void sqlite3Analyze(Parse*, Token*, Token*);
  4247   4248   int sqlite3InvokeBusyHandler(BusyHandler*, sqlite3_file*);
  4248   4249   int sqlite3FindDb(sqlite3*, Token*);
  4249   4250   int sqlite3FindDbName(sqlite3 *, const char *);
  4250   4251   int sqlite3AnalysisLoad(sqlite3*,int iDB);