/ Check-in [2a5f813b]
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:In extensions rtree, fts3 and fts5, ensure that when dynamic buffers are bound to persistent SQL statements using SQLITE_STATIC, the binding is replaced with an SQL NULL before the buffer is freed. Otherwise, a user may obtain a pointer to the persistent statement using sqlite3_next_stmt() and attempt to access the freed buffer using sqlite3_expanded_sql() or similar.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 2a5f813bc61f9e780f2ccbda425611f65ad523b6d486a1e5e2b9d5e9f1d260a2
User & Date: dan 2018-02-07 18:02:50
Context
2018-02-07
18:45
Fix typo in comment. Skip tests added by check-in [4761db83b6] when running on Windows. check-in: 468a389c user: mistachkin tags: trunk
18:02
In extensions rtree, fts3 and fts5, ensure that when dynamic buffers are bound to persistent SQL statements using SQLITE_STATIC, the binding is replaced with an SQL NULL before the buffer is freed. Otherwise, a user may obtain a pointer to the persistent statement using sqlite3_next_stmt() and attempt to access the freed buffer using sqlite3_expanded_sql() or similar. check-in: 2a5f813b user: dan tags: trunk
16:14
When the final connection disconnects from a wal mode database, check that the database file has not been moved or unlinked before deleting the wal and shm files. check-in: 4761db83 user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Show Whitespace Changes Patch

Changes to ext/fts3/fts3_write.c.

  1904   1904     sqlite3_stmt *pStmt;
  1905   1905     int rc = fts3SqlStmt(p, SQL_INSERT_SEGMENTS, &pStmt, 0);
  1906   1906     if( rc==SQLITE_OK ){
  1907   1907       sqlite3_bind_int64(pStmt, 1, iBlock);
  1908   1908       sqlite3_bind_blob(pStmt, 2, z, n, SQLITE_STATIC);
  1909   1909       sqlite3_step(pStmt);
  1910   1910       rc = sqlite3_reset(pStmt);
         1911  +    sqlite3_bind_null(pStmt, 2);
  1911   1912     }
  1912   1913     return rc;
  1913   1914   }
  1914   1915   
  1915   1916   /*
  1916   1917   ** Find the largest relative level number in the table. If successful, set
  1917   1918   ** *pnMax to this value and return SQLITE_OK. Otherwise, if an error occurs,
................................................................................
  1960   1961         char *zEnd = sqlite3_mprintf("%lld %lld", iEndBlock, nLeafData);
  1961   1962         if( !zEnd ) return SQLITE_NOMEM;
  1962   1963         sqlite3_bind_text(pStmt, 5, zEnd, -1, sqlite3_free);
  1963   1964       }
  1964   1965       sqlite3_bind_blob(pStmt, 6, zRoot, nRoot, SQLITE_STATIC);
  1965   1966       sqlite3_step(pStmt);
  1966   1967       rc = sqlite3_reset(pStmt);
         1968  +    sqlite3_bind_null(pStmt, 6);
  1967   1969     }
  1968   1970     return rc;
  1969   1971   }
  1970   1972   
  1971   1973   /*
  1972   1974   ** Return the size of the common prefix (if any) shared by zPrev and
  1973   1975   ** zNext, in bytes. For example, 
................................................................................
  3439   3441       *pRC = rc;
  3440   3442       return;
  3441   3443     }
  3442   3444     sqlite3_bind_int(pStmt, 1, FTS_STAT_DOCTOTAL);
  3443   3445     sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, SQLITE_STATIC);
  3444   3446     sqlite3_step(pStmt);
  3445   3447     *pRC = sqlite3_reset(pStmt);
         3448  +  sqlite3_bind_null(pStmt, 2);
  3446   3449     sqlite3_free(a);
  3447   3450   }
  3448   3451   
  3449   3452   /*
  3450   3453   ** Merge the entire database so that there is one segment for each 
  3451   3454   ** iIndex/iLangid combination.
  3452   3455   */
