Blob Blame History Raw
diff -up sqlite-src-3140200/ext/fts3/fts3.c.cve sqlite-src-3140200/ext/fts3/fts3.c
--- sqlite-src-3140200/ext/fts3/fts3.c.cve	2016-09-13 02:11:06.000000000 +0200
+++ sqlite-src-3140200/ext/fts3/fts3.c	2017-08-08 08:17:35.482017106 +0200
@@ -3318,8 +3318,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);
+    ** Return a pointer to the cursor.  */
+    sqlite3_result_pointer(pCtx, pCsr);
   }else if( iCol==p->nColumn+2 && pCsr->pExpr ){
     sqlite3_result_int64(pCtx, pCsr->iLangid);
   }else{
@@ -3531,16 +3531,13 @@ 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 *)
-  ){
+  Fts3Cursor *pRet = (Fts3Cursor*)sqlite3_value_pointer(pVal);
+  if( pRet==0 ){
     char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc);
     sqlite3_result_error(pContext, zErr, -1);
     sqlite3_free(zErr);
     return SQLITE_ERROR;
   }
-  memcpy(&pRet, sqlite3_value_blob(pVal), sizeof(Fts3Cursor *));
   *ppCsr = pRet;
   return SQLITE_OK;
 }
diff -up sqlite-src-3140200/ext/misc/carray.c.cve sqlite-src-3140200/ext/misc/carray.c
--- sqlite-src-3140200/ext/misc/carray.c.cve	2016-09-13 02:11:06.000000000 +0200
+++ sqlite-src-3140200/ext/misc/carray.c	2017-08-08 08:17:35.483017087 +0200
@@ -73,7 +73,7 @@ typedef struct carray_cursor carray_curs
 struct carray_cursor {
   sqlite3_vtab_cursor base;  /* Base class - must be first */
   sqlite3_int64 iRowid;      /* The rowid */
-  sqlite3_int64 iPtr;        /* Pointer to array of values */
+  void *pPtr;                /* Pointer to the array of values */
   sqlite3_int64 iCnt;        /* Number of integers in the array */
   unsigned char eType;       /* One of the CARRAY_type values */
 };
