/ Check-in [49cf31da]
Login

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

Overview
Comment:A demonstration of how FTS3 cursor pointers can be passed from the MATCH operator to the snippet() function securely and opaquely without having to use the sqlite3_result_pointer() and sqlite3_value_pointer() interfaces.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | pass-pointer-as-blob
Files: files | file ages | folders
SHA3-256:49cf31da82275dd36132d51aa13234b06ab6dd013bee7f88b15d1842096f4ca5
User & Date: drh 2017-07-27 14:04:57
Context
2017-07-27
14:04
A demonstration of how FTS3 cursor pointers can be passed from the MATCH operator to the snippet() function securely and opaquely without having to use the sqlite3_result_pointer() and sqlite3_value_pointer() interfaces. Closed-Leaf check-in: 49cf31da user: drh tags: pass-pointer-as-blob
2017-07-25
15:12
Release candidate 2 for 3.20.0. check-in: f39cb76b user: drh tags: branch-3.20
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/fts3/fts3.c.

  3349   3349   
  3350   3350     /* The column value supplied by SQLite must be in range. */
  3351   3351     assert( iCol>=0 && iCol<=p->nColumn+2 );
  3352   3352   
  3353   3353     switch( iCol-p->nColumn ){
  3354   3354       case 0:
  3355   3355         /* The special 'table-name' column */
  3356         -      sqlite3_result_pointer(pCtx, pCsr, "fts3cursor");
         3356  +      pCsr->iMagic = FTS3_CURSOR_MAGIC;
         3357  +      sqlite3_result_blob(pCtx, pCsr, 0, SQLITE_STATIC);
  3357   3358         break;
  3358   3359   
  3359   3360       case 1:
  3360   3361         /* The docid column */
  3361   3362         sqlite3_result_int64(pCtx, pCsr->iPrevId);
  3362   3363         break;
  3363   3364   
................................................................................
  3568   3569   static int fts3FunctionArg(
  3569   3570     sqlite3_context *pContext,      /* SQL function call context */
  3570   3571     const char *zFunc,              /* Function name */
  3571   3572     sqlite3_value *pVal,            /* argv[0] passed to function */
  3572   3573     Fts3Cursor **ppCsr              /* OUT: Store cursor handle here */
  3573   3574   ){
  3574   3575     int rc;
  3575         -  *ppCsr = (Fts3Cursor*)sqlite3_value_pointer(pVal, "fts3cursor");
  3576         -  if( (*ppCsr)!=0 ){
         3576  +  Fts3Cursor *pCur;
         3577  +  if( sqlite3_value_type(pVal)==SQLITE_BLOB
         3578  +   && sqlite3_value_bytes(pVal)==0
         3579  +   && (pCur = (Fts3Cursor*)sqlite3_value_blob(pVal))!=0
         3580  +   && pCur->iMagic==FTS3_CURSOR_MAGIC
         3581  +  ){
         3582  +    *ppCsr = pCur;
  3577   3583       rc = SQLITE_OK;
  3578   3584     }else{
  3579   3585       char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc);
  3580   3586       sqlite3_result_error(pContext, zErr, -1);
  3581   3587       sqlite3_free(zErr);
  3582   3588       rc = SQLITE_ERROR;
  3583   3589     }

Changes to ext/fts3/fts3Int.h.

   286    286   #ifdef SQLITE_TEST
   287    287     /* True to disable the incremental doclist optimization. This is controled
   288    288     ** by special insert command 'test-no-incr-doclist'.  */
   289    289     int bNoIncrDoclist;
   290    290   #endif
   291    291   };
   292    292   
          293  +/*
          294  +** Magic number for cursors
          295  +*/
          296  +#define FTS3_CURSOR_MAGIC  0x2f621809
          297  +
   293    298   /*
   294    299   ** When the core wants to read from the virtual table, it creates a
   295    300   ** virtual table cursor (an instance of the following structure) using
   296    301   ** the xOpen method. Cursors are destroyed using the xClose method.
   297    302   */
   298    303   struct Fts3Cursor {
   299    304     sqlite3_vtab_cursor base;       /* Base class used by SQLite core */
          305  +  u32 iMagic;                     /* Magic number to prove identity */
   300    306     i16 eSearch;                    /* Search strategy (see below) */
   301    307     u8 isEof;                       /* True if at End Of Results */
   302    308     u8 isRequireSeek;               /* True if must seek pStmt to %_content row */
   303    309     u8 bSeekStmt;                   /* True if pStmt is a seek */
   304    310     sqlite3_stmt *pStmt;            /* Prepared statement in use by the cursor */
   305    311     Fts3Expr *pExpr;                /* Parsed MATCH query string */
   306    312     int iLangid;                    /* Language being queried for */

Changes to src/vdbeapi.c.

   171    171     Mem *p = (Mem*)pVal;
   172    172     if( p->flags & (MEM_Blob|MEM_Str) ){
   173    173       if( ExpandBlob(p)!=SQLITE_OK ){
   174    174         assert( p->flags==MEM_Null && p->z==0 );
   175    175         return 0;
   176    176       }
   177    177       p->flags |= MEM_Blob;
   178         -    return p->n ? p->z : 0;
          178  +    return p->z; // p->n ? p->z : 0;
   179    179     }else{
   180    180       return sqlite3_value_text(pVal);
   181    181     }
   182    182   }
   183    183   int sqlite3_value_bytes(sqlite3_value *pVal){
   184    184     return sqlite3ValueBytes(pVal, SQLITE_UTF8);
   185    185   }