................................................................................
  4627   4630       if( rc==SQLITE_OK ){
  4628   4631         sqlite3_bind_int64(pChomp, 1, iNewStart);
  4629   4632         sqlite3_bind_blob(pChomp, 2, root.a, root.n, SQLITE_STATIC);
  4630   4633         sqlite3_bind_int64(pChomp, 3, iAbsLevel);
  4631   4634         sqlite3_bind_int(pChomp, 4, iIdx);
  4632   4635         sqlite3_step(pChomp);
  4633   4636         rc = sqlite3_reset(pChomp);
         4637  +      sqlite3_bind_null(pChomp, 2);
  4634   4638       }
  4635   4639     }
  4636   4640   
  4637   4641     sqlite3_free(root.a);
  4638   4642     sqlite3_free(block.a);
  4639   4643     return rc;
  4640   4644   }
................................................................................
  4706   4710   
  4707   4711     rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pReplace, 0);
  4708   4712     if( rc==SQLITE_OK ){
  4709   4713       sqlite3_bind_int(pReplace, 1, FTS_STAT_INCRMERGEHINT);
  4710   4714       sqlite3_bind_blob(pReplace, 2, pHint->a, pHint->n, SQLITE_STATIC);
  4711   4715       sqlite3_step(pReplace);
  4712   4716       rc = sqlite3_reset(pReplace);
         4717  +    sqlite3_bind_null(pReplace, 2);
  4713   4718     }
  4714   4719   
  4715   4720     return rc;
  4716   4721   }
  4717   4722   
  4718   4723   /*
  4719   4724   ** Load an incr-merge hint from the database. The incr-merge hint, if one 

Changes to ext/fts5/fts5_index.c.

   754    754       if( p->rc ) return;
   755    755     }
   756    756   
   757    757     sqlite3_bind_int64(p->pWriter, 1, iRowid);
   758    758     sqlite3_bind_blob(p->pWriter, 2, pData, nData, SQLITE_STATIC);
   759    759     sqlite3_step(p->pWriter);
   760    760     p->rc = sqlite3_reset(p->pWriter);
          761  +  sqlite3_bind_null(p->pWriter, 2);
   761    762   }
   762    763   
   763    764   /*
   764    765   ** Execute the following SQL:
   765    766   **
   766    767   **     DELETE FROM %_data WHERE id BETWEEN $iFirst AND $iLast
   767    768   */
................................................................................
  2382   2383     sqlite3_bind_blob(pIdxSelect, 2, pTerm, nTerm, SQLITE_STATIC);
  2383   2384     if( SQLITE_ROW==sqlite3_step(pIdxSelect) ){
  2384   2385       i64 val = sqlite3_column_int(pIdxSelect, 0);
  2385   2386       iPg = (int)(val>>1);
  2386   2387       bDlidx = (val & 0x0001);
  2387   2388     }
  2388   2389     p->rc = sqlite3_reset(pIdxSelect);
         2390  +  sqlite3_bind_null(pIdxSelect, 2);
  2389   2391   
  2390   2392     if( iPg<pSeg->pgnoFirst ){
  2391   2393       iPg = pSeg->pgnoFirst;
  2392   2394       bDlidx = 0;
  2393   2395     }
  2394   2396   
  2395   2397     pIter->iLeafPgno = iPg - 1;
................................................................................
  3594   3596           sqlite3_stmt *pIdxSelect = fts5IdxSelectStmt(p);
  3595   3597           if( p->rc==SQLITE_OK ){
  3596   3598             u8 aBlob[2] = {0xff, 0xff};
  3597   3599             sqlite3_bind_int(pIdxSelect, 1, iSegid);
  3598   3600             sqlite3_bind_blob(pIdxSelect, 2, aBlob, 2, SQLITE_STATIC);
  3599   3601             assert( sqlite3_step(pIdxSelect)!=SQLITE_ROW );
  3600   3602             p->rc = sqlite3_reset(pIdxSelect);
         3603  +          sqlite3_bind_null(pIdxSelect, 2);
  3601   3604           }
  3602   3605         }
  3603   3606   #endif
  3604   3607       }
  3605   3608     }
  3606   3609   
  3607   3610     return iSegid;