@@ -167,7 +167,7 @@ static int carrayColumn(
   carray_cursor *pCur = (carray_cursor*)cur;
   sqlite3_int64 x = 0;
   switch( i ){
-    case CARRAY_COLUMN_POINTER:   x = pCur->iPtr;   break;
+    case CARRAY_COLUMN_POINTER:   return SQLITE_OK;
     case CARRAY_COLUMN_COUNT:     x = pCur->iCnt;   break;
     case CARRAY_COLUMN_CTYPE: {
       sqlite3_result_text(ctx, azType[pCur->eType], -1, SQLITE_STATIC);
@@ -176,22 +176,22 @@ static int carrayColumn(
     default: {
       switch( pCur->eType ){
         case CARRAY_INT32: {
-          int *p = (int*)pCur->iPtr;
+          int *p = (int*)pCur->pPtr;
           sqlite3_result_int(ctx, p[pCur->iRowid-1]);
           return SQLITE_OK;
         }
         case CARRAY_INT64: {
-          sqlite3_int64 *p = (sqlite3_int64*)pCur->iPtr;
+          sqlite3_int64 *p = (sqlite3_int64*)pCur->pPtr;
           sqlite3_result_int64(ctx, p[pCur->iRowid-1]);
           return SQLITE_OK;
         }
         case CARRAY_DOUBLE: {
-          double *p = (double*)pCur->iPtr;
+          double *p = (double*)pCur->pPtr;
           sqlite3_result_double(ctx, p[pCur->iRowid-1]);
           return SQLITE_OK;
         }
         case CARRAY_TEXT: {
-          const char **p = (const char**)pCur->iPtr;
+          const char **p = (const char**)pCur->pPtr;
           sqlite3_result_text(ctx, p[pCur->iRowid-1], -1, SQLITE_TRANSIENT);
           return SQLITE_OK;
         }
@@ -232,8 +232,8 @@ static int carrayFilter(
 ){
   carray_cursor *pCur = (carray_cursor *)pVtabCursor;
   if( idxNum ){
-    pCur->iPtr = sqlite3_value_int64(argv[0]);
-    pCur->iCnt = sqlite3_value_int64(argv[1]);
+    pCur->pPtr = sqlite3_value_pointer(argv[0]);
+    pCur->iCnt = pCur->pPtr ? sqlite3_value_int64(argv[1]) : 0;
     if( idxNum<3 ){
       pCur->eType = CARRAY_INT32;
     }else{
@@ -251,7 +251,7 @@ static int carrayFilter(
       }
     }
   }else{
-    pCur->iPtr = 0;
+    pCur->pPtr = 0;
     pCur->iCnt = 0;
   }
   pCur->iRowid = 1;
@@ -345,6 +345,34 @@ static sqlite3_module carrayModule = {
   0,                         /* xRename */
 };
 
+/*
+** For testing purpose in the TCL test harness, we need a method for
+** setting the pointer value.  The inttoptr(X) SQL function accomplishes
+** this.  Tcl script will bind an integer to X and the inttoptr() SQL
+** function will use sqlite3_result_pointer() to convert that integer into
+** a pointer.
+**
+** This is for testing on TCL only.
+*/
+#ifdef SQLITE_TEST
+static void inttoptrFunc(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  void *p;
+  sqlite3_int64 i64;
+  i64 = sqlite3_value_int64(argv[0]);
+  if( sizeof(i64)==sizeof(p) ){
+    memcpy(&p, &i64, sizeof(p));
+  }else{
+    int i32 = i64 & 0xffffffff;
+    memcpy(&p, &i32, sizeof(p));
+  }
+  sqlite3_result_pointer(context, p);
+}
+#endif /* SQLITE_TEST */
+
 #endif /* SQLITE_OMIT_VIRTUALTABLE */
 
 #ifdef _WIN32
@@ -359,6 +387,12 @@ int sqlite3_carray_init(
   SQLITE_EXTENSION_INIT2(pApi);
 #ifndef SQLITE_OMIT_VIRTUALTABLE
   rc = sqlite3_create_module(db, "carray", &carrayModule, 0);
-#endif
+#ifdef SQLITE_TEST
+  if( rc==SQLITE_OK ){
+    rc = sqlite3_create_function(db, "inttoptr", 1, SQLITE_UTF8, 0,
+                                 inttoptrFunc, 0, 0);
+  }
+#endif /* SQLITE_TEST */
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
   return rc;
 }
diff -up sqlite-src-3140200/src/sqlite.h.in.cve sqlite-src-3140200/src/sqlite.h.in
--- sqlite-src-3140200/src/sqlite.h.in.cve	2016-09-13 02:11:06.000000000 +0200
+++ sqlite-src-3140200/src/sqlite.h.in	2017-08-08 08:17:35.484017068 +0200
@@ -3742,6 +3742,15 @@ typedef struct sqlite3_context sqlite3_c
 ** [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()],
@@ -3775,6 +3784,7 @@ int sqlite3_bind_text16(sqlite3_stmt*, i
 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);
 
@@ -4539,6 +4549,11 @@ SQLITE_DEPRECATED int sqlite3_memory_ala
 ** 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
@@ -4566,6 +4581,7 @@ const unsigned char *sqlite3_value_text(
 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*);
 
@@ -4578,10 +4594,6 @@ int sqlite3_value_numeric_type(sqlite3_v
 ** 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*);
 
@@ -4859,6 +4871,14 @@ typedef void (*sqlite3_destructor_type)(
 ** [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.
@@ -4882,6 +4902,7 @@ void sqlite3_result_text16(sqlite3_conte
 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);
 
diff -up sqlite-src-3140200/src/vdbeapi.c.cve sqlite-src-3140200/src/vdbeapi.c
--- sqlite-src-3140200/src/vdbeapi.c.cve	2016-09-13 02:11:06.000000000 +0200
+++ sqlite-src-3140200/src/vdbeapi.c	2017-08-08 08:17:35.484017068 +0200
@@ -198,6 +198,14 @@ unsigned int sqlite3_value_subtype(sqlit
   Mem *pMem = (Mem*)pVal;
   return ((pMem->flags & MEM_Subtype) ? pMem->eSubtype : 0);
 }
+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);
 }
@@ -376,6 +384,12 @@ void sqlite3_result_null(sqlite3_context
   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){
   Mem *pOut = pCtx->pOut;
   assert( sqlite3_mutex_held(pOut->db->mutex) );
@@ -1359,6 +1373,16 @@ int sqlite3_bind_null(sqlite3_stmt *pStm
     sqlite3_mutex_leave(p->db->mutex);
   }
   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, 
diff -up sqlite-src-3140200/src/vdbeInt.h.cve sqlite-src-3140200/src/vdbeInt.h
--- sqlite-src-3140200/src/vdbeInt.h.cve	2016-09-13 02:11:06.000000000 +0200
+++ sqlite-src-3140200/src/vdbeInt.h	2017-08-08 08:17:35.484017068 +0200
@@ -190,6 +190,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 */
@@ -484,6 +485,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);
diff -up sqlite-src-3140200/src/vdbemem.c.cve sqlite-src-3140200/src/vdbemem.c
--- sqlite-src-3140200/src/vdbemem.c.cve	2016-09-13 02:11:06.000000000 +0200
+++ sqlite-src-3140200/src/vdbemem.c	2017-08-08 08:17:35.485017049 +0200
@@ -697,6 +697,17 @@ void sqlite3VdbeMemSetInt64(Mem *pMem, i
   }
 }
 
+/*
+** 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,
diff -up sqlite-src-3140200/test/tabfunc01.test.cve sqlite-src-3140200/test/tabfunc01.test
--- sqlite-src-3140200/test/tabfunc01.test.cve	2017-08-08 08:17:40.677920037 +0200
+++ sqlite-src-3140200/test/tabfunc01.test	2017-08-08 08:17:46.798805678 +0200
@@ -149,41 +149,41 @@ do_execsql_test tabfunc01-600 {
 do_test tabfunc01-700 {
   set PTR [intarray_addr 5 7 13 17 23]
   db eval {
-    SELECT b FROM t600, carray($PTR,5) WHERE a=value;
+    SELECT b FROM t600, carray(inttoptr($PTR),5) WHERE a=value;
   }
 } {(005) (007) (013) (017) (023)}
 do_test tabfunc01-701 {
   db eval {
-    SELECT b FROM t600 WHERE a IN carray($PTR,5,'int32');
+    SELECT b FROM t600 WHERE a IN carray(inttoptr($PTR),5,'int32');
   }
 } {(005) (007) (013) (017) (023)}
 do_test tabfunc01-702 {
   db eval {
-    SELECT b FROM t600 WHERE a IN carray($PTR,4,'int32');
+    SELECT b FROM t600 WHERE a IN carray(inttoptr($PTR),4,'int32');
   }
 } {(005) (007) (013) (017)}
 do_catchsql_test tabfunc01-710 {
-  SELECT b FROM t600 WHERE a IN carray($PTR,5,'int33');
+  SELECT b FROM t600 WHERE a IN carray(inttoptr($PTR),5,'int33');
 } {1 {unknown datatype: 'int33'}}
 
 do_test tabfunc01-720 {
   set PTR [int64array_addr 5 7 13 17 23]
   db eval {
-    SELECT b FROM t600, carray($PTR,5,'int64') WHERE a=value;
+    SELECT b FROM t600, carray(inttoptr($PTR),5,'int64') WHERE a=value;
   }
 } {(005) (007) (013) (017) (023)}
 
 do_test tabfunc01-730 {
   set PTR [doublearray_addr 5.0 7.0 13.0 17.0 23.0]
   db eval {
-    SELECT b FROM t600, carray($PTR,5,'double') WHERE a=value;
+    SELECT b FROM t600, carray(inttoptr($PTR),5,'double') WHERE a=value;
   }
 } {(005) (007) (013) (017) (023)}
 
 do_test tabfunc01-740 {
   set PTR [textarray_addr 5 7 13 17 23]
   db eval {
-    SELECT b FROM t600, carray($PTR,5,'char*') WHERE a=value;
+    SELECT b FROM t600, carray(inttoptr($PTR),5,'char*') WHERE a=value;
   }
 } {(005) (007) (013) (017) (023)}