Add interfaces sqlite3_bind_pointer(), sqlite3_result_pointer(), and
sqlite3_value_pointer() used to safely move pointer values through SQL without exposing underlying memory address information. Cherrypick from commit [8201f4e1] on branch-3.18. FossilOrigin-Name: 4cb67252d39fc537601f75532ec8271994aed8bae4d20ba48a3262b52ed004c0
This commit is contained in:
+9
-11
@@ -3317,9 +3317,8 @@ static int fts3ColumnMethod(
|
||||
*/
|
||||
sqlite3_result_int64(pCtx, pCsr->iPrevId);
|
||||
}else if( iCol==p->nColumn ){
|
||||
/* The extra column whose name is the same as the table.
|
||||
** Return a blob which is a pointer to the cursor. */
|
||||
sqlite3_result_blob(pCtx, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT);
|
||||
/* The extra column whose name is the same as the table. */
|
||||
sqlite3_result_pointer(pCtx, pCsr);
|
||||
}else if( iCol==p->nColumn+2 && pCsr->pExpr ){
|
||||
sqlite3_result_int64(pCtx, pCsr->iLangid);
|
||||
}else{
|
||||
@@ -3531,18 +3530,17 @@ static int fts3FunctionArg(
|
||||
sqlite3_value *pVal, /* argv[0] passed to function */
|
||||
Fts3Cursor **ppCsr /* OUT: Store cursor handle here */
|
||||
){
|
||||
Fts3Cursor *pRet;
|
||||
if( sqlite3_value_type(pVal)!=SQLITE_BLOB
|
||||
|| sqlite3_value_bytes(pVal)!=sizeof(Fts3Cursor *)
|
||||
){
|
||||
int rc;
|
||||
*ppCsr = (Fts3Cursor*)sqlite3_value_pointer(pVal);
|
||||
if( (*ppCsr)!=0 ){
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc);
|
||||
sqlite3_result_error(pContext, zErr, -1);
|
||||
sqlite3_free(zErr);
|
||||
return SQLITE_ERROR;
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
memcpy(&pRet, sqlite3_value_blob(pVal), sizeof(Fts3Cursor *));
|
||||
*ppCsr = pRet;
|
||||
return SQLITE_OK;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
C Add\sextra\sdefenses\sagainst\sstrategically\scorrupt\sdatabases\sto\sfts3/4.
|
||||
D 2018-12-19T01:57:20.527
|
||||
C Add\sinterfaces\ssqlite3_bind_pointer(),\ssqlite3_result_pointer(),\sand\nsqlite3_value_pointer()\sused\sto\ssafely\smove\spointer\svalues\sthrough\sSQL\swithout\nexposing\sunderlying\smemory\saddress\sinformation.\sCherrypick\sfrom\scommit\n[8201f4e1]\son\sbranch-3.18.
|
||||
D 2018-12-19T16:03:56.772
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in f0088ff0d2ac949fce6de7c00f13a99ac5bdb663
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@@ -78,7 +78,7 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
|
||||
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
|
||||
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
|
||||
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
|
||||
F ext/fts3/fts3.c ba4d2e512a36c20e884d6107a38dc38410e0015950fc7c3fd1e811c3d88a67fa
|
||||
F ext/fts3/fts3.c 2e76a808d0dd7d34da20cd97bec7bd1f89e5c72c4f20046716a1d654d9678ee6
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3Int.h c84125c666ee54cef6efce6ff64abb0d0e2f4535
|
||||
F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1
|
||||
@@ -345,9 +345,9 @@ F src/resolve.c 1954a0f01bf65d78d7d559aea3d5c67f33376d91
|
||||
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
|
||||
F src/select.c 0bc9cd2e1cacfdc9cdc9a83884cc100f166e80a4
|
||||
F src/shell.c d25df04168d6ba5a4fa05bdbf859df667f9eb621
|
||||
F src/sqlite.h.in dc35357824c6bb84a04acd4e99dee3e07299a8c6
|
||||
F src/sqlite.h.in f16e13c65c4499c93a911273ce03dc87aa7fe4ddc1ae3c226797143790734b9c
|
||||
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
|
||||
F src/sqlite3ext.h 4b66e3e3435da4b4c8c83696d0349f0c503b3924
|
||||
F src/sqlite3ext.h 0d46dc1375254b211aeb62734002a6a5596cb965c816f2233f8b206129213723
|
||||
F src/sqliteInt.h e21cc96bc24161df7373f6b24367cf580496889d
|
||||
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
|
||||
F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
|
||||
@@ -408,11 +408,11 @@ F src/util.c fc612367108b74573c5fd13a85d0a23027f438bd
|
||||
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
|
||||
F src/vdbe.c 1e0bf8d6a2308ce916d444ef399921407fd5d972
|
||||
F src/vdbe.h 4bc88bd0e06f8046ee6ab7487c0015e85ad949ad
|
||||
F src/vdbeInt.h 8b867eac234e28627ffcace3cd4b4b79bbec664b
|
||||
F src/vdbeapi.c 020681b943e77766b32ae1cddf86d7831b7374ca
|
||||
F src/vdbeInt.h b4c31fcd3520797ae142ceea05342d41b1f34482055b541da29ae04309d236e5
|
||||
F src/vdbeapi.c a34cabb4a4285756180fa79637f9e61a55bada4408a164daf2f67b0e472eebb8
|
||||
F src/vdbeaux.c fd00b489ab3f44f2dca1e4344faf289b7bfcf649
|
||||
F src/vdbeblob.c 565fabd302f5fca3bdf3d56cac330483616a39b6
|
||||
F src/vdbemem.c 19b3036aa4d676e7103b0fb5efd6327da455f915
|
||||
F src/vdbemem.c dcd74d9480b50597133206f41d112c51df3e1511ee61af3a3d0379ef1fa852b4
|
||||
F src/vdbesort.c f5009e7a35e3065635d8918b9a31f498a499976b
|
||||
F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0
|
||||
F src/vtab.c 2a8b44aa372c33f6154208e7a7f6c44254549806
|
||||
@@ -722,7 +722,7 @@ F test/fts3prefix2.test e1f0a822ca661dced7f12ce392e14eaf65609dce
|
||||
F test/fts3query.test f33eb71a1fe1084ea585eeb7ee76b390729f5170
|
||||
F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0
|
||||
F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e
|
||||
F test/fts3snippet.test 63dbd687d5bf5191f1b8e6a0977aa9c1e28a7004
|
||||
F test/fts3snippet.test 235098c9078a11b27fc8001b58c845c5da3c25b7a8274b2fcb9f25d6065d5acb
|
||||
F test/fts3sort.test ed34c716a11cc2009a35210e84ad5f9c102362ca
|
||||
F test/fts3tok1.test 178c050199af8c05299b1ad572514ce1c54b7827
|
||||
F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d
|
||||
@@ -1391,8 +1391,8 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P dfbfd34b3ff4d6da6f2db56e4664d7058f10c098
|
||||
Q +4bb21d8205b3c72b94442018a0544ecc55e3320ef2593f0e3350142b7f2a7663
|
||||
R 22e0b536e8f483d58bcb1a29460375cf
|
||||
U drh
|
||||
Z 4c2d78cc158ff3dc7aa21579c2a29a43
|
||||
P 882ef4e39b5a2aae3786caef492c77af67693b5123ce9c40d99c10c55dc02f98
|
||||
Q +72de49f204277191f62601cce70d5013ec30b564a01063f1e841019c78ae6c77
|
||||
R cf13503fc49cb85466747faa5df4b552
|
||||
U dan
|
||||
Z a7be1e512c71fcc72c6af46ee43923b0
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
882ef4e39b5a2aae3786caef492c77af67693b5123ce9c40d99c10c55dc02f98
|
||||
4cb67252d39fc537601f75532ec8271994aed8bae4d20ba48a3262b52ed004c0
|
||||
+25
-4
@@ -3532,6 +3532,15 @@ typedef struct sqlite3_context sqlite3_context;
|
||||
** [sqlite3_blob_open | incremental BLOB I/O] routines.
|
||||
** ^A negative value for the zeroblob results in a zero-length BLOB.
|
||||
**
|
||||
** ^The sqlite3_bind_pointer(S,I,P) routine causes the I-th parameter in
|
||||
** [prepared statement] S to have an SQL value of NULL, but to also be
|
||||
** associated with the pointer P.
|
||||
** ^The sqlite3_bind_pointer() routine can be used to pass
|
||||
** host-language pointers into [application-defined SQL functions].
|
||||
** ^A parameter that is initialized using [sqlite3_bind_pointer()] appears
|
||||
** to be an ordinary SQL NULL value to everything other than
|
||||
** [sqlite3_value_pointer()].
|
||||
**
|
||||
** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer
|
||||
** for the [prepared statement] or with a prepared statement for which
|
||||
** [sqlite3_step()] has been called more recently than [sqlite3_reset()],
|
||||
@@ -3565,6 +3574,7 @@ int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
|
||||
int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64,
|
||||
void(*)(void*), unsigned char encoding);
|
||||
int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
|
||||
int sqlite3_bind_pointer(sqlite3_stmt*, int, void*);
|
||||
int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
|
||||
int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64);
|
||||
|
||||
@@ -4329,6 +4339,11 @@ SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
|
||||
** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces
|
||||
** extract UTF-16 strings as big-endian and little-endian respectively.
|
||||
**
|
||||
** ^If [sqlite3_value] object V was initialized
|
||||
** using [sqlite3_bind_pointer(S,I,P)] or [sqlite3_result_pointer(C,P)], then
|
||||
** sqlite3_value_pointer(V) will return the pointer P. Otherwise,
|
||||
** sqlite3_value_pointer(V) returns a NULL.
|
||||
**
|
||||
** ^(The sqlite3_value_numeric_type() interface attempts to apply
|
||||
** numeric affinity to the value. This means that an attempt is
|
||||
** made to convert the value to an integer or floating point. If
|
||||
@@ -4356,6 +4371,7 @@ const unsigned char *sqlite3_value_text(sqlite3_value*);
|
||||
const void *sqlite3_value_text16(sqlite3_value*);
|
||||
const void *sqlite3_value_text16le(sqlite3_value*);
|
||||
const void *sqlite3_value_text16be(sqlite3_value*);
|
||||
void *sqlite3_value_pointer(sqlite3_value*);
|
||||
int sqlite3_value_type(sqlite3_value*);
|
||||
int sqlite3_value_numeric_type(sqlite3_value*);
|
||||
|
||||
@@ -4368,10 +4384,6 @@ int sqlite3_value_numeric_type(sqlite3_value*);
|
||||
** information can be used to pass a limited amount of context from
|
||||
** one SQL function to another. Use the [sqlite3_result_subtype()]
|
||||
** routine to set the subtype for the return value of an SQL function.
|
||||
**
|
||||
** SQLite makes no use of subtype itself. It merely passes the subtype
|
||||
** from the result of one [application-defined SQL function] into the
|
||||
** input of another.
|
||||
*/
|
||||
unsigned int sqlite3_value_subtype(sqlite3_value*);
|
||||
|
||||
@@ -4648,6 +4660,14 @@ typedef void (*sqlite3_destructor_type)(void*);
|
||||
** [unprotected sqlite3_value] object is required, so either
|
||||
** kind of [sqlite3_value] object can be used with this interface.
|
||||
**
|
||||
** ^The sqlite3_result_pointer(C,P) interface sets the result to an
|
||||
** SQL NULL value, just like [sqlite3_result_null(C)], except that it
|
||||
** also associates the host-language pointer P with that NULL value such
|
||||
** that the pointer can be retrieved within an
|
||||
** [application-defined SQL function] using [sqlite3_value_pointer()].
|
||||
** This mechanism can be used to pass non-SQL values between
|
||||
** application-defined functions.
|
||||
**
|
||||
** If these routines are called from within the different thread
|
||||
** than the one containing the application-defined function that received
|
||||
** the [sqlite3_context] pointer, the results are undefined.
|
||||
@@ -4671,6 +4691,7 @@ void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
|
||||
void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
|
||||
void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
|
||||
void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
|
||||
void sqlite3_result_pointer(sqlite3_context*, void*);
|
||||
void sqlite3_result_zeroblob(sqlite3_context*, int n);
|
||||
int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n);
|
||||
|
||||
|
||||
@@ -514,6 +514,9 @@ struct sqlite3_api_routines {
|
||||
/* Version 3.9.0 and later */
|
||||
#define sqlite3_value_subtype sqlite3_api->value_subtype
|
||||
#define sqlite3_result_subtype sqlite3_api->result_subtype
|
||||
#define sqlite3_bind_pointer sqlite3_api->bind_pointer
|
||||
#define sqlite3_result_pointer sqlite3_api->result_pointer
|
||||
#define sqlite3_value_pointer sqlite3_api->value_pointer
|
||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
||||
|
||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||
|
||||
+4
-1
@@ -169,6 +169,7 @@ struct Mem {
|
||||
double r; /* Real value used when MEM_Real is set in flags */
|
||||
i64 i; /* Integer value used when MEM_Int is set in flags */
|
||||
int nZero; /* Used when bit MEM_Zero is set in flags */
|
||||
void *pPtr; /* Pointer when flags=MEM_NULL and eSubtype='p' */
|
||||
FuncDef *pDef; /* Used only when flags==MEM_Agg */
|
||||
RowSet *pRowSet; /* Used only when flags==MEM_RowSet */
|
||||
VdbeFrame *pFrame; /* Used when flags==MEM_Frame */
|
||||
@@ -218,7 +219,7 @@ struct Mem {
|
||||
#define MEM_Frame 0x0040 /* Value is a VdbeFrame object */
|
||||
#define MEM_Undefined 0x0080 /* Value is undefined */
|
||||
#define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */
|
||||
#define MEM_TypeMask 0x01ff /* Mask of type bits */
|
||||
#define MEM_TypeMask 0x81ff /* Mask of type bits */
|
||||
|
||||
|
||||
/* Whenever Mem contains a valid string or blob representation, one of
|
||||
@@ -232,6 +233,7 @@ struct Mem {
|
||||
#define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */
|
||||
#define MEM_Agg 0x2000 /* Mem.z points to an agg function context */
|
||||
#define MEM_Zero 0x4000 /* Mem.i contains count of 0s appended to blob */
|
||||
#define MEM_Subtype 0x8000
|
||||
#ifdef SQLITE_OMIT_INCRBLOB
|
||||
#undef MEM_Zero
|
||||
#define MEM_Zero 0x0000
|
||||
@@ -436,6 +438,7 @@ void sqlite3VdbeMemSetInt64(Mem*, i64);
|
||||
#else
|
||||
void sqlite3VdbeMemSetDouble(Mem*, double);
|
||||
#endif
|
||||
void sqlite3VdbeMemSetPointer(Mem*, void*);
|
||||
void sqlite3VdbeMemInit(Mem*,sqlite3*,u16);
|
||||
void sqlite3VdbeMemSetNull(Mem*);
|
||||
void sqlite3VdbeMemSetZeroBlob(Mem*,int);
|
||||
|
||||
@@ -190,6 +190,14 @@ sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){
|
||||
unsigned int sqlite3_value_subtype(sqlite3_value *pVal){
|
||||
return ((Mem*)pVal)->eSubtype;
|
||||
}
|
||||
void *sqlite3_value_pointer(sqlite3_value *pVal){
|
||||
Mem *p = (Mem*)pVal;
|
||||
if( (p->flags & MEM_TypeMask)==(MEM_Null|MEM_Subtype) && p->eSubtype=='p' ){
|
||||
return p->u.pPtr;
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
const unsigned char *sqlite3_value_text(sqlite3_value *pVal){
|
||||
return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8);
|
||||
}
|
||||
@@ -368,6 +376,12 @@ void sqlite3_result_null(sqlite3_context *pCtx){
|
||||
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
||||
sqlite3VdbeMemSetNull(pCtx->pOut);
|
||||
}
|
||||
void sqlite3_result_pointer(sqlite3_context *pCtx, void *pPtr){
|
||||
Mem *pOut = pCtx->pOut;
|
||||
assert( sqlite3_mutex_held(pOut->db->mutex) );
|
||||
sqlite3VdbeMemSetNull(pOut);
|
||||
sqlite3VdbeMemSetPointer(pOut, pPtr);
|
||||
}
|
||||
void sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){
|
||||
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
||||
pCtx->pOut->eSubtype = eSubtype & 0xff;
|
||||
@@ -1346,6 +1360,16 @@ int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
int sqlite3_bind_pointer(sqlite3_stmt *pStmt, int i, void *pPtr){
|
||||
int rc;
|
||||
Vdbe *p = (Vdbe*)pStmt;
|
||||
rc = vdbeUnbind(p, i);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3VdbeMemSetPointer(&p->aVar[i-1], pPtr);
|
||||
sqlite3_mutex_leave(p->db->mutex);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
int sqlite3_bind_text(
|
||||
sqlite3_stmt *pStmt,
|
||||
int i,
|
||||
|
||||
@@ -696,6 +696,17 @@ void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the value stored in *pMem should already be a NULL.
|
||||
** Also store a pointer to go with it.
|
||||
*/
|
||||
void sqlite3VdbeMemSetPointer(Mem *pMem, void *pPtr){
|
||||
assert( pMem->flags==MEM_Null );
|
||||
pMem->flags = MEM_Null|MEM_Subtype;
|
||||
pMem->u.pPtr = pPtr;
|
||||
pMem->eSubtype = 'p';
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
/*
|
||||
** Delete any previous value and set the value stored in *pMem to val,
|
||||
|
||||
@@ -554,7 +554,9 @@ do_test 4.2 {
|
||||
}]
|
||||
} {64}
|
||||
|
||||
|
||||
do_execsql_test 4.3.1 {
|
||||
SELECT quote(t4) FROM t4;
|
||||
} {NULL NULL}
|
||||
|
||||
|
||||
set sqlite_fts3_enable_parentheses 0
|
||||
|
||||
Reference in New Issue
Block a user