Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Make the sqlite_rename_column() SQL function resistant to problems caused by OOMs and/or malformed parameters submitted by hostile application code. Also add additional comments to the RENAME COLUMN logic. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | alter-table-rename-column |
Files: | files | file ages | folders |
SHA3-256: |
87743ddef11749b4017d60abc297abfd |
User & Date: | drh 2018-08-13 17:02:26.434 |
Context
2018-08-14
| ||
16:18 | Fix ALTER TABLE RENAME COLUMN in cases where the column being renamed is an IPK declared with a separate PRIMARY KEY clause - "CREATE TABLE x(y INTEGER, PRIMARY KEY(y))". (check-in: 32ca8418df user: dan tags: alter-table-rename-column) | |
2018-08-13
| ||
17:02 | Make the sqlite_rename_column() SQL function resistant to problems caused by OOMs and/or malformed parameters submitted by hostile application code. Also add additional comments to the RENAME COLUMN logic. (check-in: 87743ddef1 user: drh tags: alter-table-rename-column) | |
15:09 | Fix legacy comments on Token. Begin commenting the new ALTER TABLE RENAME COLUMN code. Fix a memory leak in the sqlite_rename_column() SQL function. (check-in: 32edc89203 user: drh tags: alter-table-rename-column) | |
Changes
Changes to src/alter.c.
︙ | ︙ | |||
936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 | RenameToken *p; for(p=pToken; p; p=pNext){ pNext = p->pNext; sqlite3DbFree(db, p); } } static RenameToken *renameTokenFind(Parse *pParse, void *pPtr){ RenameToken **pp; for(pp=&pParse->pRename; (*pp); pp=&(*pp)->pNext){ if( (*pp)->p==pPtr ){ RenameToken *pToken = *pp; *pp = pToken->pNext; pToken->pNext = 0; return pToken; } } return 0; } static int renameColumnExprCb(Walker *pWalker, Expr *pExpr){ struct RenameCtx *p = pWalker->u.pRename; if( pExpr->op==TK_COLUMN && pExpr->iColumn==p->iCol ){ RenameToken *pTok = renameTokenFind(pWalker->pParse, (void*)pExpr); if( pTok ){ pTok->pNext = p->pList; p->pList = pTok; p->nList++; } } return WRC_Continue; } static RenameToken *renameColumnTokenNext(struct RenameCtx *pCtx){ RenameToken *pBest = pCtx->pList; RenameToken *pToken; RenameToken **pp; for(pToken=pBest->pNext; pToken; pToken=pToken->pNext){ if( pToken->t.z>pBest->t.z ) pBest = pToken; } for(pp=&pCtx->pList; *pp!=pBest; pp=&(*pp)->pNext); *pp = pBest->pNext; return pBest; } /* | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > | 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 | RenameToken *p; for(p=pToken; p; p=pNext){ pNext = p->pNext; sqlite3DbFree(db, p); } } /* ** Return the RenameToken object associated with parse tree element pPtr, ** or a NULL pointer if not found. The RenameToken object returned is ** removed from the list of RenameToken objects attached to the Parse ** object and the caller becomes the new owner of the RenameToken object ** Hence, the caller assumes responsibility for freeing the returned ** RenameToken object. */ static RenameToken *renameTokenFind(Parse *pParse, void *pPtr){ RenameToken **pp; for(pp=&pParse->pRename; (*pp); pp=&(*pp)->pNext){ if( (*pp)->p==pPtr ){ RenameToken *pToken = *pp; *pp = pToken->pNext; pToken->pNext = 0; return pToken; } } return 0; } /* ** This is a Walker expression callback. ** ** For every TK_COLUMN node in the expression tree, search to see ** if the column being references is the column being renamed by an ** ALTER TABLE statement. If it is, then attach its associated ** RenameToken object to the list of RenameToken objects being ** constructed in RenameCtx object at pWalker->u.pRename. */ static int renameColumnExprCb(Walker *pWalker, Expr *pExpr){ struct RenameCtx *p = pWalker->u.pRename; if( pExpr->op==TK_COLUMN && pExpr->iColumn==p->iCol ){ RenameToken *pTok = renameTokenFind(pWalker->pParse, (void*)pExpr); if( pTok ){ pTok->pNext = p->pList; p->pList = pTok; p->nList++; } } return WRC_Continue; } /* ** The RenameCtx contains a list of tokens that reference a column that ** is being renamed by an ALTER TABLE statement. Return the "first" ** RenameToken in the RenameCtx and remove that RenameToken from the ** RenameContext. "First" means the first RenameToken encountered when ** the input SQL from left to right. Repeated calls to this routine ** return all column name tokens in the order that they are encountered ** in the SQL statement. */ static RenameToken *renameColumnTokenNext(struct RenameCtx *pCtx){ RenameToken *pBest = pCtx->pList; RenameToken *pToken; RenameToken **pp; for(pToken=pBest->pNext; pToken; pToken=pToken->pNext){ if( pToken->t.z>pBest->t.z ) pBest = pToken; } for(pp=&pCtx->pList; *pp!=pBest; pp=&(*pp)->pNext); *pp = pBest->pNext; return pBest; } /* ** SQL function: ** ** sqlite_rename_column(zSql, iCol, bQuote, zNew, zTable, zOld) ** ** Do a column rename operation on the CREATE statement given in zSql. ** The iCol-th column (left-most is 0) of table zTable is renamed from zCol ** into zNew. The name should be quoted if bQuote is true. ** ** This function is used internally by the ALTER TABLE RENAME COLUMN command. ** Though accessible to application code, it is not intended for use by ** applications. The existance of this function, and the way it works, ** is subject to change without notice. ** ** If any of the parameters are out-of-bounds, then simply return NULL. ** An out-of-bounds parameter can only occur when the application calls ** this function directly. The parameters will always be well-formed when ** this routine is invoked by the bytecode for a legitimate ALTER TABLE ** statement. */ static void renameColumnFunc( sqlite3_context *context, int NotUsed, sqlite3_value **argv ){ sqlite3 *db = sqlite3_context_db_handle(context); |
︙ | ︙ | |||
1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 | Index *pIdx; char *zOut = 0; char *zQuot = 0; /* Quoted version of zNew */ int nQuot = 0; /* Length of zQuot in bytes */ int i; memset(&sCtx, 0, sizeof(sCtx)); sCtx.iCol = sqlite3_value_int(argv[1]); memset(&sParse, 0, sizeof(sParse)); sParse.eParseMode = PARSE_MODE_RENAME_COLUMN; sParse.db = db; sParse.nQueryLoop = 1; rc = sqlite3RunParser(&sParse, zSql, &zErr); assert( sParse.pNewTable==0 || sParse.pNewIndex==0 ); | > > > > > | 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 | Index *pIdx; char *zOut = 0; char *zQuot = 0; /* Quoted version of zNew */ int nQuot = 0; /* Length of zQuot in bytes */ int i; if( zSql==0 ) return; if( zNew==0 ) return; if( zTable==0 ) return; if( zOld==0 ) return; memset(&sCtx, 0, sizeof(sCtx)); sCtx.iCol = sqlite3_value_int(argv[1]); if( sCtx.iCol<0 ) return; memset(&sParse, 0, sizeof(sParse)); sParse.eParseMode = PARSE_MODE_RENAME_COLUMN; sParse.db = db; sParse.nQueryLoop = 1; rc = sqlite3RunParser(&sParse, zSql, &zErr); assert( sParse.pNewTable==0 || sParse.pNewIndex==0 ); |
︙ | ︙ |