/ Check-in [2ec7e50c]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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 Unified Diffs Ignore Whitespace Patch

Changes to src/alter.c.

620
621
622
623
624
625
626
























627

628
629

630
631
632


633
634
635




636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
...
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673




















674
675
676
677
678
679
680
  RenameToken *pList;             /* List of tokens to overwrite */
  int nList;                      /* Number of tokens in pList */
  int iCol;                       /* Index of column being renamed */
  Table *pTab;                    /* Table being ALTERed */ 
  const char *zOld;               /* Old column name */
};

























void renameTokenClear(Parse *pParse, void *pPtr){

  RenameToken *p;
  assert( pPtr || pParse->db->mallocFailed );

  for(p=pParse->pRename; p; p=p->pNext){
    if( p->p==pPtr ){
      p->p = 0;


    }
  }
}





/*
** Add a new RenameToken object mapping parse tree element pPtr into
** token *pToken to the Parse object currently under construction.
**
** Return a copy of pPtr.
*/
void *sqlite3RenameTokenMap(Parse *pParse, void *pPtr, Token *pToken){
  RenameToken *pNew;
  assert( pPtr || pParse->db->mallocFailed );

  renameTokenClear(pParse, pPtr);
  pNew = sqlite3DbMallocZero(pParse->db, sizeof(RenameToken));
  if( pNew ){
    pNew->p = pPtr;
    pNew->t = *pToken;
    pNew->pNext = pParse->pRename;
    pParse->pRename = pNew;
  }
................................................................................
/*
** It is assumed that there is already a RenameToken object associated
** with parse tree element pFrom. This function remaps the associated token
** to parse tree element pTo.
*/
void sqlite3RenameTokenRemap(Parse *pParse, void *pTo, void *pFrom){
  RenameToken *p;
  if( pTo ) renameTokenClear(pParse, pTo);
  for(p=pParse->pRename; p; p=p->pNext){
    if( p->p==pFrom ){
      p->p = pTo;
      break;
    }
  }
}





















/*
** Free the list of RenameToken objects given in the second argument
*/
static void renameTokenFree(sqlite3 *db, RenameToken *pToken){
  RenameToken *pNext;
  RenameToken *p;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
<
>
|
|
<
>
>
|
|
|
>
>
>
>










<
|







 







|







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653

654
655
656

657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675

676
677
678
679
680
681
682
683
...
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
  RenameToken *pList;             /* List of tokens to overwrite */
  int nList;                      /* Number of tokens in pList */
  int iCol;                       /* Index of column being renamed */
  Table *pTab;                    /* Table being ALTERed */ 
  const char *zOld;               /* Old column name */
};

#ifdef SQLITE_DEBUG
/*
** This function is only for debugging. It performs two tasks:
**
**   1. Checks that pointer pPtr does not already appear in the 
**      rename-token list.
**
**   2. Dereferences each pointer in the rename-token list.
**
** The second is most effective when debugging under valgrind or
** address-sanitizer or similar. If any of these pointers no longer 
** point to valid objects, an exception is raised by the memory-checking 
** tool.
**
** The point of this is to prevent comparisons of invalid pointer values.
** Even though this always seems to work, it is undefined according to the
** C standard. Example of undefined comparison:
**
**     sqlite3_free(x);
**     if( x==y ) ...
**
** Technically, as x no longer points into a valid object or to the byte
** following a valid object, it may not be used in comparison operations.
*/
void renameTokenCheckAll(Parse *pParse, void *pPtr){
  if( pParse->nErr==0 && pParse->db->mallocFailed==0 ){
    RenameToken *p;

    u8 i = 0;
    for(p=pParse->pRename; p; p=p->pNext){
      if( p->p ){

        assert( p->p!=pPtr );
        i += *(u8*)(p->p);
      }
    }
  }
}
#else
# define renameTokenCheckAll(x,y)
#endif

/*
** Add a new RenameToken object mapping parse tree element pPtr into
** token *pToken to the Parse object currently under construction.
**
** Return a copy of pPtr.
*/
void *sqlite3RenameTokenMap(Parse *pParse, void *pPtr, Token *pToken){
  RenameToken *pNew;
  assert( pPtr || pParse->db->mallocFailed );

  renameTokenCheckAll(pParse, pPtr);
  pNew = sqlite3DbMallocZero(pParse->db, sizeof(RenameToken));
  if( pNew ){
    pNew->p = pPtr;
    pNew->t = *pToken;
    pNew->pNext = pParse->pRename;
    pParse->pRename = pNew;
  }
................................................................................
/*
** It is assumed that there is already a RenameToken object associated
** with parse tree element pFrom. This function remaps the associated token
** to parse tree element pTo.
*/
void sqlite3RenameTokenRemap(Parse *pParse, void *pTo, void *pFrom){
  RenameToken *p;
  renameTokenCheckAll(pParse, pTo);
  for(p=pParse->pRename; p; p=p->pNext){
    if( p->p==pFrom ){
      p->p = pTo;
      break;
    }
  }
}

/*
** Walker callback used by sqlite3RenameExprUnmap().
*/
static int renameUnmapExprCb(Walker *pWalker, Expr *pExpr){
  Parse *pParse = pWalker->pParse;
  sqlite3RenameTokenRemap(pParse, 0, (void*)pExpr);
  return WRC_Continue;
}

/*
** Remove all nodes that are part of expression pExpr from the rename list.
*/
void sqlite3RenameExprUnmap(Parse *pParse, Expr *pExpr){
  Walker sWalker;
  memset(&sWalker, 0, sizeof(Walker));
  sWalker.pParse = pParse;
  sWalker.xExprCallback = renameUnmapExprCb;
  sqlite3WalkExpr(&sWalker, pExpr);
}

/*
** Free the list of RenameToken objects given in the second argument
*/
static void renameTokenFree(sqlite3 *db, RenameToken *pToken){
  RenameToken *pNext;
  RenameToken *p;

Changes to src/build.c.

1278
1279
1280
1281
1282
1283
1284



1285
1286
1287
1288
1289
1290
1291
      x.u.zToken = sqlite3DbSpanDup(db, zStart, zEnd);
      x.pLeft = pExpr;
      x.flags = EP_Skip;
      pCol->pDflt = sqlite3ExprDup(db, &x, EXPRDUP_REDUCE);
      sqlite3DbFree(db, x.u.zToken);
    }
  }



  sqlite3ExprDelete(db, pExpr);
}

