/ Check-in [4a9483f8]
Login

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

Overview
Comment:Have fts5 reject attempts to insert a non-integer, non-null value into a rowid column with SQLITE_MISMATCH.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 4a9483f81e9ca1aa41d6ca33cb3171370418ccc71fdee9741bbf6f694bf4fbaa
User & Date: dan 2019-01-15 15:18:58
Context
2019-01-15
16:14
Fix a buffer overread in fts3 caused by a corrupt record. check-in: e54efd60 user: dan tags: trunk
15:18
Have fts5 reject attempts to insert a non-integer, non-null value into a rowid column with SQLITE_MISMATCH. check-in: 4a9483f8 user: dan tags: trunk
14:44
Fix a harmless memory leak in the Lemon parser generator utility program. check-in: 1caff0fb user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/fts5/fts5_main.c.

  1493   1493     int rc = SQLITE_OK;             /* Return code */
  1494   1494   
  1495   1495     /* A transaction must be open when this is called. */
  1496   1496     assert( pTab->ts.eState==1 );
  1497   1497   
  1498   1498     assert( pVtab->zErrMsg==0 );
  1499   1499     assert( nArg==1 || nArg==(2+pConfig->nCol+2) );
  1500         -  assert( nArg==1 
  1501         -      || sqlite3_value_type(apVal[1])==SQLITE_INTEGER 
  1502         -      || sqlite3_value_type(apVal[1])==SQLITE_NULL 
         1500  +  assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER 
         1501  +       || sqlite3_value_type(apVal[0])==SQLITE_NULL 
  1503   1502     );
  1504   1503     assert( pTab->pConfig->pzErrmsg==0 );
  1505   1504     pTab->pConfig->pzErrmsg = &pTab->base.zErrMsg;
  1506   1505   
  1507   1506     /* Put any active cursors into REQUIRE_SEEK state. */
  1508   1507     fts5TripCursors(pTab);
  1509   1508   
................................................................................
  1552   1551   
  1553   1552       /* DELETE */
  1554   1553       else if( nArg==1 ){
  1555   1554         i64 iDel = sqlite3_value_int64(apVal[0]);  /* Rowid to delete */
  1556   1555         rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0);
  1557   1556       }
  1558   1557   
  1559         -    /* INSERT */
  1560         -    else if( eType0!=SQLITE_INTEGER ){     
  1561         -      /* If this is a REPLACE, first remove the current entry (if any) */
  1562         -      if( eConflict==SQLITE_REPLACE 
  1563         -       && sqlite3_value_type(apVal[1])==SQLITE_INTEGER 
  1564         -      ){
  1565         -        i64 iNew = sqlite3_value_int64(apVal[1]);  /* Rowid to delete */
  1566         -        rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
  1567         -      }
  1568         -      fts5StorageInsert(&rc, pTab, apVal, pRowid);
  1569         -    }
  1570         -
  1571         -    /* UPDATE */
         1558  +    /* INSERT or UPDATE */
  1572   1559       else{
  1573         -      i64 iOld = sqlite3_value_int64(apVal[0]);  /* Old rowid */
  1574         -      i64 iNew = sqlite3_value_int64(apVal[1]);  /* New rowid */
  1575         -      if( iOld!=iNew ){
  1576         -        if( eConflict==SQLITE_REPLACE ){
  1577         -          rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
  1578         -          if( rc==SQLITE_OK ){
  1579         -            rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
  1580         -          }
  1581         -          fts5StorageInsert(&rc, pTab, apVal, pRowid);
  1582         -        }else{
  1583         -          rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, pRowid);
  1584         -          if( rc==SQLITE_OK ){
         1560  +      int eType1 = sqlite3_value_numeric_type(apVal[1]);
         1561  +
         1562  +      if( eType1!=SQLITE_INTEGER && eType1!=SQLITE_NULL ){
         1563  +        rc = SQLITE_MISMATCH;
         1564  +      }
         1565  +
         1566  +      else if( eType0!=SQLITE_INTEGER ){     
         1567  +        /* If this is a REPLACE, first remove the current entry (if any) */
         1568  +        if( eConflict==SQLITE_REPLACE && eType1==SQLITE_INTEGER ){
         1569  +          i64 iNew = sqlite3_value_int64(apVal[1]);  /* Rowid to delete */
         1570  +          rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
         1571  +        }
         1572  +        fts5StorageInsert(&rc, pTab, apVal, pRowid);
         1573  +      }
         1574  +
         1575  +      /* UPDATE */
         1576  +      else{
         1577  +        i64 iOld = sqlite3_value_int64(apVal[0]);  /* Old rowid */
         1578  +        i64 iNew = sqlite3_value_int64(apVal[1]);  /* New rowid */
         1579  +        if( eType1==SQLITE_INTEGER && iOld!=iNew ){
         1580  +          if( eConflict==SQLITE_REPLACE ){
  1585   1581               rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
  1586         -          }
  1587         -          if( rc==SQLITE_OK ){
  1588         -            rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal, *pRowid);
         1582  +            if( rc==SQLITE_OK ){
         1583  +              rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
         1584  +            }
         1585  +            fts5StorageInsert(&rc, pTab, apVal, pRowid);
         1586  +          }else{
         1587  +            rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, pRowid);
         1588  +            if( rc==SQLITE_OK ){
         1589  +              rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
         1590  +            }
         1591  +            if( rc==SQLITE_OK ){
         1592  +              rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal,*pRowid);
         1593  +            }
  1589   1594             }
         1595  +        }else{
         1596  +          rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
         1597  +          fts5StorageInsert(&rc, pTab, apVal, pRowid);
  1590   1598           }
  1591         -      }else{
  1592         -        rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
  1593         -        fts5StorageInsert(&rc, pTab, apVal, pRowid);
  1594   1599         }
  1595   1600       }
  1596   1601     }
  1597   1602   
  1598   1603     pTab->pConfig->pzErrmsg = 0;
  1599   1604     return rc;
  1600   1605   }

Changes to ext/fts5/test/fts5update.test.

   130    130     db eval { SELECT * FROM x3('one') } {
   131    131       db eval {
   132    132         INSERT INTO x3(x3) VALUES('optimize');
   133    133       }
   134    134     }
   135    135   } {}
   136    136   
          137  +do_execsql_test 4.0 {
          138  +  CREATE VIRTUAL TABLE x4 USING fts5(a, detail=%DETAIL%);
          139  +  INSERT INTO x4 VALUES('one two three');
          140  +  INSERT INTO x4(rowid, a) VALUES('2', 'one two three');
          141  +  INSERT INTO x4(rowid, a) VALUES('3.0', 'one two three');
          142  +}
          143  +do_catchsql_test 4.1 {
          144  +  INSERT INTO x4(rowid, a) VALUES('four', 'one two three');
          145  +} {1 {datatype mismatch}}
          146  +
          147  +do_catchsql_test 4.2 {
          148  +  UPDATE x4 SET rowid = 'four' WHERE rowid=1;
          149  +} {1 {datatype mismatch}}
          150  +
   137    151   
   138    152   }
   139    153   
   140    154   reset_db
   141    155   do_catchsql_test 4.0 { CREATE VIRTUAL TABLE t1 USING fts5(a,b,c); } {0 {}}
   142    156   do_catchsql_test 4.1 { DELETE FROM t1 WHERE t1 MATCH 'f*'; } {0 {}}
   143    157   finish_test