/ Check-in [4cb67252]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment: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.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | branch-3.9
Files: files | file ages | folders
SHA3-256: 4cb67252d39fc537601f75532ec8271994aed8bae4d20ba48a3262b52ed004c0
User & Date: dan 2018-12-19 16:03:56
Context
2019-09-03
17:39
Disable the undocumented rtreenode() SQL function that is only used for testing, except when doing a build that is specifically intended for testing. check-in: 7b4583f9 user: drh tags: branch-3.9
2018-12-19
16:03
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. check-in: 4cb67252 user: dan tags: branch-3.9
01:57
Add extra defenses against strategically corrupt databases to fts3/4. check-in: 882ef4e3 user: drh tags: branch-3.9
2017-07-13
18:09
Add new 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. check-in: 72de49f2 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Show Whitespace Changes Patch

Changes to ext/fts3/fts3.c.

  3313   3313   
  3314   3314     if( iCol==p->nColumn+1 ){
  3315   3315       /* This call is a request for the "docid" column. Since "docid" is an 
  3316   3316       ** alias for "rowid", use the xRowid() method to obtain the value.
  3317   3317       */
  3318   3318       sqlite3_result_int64(pCtx, pCsr->iPrevId);
  3319   3319     }else if( iCol==p->nColumn ){
  3320         -    /* The extra column whose name is the same as the table.
  3321         -    ** Return a blob which is a pointer to the cursor.  */
  3322         -    sqlite3_result_blob(pCtx, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT);
         3320  +    /* The extra column whose name is the same as the table. */
         3321  +    sqlite3_result_pointer(pCtx, pCsr);
  3323   3322     }else if( iCol==p->nColumn+2 && pCsr->pExpr ){
  3324   3323       sqlite3_result_int64(pCtx, pCsr->iLangid);
  3325   3324     }else{
  3326   3325       /* The requested column is either a user column (one that contains 
  3327   3326       ** indexed data), or the language-id column.  */
  3328   3327       rc = fts3CursorSeek(0, pCsr);
  3329   3328   
................................................................................
  3527   3526   */
  3528   3527   static int fts3FunctionArg(
  3529   3528     sqlite3_context *pContext,      /* SQL function call context */
  3530   3529     const char *zFunc,              /* Function name */
  3531   3530     sqlite3_value *pVal,            /* argv[0] passed to function */
  3532   3531     Fts3Cursor **ppCsr              /* OUT: Store cursor handle here */
  3533   3532   ){
  3534         -  Fts3Cursor *pRet;
  3535         -  if( sqlite3_value_type(pVal)!=SQLITE_BLOB 
  3536         -   || sqlite3_value_bytes(pVal)!=sizeof(Fts3Cursor *)
  3537         -  ){
         3533  +  int rc;
         3534  +  *ppCsr = (Fts3Cursor*)sqlite3_value_pointer(pVal);
         3535  +  if( (*ppCsr)!=0 ){
         3536  +    rc = SQLITE_OK;
         3537  +  }else{
  3538   3538       char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc);
  3539   3539       sqlite3_result_error(pContext, zErr, -1);
  3540   3540       sqlite3_free(zErr);
  3541         -    return SQLITE_ERROR;
         3541  +    rc = SQLITE_ERROR;
  3542   3542     }
  3543         -  memcpy(&pRet, sqlite3_value_blob(pVal), sizeof(Fts3Cursor *));
  3544         -  *ppCsr = pRet;
  3545         -  return SQLITE_OK;
         3543  +  return rc;
  3546   3544   }
  3547   3545   
  3548   3546   /*
  3549   3547   ** Implementation of the snippet() function for FTS3
  3550   3548   */
  3551   3549   static void fts3SnippetFunc(
  3552   3550     sqlite3_context *pContext,      /* SQLite function call context */

Changes to src/sqlite.h.in.

  3527   3527   ** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that
  3528   3528   ** is filled with zeroes.  ^A zeroblob uses a fixed amount of memory
  3529   3529   ** (just an integer to hold its size) while it is being processed.
  3530   3530   ** Zeroblobs are intended to serve as placeholders for BLOBs whose
  3531   3531   ** content is later written using
  3532   3532   ** [sqlite3_blob_open | incremental BLOB I/O] routines.
  3533   3533   ** ^A negative value for the zeroblob results in a zero-length BLOB.
         3534  +**
         3535  +** ^The sqlite3_bind_pointer(S,I,P) routine causes the I-th parameter in
         3536  +** [prepared statement] S to have an SQL value of NULL, but to also be
         3537  +** associated with the pointer P.
         3538  +** ^The sqlite3_bind_pointer() routine can be used to pass
         3539  +** host-language pointers into [application-defined SQL functions].
         3540  +** ^A parameter that is initialized using [sqlite3_bind_pointer()] appears
         3541  +** to be an ordinary SQL NULL value to everything other than
         3542  +** [sqlite3_value_pointer()].
  3534   3543   **
  3535   3544   ** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer
  3536   3545   ** for the [prepared statement] or with a prepared statement for which
  3537   3546   ** [sqlite3_step()] has been called more recently than [sqlite3_reset()],
  3538   3547   ** then the call will return [SQLITE_MISUSE].  If any sqlite3_bind_()
  3539   3548   ** routine is passed a [prepared statement] that has been finalized, the
  3540   3549   ** result is undefined and probably harmful.
................................................................................
  3561   3570   int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
  3562   3571   int sqlite3_bind_null(sqlite3_stmt*, int);
  3563   3572   int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
  3564   3573   int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
  3565   3574   int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64,
  3566   3575                            void(*)(void*), unsigned char encoding);
  3567   3576   int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
         3577  +int sqlite3_bind_pointer(sqlite3_stmt*, int, void*);
  3568   3578   int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
  3569   3579   int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64);
  3570   3580   
  3571   3581   /*
  3572   3582   ** CAPI3REF: Number Of SQL Parameters
  3573   3583   ** METHOD: sqlite3_stmt
  3574   3584   **
................................................................................
  4324   4334   ** except that these routines take a single [protected sqlite3_value] object
  4325   4335   ** pointer instead of a [sqlite3_stmt*] pointer and an integer column number.
  4326   4336   **
  4327   4337   ** ^The sqlite3_value_text16() interface extracts a UTF-16 string
  4328   4338   ** in the native byte-order of the host machine.  ^The
  4329   4339   ** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces
  4330   4340   ** extract UTF-16 strings as big-endian and little-endian respectively.
         4341  +**
         4342  +** ^If [sqlite3_value] object V was initialized 
         4343  +** using [sqlite3_bind_pointer(S,I,P)] or [sqlite3_result_pointer(C,P)], then
         4344  +** sqlite3_value_pointer(V) will return the pointer P.  Otherwise,
         4345  +** sqlite3_value_pointer(V) returns a NULL.
  4331   4346   **
  4332   4347   ** ^(The sqlite3_value_numeric_type() interface attempts to apply
  4333   4348   ** numeric affinity to the value.  This means that an attempt is
  4334   4349   ** made to convert the value to an integer or floating point.  If
  4335   4350   ** such a conversion is possible without loss of information (in other
  4336   4351   ** words, if the value is a string that looks like a number)
  4337   4352   ** then the conversion is performed.  Otherwise no conversion occurs.
................................................................................
  4352   4367   double sqlite3_value_double(sqlite3_value*);
  4353   4368   int sqlite3_value_int(sqlite3_value*);
  4354   4369   sqlite3_int64 sqlite3_value_int64(sqlite3_value*);
  4355   4370   const unsigned char *sqlite3_value_text(sqlite3_value*);
  4356   4371   const void *sqlite3_value_text16(sqlite3_value*);
  4357   4372   const void *sqlite3_value_text16le(sqlite3_value*);
  4358   4373   const void *sqlite3_value_text16be(sqlite3_value*);
         4374  +void *sqlite3_value_pointer(sqlite3_value*);
  4359   4375   int sqlite3_value_type(sqlite3_value*);
  4360   4376   int sqlite3_value_numeric_type(sqlite3_value*);
  4361   4377   
  4362   4378   /*
  4363   4379   ** CAPI3REF: Finding The Subtype Of SQL Values
  4364   4380   ** METHOD: sqlite3_value
  4365   4381   **
  4366   4382   ** The sqlite3_value_subtype(V) function returns the subtype for
  4367   4383   ** an [application-defined SQL function] argument V.  The subtype
  4368   4384   ** information can be used to pass a limited amount of context from
  4369   4385   ** one SQL function to another.  Use the [sqlite3_result_subtype()]
  4370   4386   ** routine to set the subtype for the return value of an SQL function.
  4371         -**
  4372         -** SQLite makes no use of subtype itself.  It merely passes the subtype
  4373         -** from the result of one [application-defined SQL function] into the
  4374         -** input of another.
  4375   4387   */
  4376   4388   unsigned int sqlite3_value_subtype(sqlite3_value*);
  4377   4389   
  4378   4390   /*
  4379   4391   ** CAPI3REF: Copy And Free SQL Values
  4380   4392   ** METHOD: sqlite3_value
  4381   4393   **
................................................................................
  4643   4655   ** [unprotected sqlite3_value] object specified by the 2nd parameter.  ^The
  4644   4656   ** sqlite3_result_value() interface makes a copy of the [sqlite3_value]
  4645   4657   ** so that the [sqlite3_value] specified in the parameter may change or
  4646   4658   ** be deallocated after sqlite3_result_value() returns without harm.
  4647   4659   ** ^A [protected sqlite3_value] object may always be used where an
  4648   4660   ** [unprotected sqlite3_value] object is required, so either
  4649   4661   ** kind of [sqlite3_value] object can be used with this interface.
         4662  +**
         4663  +** ^The sqlite3_result_pointer(C,P) interface sets the result to an
         4664  +** SQL NULL value, just like [sqlite3_result_null(C)], except that it
         4665  +** also associates the host-language pointer P with that NULL value such
         4666  +** that the pointer can be retrieved within an
         4667  +** [application-defined SQL function] using [sqlite3_value_pointer()].
         4668  +** This mechanism can be used to pass non-SQL values between
         4669  +** application-defined functions.
  4650   4670   **
  4651   4671   ** If these routines are called from within the different thread
  4652   4672   ** than the one containing the application-defined function that received
  4653   4673   ** the [sqlite3_context] pointer, the results are undefined.
  4654   4674   */
  4655   4675   void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
  4656   4676   void sqlite3_result_blob64(sqlite3_context*,const void*,
................................................................................
  4667   4687   void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
  4668   4688   void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64,
  4669   4689                              void(*)(void*), unsigned char encoding);
  4670   4690   void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
  4671   4691   void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
  4672   4692   void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
  4673   4693   void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
         4694  +void sqlite3_result_pointer(sqlite3_context*, void*);
  4674   4695   void sqlite3_result_zeroblob(sqlite3_context*, int n);
  4675   4696   int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n);
  4676   4697   
  4677   4698   
  4678   4699   /*
  4679   4700   ** CAPI3REF: Setting The Subtype Of An SQL Function
  4680   4701   ** METHOD: sqlite3_context

Changes to src/sqlite3ext.h.

   510    510   #define sqlite3_value_dup              sqlite3_api->value_dup
   511    511   #define sqlite3_value_free             sqlite3_api->value_free
   512    512   #define sqlite3_result_zeroblob64      sqlite3_api->result_zeroblob64
   513    513   #define sqlite3_bind_zeroblob64        sqlite3_api->bind_zeroblob64
   514    514   /* Version 3.9.0 and later */
   515    515   #define sqlite3_value_subtype          sqlite3_api->value_subtype
   516    516   #define sqlite3_result_subtype         sqlite3_api->result_subtype
          517  +#define sqlite3_bind_pointer           sqlite3_api->bind_pointer
          518  +#define sqlite3_result_pointer         sqlite3_api->result_pointer
          519  +#define sqlite3_value_pointer          sqlite3_api->value_pointer
   517    520   #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
   518    521   
   519    522   #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
   520    523     /* This case when the file really is being compiled as a loadable 
   521    524     ** extension */
   522    525   # define SQLITE_EXTENSION_INIT1     const sqlite3_api_routines *sqlite3_api=0;
   523    526   # define SQLITE_EXTENSION_INIT2(v)  sqlite3_api=v;