................................................................................
  3720   3723       const char *z = (pWriter->btterm.n>0?(const char*)pWriter->btterm.p:"");
  3721   3724       /* The following was already done in fts5WriteInit(): */
  3722   3725       /* sqlite3_bind_int(p->pIdxWriter, 1, pWriter->iSegid); */
  3723   3726       sqlite3_bind_blob(p->pIdxWriter, 2, z, pWriter->btterm.n, SQLITE_STATIC);
  3724   3727       sqlite3_bind_int64(p->pIdxWriter, 3, bFlag + ((i64)pWriter->iBtPage<<1));
  3725   3728       sqlite3_step(p->pIdxWriter);
  3726   3729       p->rc = sqlite3_reset(p->pIdxWriter);
         3730  +    sqlite3_bind_null(p->pIdxWriter, 2);
  3727   3731     }
  3728   3732     pWriter->iBtPage = 0;
  3729   3733   }
  3730   3734   
  3731   3735   /*
  3732   3736   ** This is called once for each leaf page except the first that contains
  3733   3737   ** at least one term. Argument (nTerm/pTerm) is the split-key - a term that

Changes to ext/fts5/fts5_storage.c.

   454    454       sqlite3_stmt *pReplace = 0;
   455    455       rc = fts5StorageGetStmt(p, FTS5_STMT_REPLACE_DOCSIZE, &pReplace, 0);
   456    456       if( rc==SQLITE_OK ){
   457    457         sqlite3_bind_int64(pReplace, 1, iRowid);
   458    458         sqlite3_bind_blob(pReplace, 2, pBuf->p, pBuf->n, SQLITE_STATIC);
   459    459         sqlite3_step(pReplace);
   460    460         rc = sqlite3_reset(pReplace);
          461  +      sqlite3_bind_null(pReplace, 2);
   461    462       }
   462    463     }
   463    464     return rc;
   464    465   }
   465    466   
   466    467   /*
   467    468   ** Load the contents of the "averages" record from disk into the 
................................................................................
  1114   1115       if( pVal ){
  1115   1116         sqlite3_bind_value(pReplace, 2, pVal);
  1116   1117       }else{
  1117   1118         sqlite3_bind_int(pReplace, 2, iVal);
  1118   1119       }
  1119   1120       sqlite3_step(pReplace);
  1120   1121       rc = sqlite3_reset(pReplace);
         1122  +    sqlite3_bind_null(pReplace, 1);
  1121   1123     }
  1122   1124     if( rc==SQLITE_OK && pVal ){
  1123   1125       int iNew = p->pConfig->iCookie + 1;
  1124   1126       rc = sqlite3Fts5IndexSetCookie(p->pIndex, iNew);
  1125   1127       if( rc==SQLITE_OK ){
  1126   1128         p->pConfig->iCookie = iNew;
  1127   1129       }
  1128   1130     }
  1129   1131     return rc;
  1130   1132   }

Changes to ext/fts5/test/fts5aa.test.

   589    589   
   590    590   do_execsql_test 22.1 {
   591    591     SELECT rowid FROM t9('a*')
   592    592   } {1}
   593    593   
   594    594   }
   595    595   
   596         -
          596  +expand_all_sql db
   597    597   finish_test

Changes to ext/rtree/rtree.c.

   781    781       }else{
   782    782         sqlite3_bind_null(p, 1);
   783    783       }
   784    784       sqlite3_bind_blob(p, 2, pNode->zData, pRtree->iNodeSize, SQLITE_STATIC);
   785    785       sqlite3_step(p);
   786    786       pNode->isDirty = 0;
   787    787       rc = sqlite3_reset(p);
          788  +    sqlite3_bind_null(p, 2);
   788    789       if( pNode->iNode==0 && rc==SQLITE_OK ){
   789    790         pNode->iNode = sqlite3_last_insert_rowid(pRtree->db);
   790    791         nodeHashInsert(pRtree, pNode);
   791    792       }
   792    793     }
   793    794     return rc;
   794    795   }

Changes to ext/rtree/rtree1.test.

   605    605     INSERT INTO rt VALUES(1,2,3,4,5);
   606    606   }
   607    607   do_execsql_test 15.2 {
   608    608     DROP TABLE t13;
   609    609     COMMIT;
   610    610   }
   611    611   
          612  +expand_all_sql db
   612    613   finish_test

Changes to ext/rtree/rtree4.test.

   246    246         list $where [db eval "SELECT id FROM rx $where ORDER BY id"]
   247    247       } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]]
   248    248     }
   249    249   
   250    250     do_rtree_integrity_test rtree4-$nDim.3 rx
   251    251   }
   252    252   
          253  +expand_all_sql db
   253    254   finish_test

Changes to ext/rtree/rtree5.test.

    75     75       SELECT * FROM t1 WHERE 
    76     76           x1=2147483643 AND x2=2147483647 AND 
    77     77           y1=-2147483648 AND y2=-2147483643
    78     78     }
    79     79   } {2 2147483643 2147483647 -2147483648 -2147483643}
    80     80   do_rtree_integrity_test rtree5-1.14 t1
    81     81   
           82  +expand_all_sql db
    82     83   finish_test

Changes to ext/rtree/rtree6.test.

   154    154       x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND 
   155    155       x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND 
   156    156       x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND 
   157    157       x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND 
   158    158       x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>1.1
   159    159   } {}
   160    160   
   161         -
          161  +expand_all_sql db
   162    162   finish_test

Changes to ext/rtree/rtreeG.test.

    55     55   do_execsql_test rtreeG-1.4 {
    56     56     DROP TABLE t1;
    57     57   } {}
    58     58   do_test rtreeG-1.4log {
    59     59     set ::log
    60     60   } {}
    61     61   
           62  +expand_all_sql db
    62     63   db close
    63     64   sqlite3_shutdown
    64     65   test_sqlite3_log
    65     66   sqlite3_initialize
    66     67   sqlite3 db test.db
    67     68   
    68     69   finish_test

Changes to test/fts3aa.test.

   246    246   do_execsql_test 9.1 {
   247    247     CREATE VIRTUAL TABLE t9 USING fts4(a, "", '---');
   248    248   }
   249    249   do_execsql_test 9.2 {
   250    250     CREATE VIRTUAL TABLE t10 USING fts3(<, b, c);
   251    251   }
   252    252   
          253  +expand_all_sql db
   253    254   finish_test

Changes to test/tester.tcl.

  2304   2304   # [finish_test ; return] in the callers context.
  2305   2305   #
  2306   2306   proc test_find_sqldiff {} {
  2307   2307     set prog [test_find_binary sqldiff]
  2308   2308     if {$prog==""} { return -code return }
  2309   2309     return $prog
  2310   2310   }
         2311  +
         2312  +# Call sqlite3_expanded_sql() on all statements associated with database
         2313  +# connection $db. This sometimes finds use-after-free bugs if run with
         2314  +# valgrind or address-sanitizer.
         2315  +proc expand_all_sql {db} {
         2316  +  set stmt ""
         2317  +  while {[set stmt [sqlite3_next_stmt $db $stmt]]!=""} {
         2318  +    sqlite3_expanded_sql $stmt
         2319  +  }
         2320  +}
  2311   2321   
  2312   2322   
  2313   2323   # If the library is compiled with the SQLITE_DEFAULT_AUTOVACUUM macro set
  2314   2324   # to non-zero, then set the global variable $AUTOVACUUM to 1.
  2315   2325   set AUTOVACUUM $sqlite_options(default_autovacuum)
  2316   2326   
  2317   2327   # Make sure the FTS enhanced query syntax is disabled.