diff options
author | drh <drh@noemail.net> | 2016-12-23 13:52:45 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2016-12-23 13:52:45 +0000 |
commit | ce1bbe51b5c57b6487e92fe83c5c168a84c9e051 (patch) | |
tree | 334b07f003c4e05a9796f5eb50211760826f6617 /src | |
parent | f326d66d618c50bfcb348e3023793524da25c28b (diff) | |
download | sqlite-ce1bbe51b5c57b6487e92fe83c5c168a84c9e051.tar.gz sqlite-ce1bbe51b5c57b6487e92fe83c5c168a84c9e051.zip |
Add check to prevent a VList from growing after pointers to labels have been
taken.
FossilOrigin-Name: aa23d7eaf69f5ecbf9500b2353846094cae41e6c
Diffstat (limited to 'src')
-rw-r--r-- | src/expr.c | 1 | ||||
-rw-r--r-- | src/util.c | 32 |
2 files changed, 24 insertions, 9 deletions
diff --git a/src/expr.c b/src/expr.c index 3f8406bc5..ecc6c7928 100644 --- a/src/expr.c +++ b/src/expr.c @@ -3422,6 +3422,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ if( pExpr->u.zToken[1]!=0 ){ const char *z = sqlite3VListNumToName(pParse->pVList, pExpr->iColumn); assert( pExpr->u.zToken[0]=='?' || strcmp(pExpr->u.zToken, z)==0 ); + pParse->pVList[0] = 0; /* Indicate VList may no longer be enlarged */ sqlite3VdbeAppendP4(v, (char*)z, P4_STATIC); } return target; diff --git a/src/util.c b/src/util.c index 5ece9226f..b9684c6c0 100644 --- a/src/util.c +++ b/src/util.c @@ -1457,7 +1457,7 @@ u64 sqlite3LogEstToInt(LogEst x){ /* ** Add a new name/number pair to a VList. This might require that the ** VList object be reallocated, so return the new VList. If an OOM -** error occurs, the original VList freed, NULL is returned, and the +** error occurs, the original VList returned and the ** db->mallocFailed flag is set. ** ** A VList is really just an array of integers. To destroy a VList, @@ -1468,11 +1468,27 @@ u64 sqlite3LogEstToInt(LogEst x){ ** Each name/number pair is encoded by subsequent groups of 3 or more ** integers. ** -** Each name/number pair starts with two integers which are the number +** Each name/number pair starts with two integers which are the numeric ** value for the pair and the size of the name/number pair, respectively. ** The text name overlays one or more following integers. The text name ** is always zero-terminated. -** +** +** Conceptually: +** +** struct VList { +** int nAlloc; // Number of allocated slots +** int nUsed; // Number of used slots +** struct VListEntry { +** int iValue; // Value for this entry +** int nSlot; // Slots used by this entry +** // ... variable name goes here +** } a[0]; +** } +** +** During code generation, pointers to the variable names within the +** VList are taken. When that happens, nAlloc is set to zero as an +** indication that the VList may never again be enlarged, since the +** accompanying realloc() would invalidate the pointers. */ VList *sqlite3VListAdd( sqlite3 *db, /* The database connection used for malloc() */ @@ -1482,18 +1498,16 @@ VList *sqlite3VListAdd( int iVal /* Value to associate with zName */ ){ int nInt; /* number of sizeof(int) objects needed for zName */ - char *z; - int i; + char *z; /* Pointer to where zName will be stored */ + int i; /* Index in pIn[] where zName is stored */ nInt = nName/4 + 3; + assert( pIn==0 || pIn[0]>=3 ); /* Verify ok to add new elements */ if( pIn==0 || pIn[1]+nInt > pIn[0] ){ /* Enlarge the allocation */ int nAlloc = (pIn ? pIn[0]*2 : 10) + nInt; VList *pOut = sqlite3DbRealloc(db, pIn, nAlloc*sizeof(int)); - if( pOut==0 ){ - sqlite3DbFree(db, pIn); - return 0; - } + if( pOut==0 ) return pIn; if( pIn==0 ) pOut[1] = 2; pIn = pOut; pIn[0] = nAlloc; |