Changes to src/vdbeInt.h.

   165    165   ** integer etc.) of the same value.
   166    166   */
   167    167   struct Mem {
   168    168     union MemValue {
   169    169       double r;           /* Real value used when MEM_Real is set in flags */
   170    170       i64 i;              /* Integer value used when MEM_Int is set in flags */
   171    171       int nZero;          /* Used when bit MEM_Zero is set in flags */
          172  +    void *pPtr;         /* Pointer when flags=MEM_NULL and eSubtype='p' */
   172    173       FuncDef *pDef;      /* Used only when flags==MEM_Agg */
   173    174       RowSet *pRowSet;    /* Used only when flags==MEM_RowSet */
   174    175       VdbeFrame *pFrame;  /* Used when flags==MEM_Frame */
   175    176     } u;
   176    177     u16 flags;          /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
   177    178     u8  enc;            /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
   178    179     u8  eSubtype;       /* Subtype for this value */
................................................................................
   214    215   #define MEM_Real      0x0008   /* Value is a real number */
   215    216   #define MEM_Blob      0x0010   /* Value is a BLOB */
   216    217   #define MEM_AffMask   0x001f   /* Mask of affinity bits */
   217    218   #define MEM_RowSet    0x0020   /* Value is a RowSet object */
   218    219   #define MEM_Frame     0x0040   /* Value is a VdbeFrame object */
   219    220   #define MEM_Undefined 0x0080   /* Value is undefined */
   220    221   #define MEM_Cleared   0x0100   /* NULL set by OP_Null, not from data */
   221         -#define MEM_TypeMask  0x01ff   /* Mask of type bits */
          222  +#define MEM_TypeMask  0x81ff   /* Mask of type bits */
   222    223   
   223    224   
   224    225   /* Whenever Mem contains a valid string or blob representation, one of
   225    226   ** the following flags must be set to determine the memory management
   226    227   ** policy for Mem.z.  The MEM_Term flag tells us whether or not the
   227    228   ** string is \000 or \u0000 terminated
   228    229   */
   229    230   #define MEM_Term      0x0200   /* String rep is nul terminated */
   230    231   #define MEM_Dyn       0x0400   /* Need to call Mem.xDel() on Mem.z */
   231    232   #define MEM_Static    0x0800   /* Mem.z points to a static string */
   232    233   #define MEM_Ephem     0x1000   /* Mem.z points to an ephemeral string */
   233    234   #define MEM_Agg       0x2000   /* Mem.z points to an agg function context */
   234    235   #define MEM_Zero      0x4000   /* Mem.i contains count of 0s appended to blob */
          236  +#define MEM_Subtype   0x8000 
   235    237   #ifdef SQLITE_OMIT_INCRBLOB
   236    238     #undef MEM_Zero
   237    239     #define MEM_Zero 0x0000
   238    240   #endif
   239    241   
   240    242   /*
   241    243   ** Clear any existing type flags from a Mem and replace them with f
................................................................................
   432    434   int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*));
   433    435   void sqlite3VdbeMemSetInt64(Mem*, i64);
   434    436   #ifdef SQLITE_OMIT_FLOATING_POINT
   435    437   # define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64
   436    438   #else
   437    439     void sqlite3VdbeMemSetDouble(Mem*, double);
   438    440   #endif
          441  +void sqlite3VdbeMemSetPointer(Mem*, void*);
   439    442   void sqlite3VdbeMemInit(Mem*,sqlite3*,u16);
   440    443   void sqlite3VdbeMemSetNull(Mem*);
   441    444   void sqlite3VdbeMemSetZeroBlob(Mem*,int);
   442    445   void sqlite3VdbeMemSetRowSet(Mem*);
   443    446   int sqlite3VdbeMemMakeWriteable(Mem*);
   444    447   int sqlite3VdbeMemStringify(Mem*, u8, u8);
   445    448   i64 sqlite3VdbeIntValue(Mem*);

Changes to src/vdbeapi.c.

   185    185     return (int)sqlite3VdbeIntValue((Mem*)pVal);
   186    186   }
   187    187   sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){
   188    188     return sqlite3VdbeIntValue((Mem*)pVal);
   189    189   }
   190    190   unsigned int sqlite3_value_subtype(sqlite3_value *pVal){
   191    191     return ((Mem*)pVal)->eSubtype;
          192  +}
          193  +void *sqlite3_value_pointer(sqlite3_value *pVal){
          194  +  Mem *p = (Mem*)pVal;
          195  +  if( (p->flags & MEM_TypeMask)==(MEM_Null|MEM_Subtype) && p->eSubtype=='p' ){
          196  +    return p->u.pPtr;
          197  +  }else{
          198  +    return 0;
          199  +  }
   192    200   }
   193    201   const unsigned char *sqlite3_value_text(sqlite3_value *pVal){
   194    202     return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8);
   195    203   }
   196    204   #ifndef SQLITE_OMIT_UTF16
   197    205   const void *sqlite3_value_text16(sqlite3_value* pVal){
   198    206     return sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
................................................................................
   363    371   void sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){
   364    372     assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
   365    373     sqlite3VdbeMemSetInt64(pCtx->pOut, iVal);
   366    374   }
   367    375   void sqlite3_result_null(sqlite3_context *pCtx){
   368    376     assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
   369    377     sqlite3VdbeMemSetNull(pCtx->pOut);
          378  +}
          379  +void sqlite3_result_pointer(sqlite3_context *pCtx, void *pPtr){
          380  +  Mem *pOut = pCtx->pOut;
          381  +  assert( sqlite3_mutex_held(pOut->db->mutex) );
          382  +  sqlite3VdbeMemSetNull(pOut);
          383  +  sqlite3VdbeMemSetPointer(pOut, pPtr);
   370    384   }
   371    385   void sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){
   372    386     assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
   373    387     pCtx->pOut->eSubtype = eSubtype & 0xff;
   374    388   }
   375    389   void sqlite3_result_text(
   376    390     sqlite3_context *pCtx, 
................................................................................
  1341   1355     int rc;
  1342   1356     Vdbe *p = (Vdbe*)pStmt;
  1343   1357     rc = vdbeUnbind(p, i);
  1344   1358     if( rc==SQLITE_OK ){
  1345   1359       sqlite3_mutex_leave(p->db->mutex);
  1346   1360     }
  1347   1361     return rc;
         1362  +}
         1363  +int sqlite3_bind_pointer(sqlite3_stmt *pStmt, int i, void *pPtr){
         1364  +  int rc;
         1365  +  Vdbe *p = (Vdbe*)pStmt;
         1366  +  rc = vdbeUnbind(p, i);
         1367  +  if( rc==SQLITE_OK ){
         1368  +    sqlite3VdbeMemSetPointer(&p->aVar[i-1], pPtr);
         1369  +    sqlite3_mutex_leave(p->db->mutex);
         1370  +  }
         1371  +  return rc;
  1348   1372   }
  1349   1373   int sqlite3_bind_text( 
  1350   1374     sqlite3_stmt *pStmt, 
  1351   1375     int i, 
  1352   1376     const char *zData, 
  1353   1377     int nData, 
  1354   1378     void (*xDel)(void*)

Changes to src/vdbemem.c.

   691    691     if( VdbeMemDynamic(pMem) ){
   692    692       vdbeReleaseAndSetInt64(pMem, val);
   693    693     }else{
   694    694       pMem->u.i = val;
   695    695       pMem->flags = MEM_Int;
   696    696     }
   697    697   }
          698  +
          699  +/*
          700  +** Set the value stored in *pMem should already be a NULL.
          701  +** Also store a pointer to go with it.
          702  +*/
          703  +void sqlite3VdbeMemSetPointer(Mem *pMem, void *pPtr){
          704  +  assert( pMem->flags==MEM_Null );
          705  +  pMem->flags = MEM_Null|MEM_Subtype;
          706  +  pMem->u.pPtr = pPtr;
          707  +  pMem->eSubtype = 'p';
          708  +}
   698    709   
   699    710   #ifndef SQLITE_OMIT_FLOATING_POINT
   700    711   /*
   701    712   ** Delete any previous value and set the value stored in *pMem to val,
   702    713   ** manifest type REAL.
   703    714   */
   704    715   void sqlite3VdbeMemSetDouble(Mem *pMem, double val){

Changes to test/fts3snippet.test.

   550    550     set x35 [string trim [string repeat "x " 35]]
   551    551     execsql "INSERT INTO t4 VALUES('$x35 E $x35 F $x35 G $x35');"
   552    552     llength [db one {
   553    553       SELECT snippet(t4, '', '', '', 0, 64) FROM t4 WHERE t4 MATCH 'E'
   554    554     }]
   555    555   } {64}
   556    556   
   557         -
          557  +do_execsql_test 4.3.1 {
          558  +  SELECT quote(t4) FROM t4;
          559  +} {NULL NULL}
   558    560   
   559    561   
   560    562   set sqlite_fts3_enable_parentheses 0
   561    563   finish_test
   562    564