aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <>2023-01-25 16:56:24 +0000
committerdrh <>2023-01-25 16:56:24 +0000
commitb604f1456e4116b6a60d0d24a0ed1e678617dcf3 (patch)
treea57d0215a3c6ba7fec7b10d4d90118af14307715 /src
parenta0fe1e7d137334aaf7e6518165894bc5fe15dbe8 (diff)
downloadsqlite-b604f1456e4116b6a60d0d24a0ed1e678617dcf3.tar.gz
sqlite-b604f1456e4116b6a60d0d24a0ed1e678617dcf3.zip
Enhance the sqlite3_vtab_in_first() and sqlite3_vtab_in_next() interfaces so
that they reliably return SQLITE_ERROR (and not SQLITE_MISUSE) if they are invoked on a parameter that did not have multi-value IN processing enabled via a prior call to sqlite3_vtab_in(). See [forum:/forumpost/a823d4a3d5f73def|forum thread a823d4a3d5f73def]. FossilOrigin-Name: 144326dc171025dc8b5a77bebd8de3c19d5244ab807f5aa41f95313a25b880bc
Diffstat (limited to 'src')
-rw-r--r--src/sqlite.h.in5
-rw-r--r--src/vdbe.c2
-rw-r--r--src/vdbeInt.h2
-rw-r--r--src/vdbeapi.c22
4 files changed, 25 insertions, 6 deletions
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index af482ff0b..0ae65aa75 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -9806,14 +9806,13 @@ int sqlite3_vtab_in(sqlite3_index_info*, int iCons, int bHandle);
** is undefined and probably harmful.
**
** The X parameter in a call to sqlite3_vtab_in_first(X,P) or
-** sqlite3_vtab_in_next(X,P) must be one of the parameters to the
+** sqlite3_vtab_in_next(X,P) should be one of the parameters to the
** xFilter method which invokes these routines, and specifically
** a parameter that was previously selected for all-at-once IN constraint
** processing use the [sqlite3_vtab_in()] interface in the
** [xBestIndex|xBestIndex method]. ^(If the X parameter is not
** an xFilter argument that was selected for all-at-once IN constraint
-** processing, then these routines return [SQLITE_MISUSE])^ or perhaps
-** exhibit some other undefined or harmful behavior.
+** processing, then these routines return [SQLITE_ERROR].)^
**
** ^(Use these routines to access all values on the right-hand side
** of the IN constraint using code like the following:
diff --git a/src/vdbe.c b/src/vdbe.c
index db6086233..fb5e04a81 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -8031,7 +8031,7 @@ case OP_VInitIn: { /* out2, ncycle */
pRhs->pOut = &aMem[pOp->p3];
pOut = out2Prerelease(p, pOp);
pOut->flags = MEM_Null;
- sqlite3VdbeMemSetPointer(pOut, pRhs, "ValueList", sqlite3_free);
+ sqlite3VdbeMemSetPointer(pOut, pRhs, "ValueList", sqlite3VdbeValueListFree);
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
diff --git a/src/vdbeInt.h b/src/vdbeInt.h
index 03f4ec542..b901a0180 100644
--- a/src/vdbeInt.h
+++ b/src/vdbeInt.h
@@ -657,6 +657,8 @@ int sqlite3VdbeSorterRewind(const VdbeCursor *, int *);
int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *);
int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *);
+void sqlite3VdbeValueListFree(void*);
+
#ifdef SQLITE_DEBUG
void sqlite3VdbeIncrWriteCounter(Vdbe*, VdbeCursor*);
void sqlite3VdbeAssertAbortable(Vdbe*);
diff --git a/src/vdbeapi.c b/src/vdbeapi.c
index e080449c5..647976b5f 100644
--- a/src/vdbeapi.c
+++ b/src/vdbeapi.c
@@ -883,6 +883,17 @@ int sqlite3_vtab_nochange(sqlite3_context *p){
}
/*
+** The destructor function for a ValueList object. This needs to be
+** a separate function, unknowable to the application, to ensure that
+** calls to sqlite3_vtab_in_first()/sqlite3_vtab_in_next() that are not
+** preceeded by activation of IN processing via sqlite3_vtab_int() do not
+** try to access a fake ValueList object inserted by a hostile extension.
+*/
+void sqlite3VdbeValueListFree(void *pToDelete){
+ sqlite3_free(pToDelete);
+}
+
+/*
** Implementation of sqlite3_vtab_in_first() (if bNext==0) and
** sqlite3_vtab_in_next() (if bNext!=0).
*/
@@ -896,8 +907,15 @@ static int valueFromValueList(
*ppOut = 0;
if( pVal==0 ) return SQLITE_MISUSE;
- pRhs = (ValueList*)sqlite3_value_pointer(pVal, "ValueList");
- if( pRhs==0 ) return SQLITE_MISUSE;
+ if( pVal->xDel!=sqlite3VdbeValueListFree ){
+ return SQLITE_ERROR;
+ }else{
+ assert( (pVal->flags&(MEM_TypeMask|MEM_Term|MEM_Subtype)) ==
+ (MEM_Null|MEM_Term|MEM_Subtype) );
+ assert( pVal->eSubtype=='p' );
+ assert( pVal->u.zPType!=0 && strcmp(pVal->u.zPType,"ValueList")==0 );
+ pRhs = (ValueList*)pVal->z;
+ }
if( bNext ){
rc = sqlite3BtreeNext(pRhs->pCsr, 0);
}else{