/*
** Backwards Compatibility Hack:
** 
** Historical versions of SQLite accepted strings as column names in







>
>
>







1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
      x.u.zToken = sqlite3DbSpanDup(db, zStart, zEnd);
      x.pLeft = pExpr;
      x.flags = EP_Skip;
      pCol->pDflt = sqlite3ExprDup(db, &x, EXPRDUP_REDUCE);
      sqlite3DbFree(db, x.u.zToken);
    }
  }
  if( IN_RENAME_OBJECT ){
    sqlite3RenameExprUnmap(pParse, pExpr);
  }
  sqlite3ExprDelete(db, pExpr);
}

/*
** Backwards Compatibility Hack:
** 
** Historical versions of SQLite accepted strings as column names in

Changes to src/sqliteInt.h.

4237
4238
4239
4240
4241
4242
4243

4244
4245
4246
4247
4248
4249
4250
void sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*);
int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
void sqlite3AlterFinishAddColumn(Parse *, Token *);
void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
void *sqlite3RenameTokenMap(Parse*, void*, Token*);
void sqlite3RenameTokenRemap(Parse*, void *pTo, void *pFrom);

CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
char sqlite3AffinityType(const char*, Column*);
void sqlite3Analyze(Parse*, Token*, Token*);
int sqlite3InvokeBusyHandler(BusyHandler*, sqlite3_file*);
int sqlite3FindDb(sqlite3*, Token*);
int sqlite3FindDbName(sqlite3 *, const char *);
int sqlite3AnalysisLoad(sqlite3*,int iDB);







>







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