/ Check-in [d99bb0c1]
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:Avoid reading outside a record buffer when extracting an SQL value in the sqlite_dbdata virtual table code.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: d99bb0c11d62f629bf59da037827af73a9b814e65815006e0cbca1bc41f42e25
User & Date: dan 2019-05-09 11:34:31
Context
2019-05-09
11:45
Fix a problem with running the ".recover" command on a database that is zero pages in size. check-in: 47fa6534 user: dan tags: trunk
11:34
Avoid reading outside a record buffer when extracting an SQL value in the sqlite_dbdata virtual table code. check-in: d99bb0c1 user: dan tags: trunk
11:21
Merge accidental fork in trunk. check-in: ec937303 user: dan tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ext/misc/dbdata.c.

378
379
380
381
382
383
384

385
386

387
388

389
390
391
392
393






394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435

436
437
438
439
440
441
442
443
444
445
446
447
...
724
725
726
727
728
729
730
731


732
733
734
735
736
737
738
      return 4;
    case 5:
      return 6;
    case 6:
    case 7:
      return 8;
    default:

      return ((eType-12) / 2);
  }

}


/*
** Load a value of type eType from buffer pData and use it to set the
** result of context object pCtx.
*/
static void dbdataValue(sqlite3_context *pCtx, int eType, u8 *pData){






  switch( eType ){
    case 0: 
    case 10: 
    case 11: 
      sqlite3_result_null(pCtx);
      break;
    
    case 8: 
      sqlite3_result_int(pCtx, 0);
      break;
    case 9:
      sqlite3_result_int(pCtx, 1);
      break;

    case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
      sqlite3_uint64 v = (signed char)pData[0];
      pData++;
      switch( eType ){
        case 7:
        case 6:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
        case 5:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
        case 4:  v = (v<<8) + pData[0];  pData++;
        case 3:  v = (v<<8) + pData[0];  pData++;
        case 2:  v = (v<<8) + pData[0];  pData++;
      }

      if( eType==7 ){
        double r;
        memcpy(&r, &v, sizeof(r));
        sqlite3_result_double(pCtx, r);
      }else{
        sqlite3_result_int64(pCtx, (sqlite3_int64)v);
      }
      break;
    }

    default: {
      int n = ((eType-12) / 2);
      if( eType % 2 ){
        sqlite3_result_text(pCtx, (const char*)pData, n, SQLITE_TRANSIENT);
      }else{
        sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);

      }
    }
  }
}


/*
** Move an sqlite_dbdata or sqlite_dbptr cursor to the next entry.
*/
static int dbdataNext(sqlite3_vtab_cursor *pCursor){
  DbdataCursor *pCsr = (DbdataCursor*)pCursor;
  DbdataTable *pTab = (DbdataTable*)pCursor->pVtab;
................................................................................
        break;
      case DBDATA_COLUMN_VALUE: {
        if( pCsr->iField<0 ){
          sqlite3_result_int64(ctx, pCsr->iIntkey);
        }else{
          sqlite3_int64 iType;
          dbdataGetVarint(pCsr->pHdrPtr, &iType);
          dbdataValue(ctx, iType, pCsr->pPtr);


        }
        break;
      }
    }
  }
  return SQLITE_OK;
}







>
|
|
>
|
|
>




|
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>




<







 







|
>
>







378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449

450
451
452
453
454
455
456
...
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
      return 4;
    case 5:
      return 6;
    case 6:
    case 7:
      return 8;
    default:
      if( eType>0 ){
        return ((eType-12) / 2);
      }
      return 0;
  }
}

/*
** Load a value of type eType from buffer pData and use it to set the
** result of context object pCtx.
*/
static void dbdataValue(
  sqlite3_context *pCtx, 
  int eType, 
  u8 *pData,
  int nData
){
  if( eType>=0 && dbdataValueBytes(eType)<=nData ){
    switch( eType ){
      case 0: 
      case 10: 
      case 11: 
        sqlite3_result_null(pCtx);
        break;
      
      case 8: 
        sqlite3_result_int(pCtx, 0);
        break;
      case 9:
        sqlite3_result_int(pCtx, 1);
        break;
  
      case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
        sqlite3_uint64 v = (signed char)pData[0];
        pData++;
        switch( eType ){
          case 7:
          case 6:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
          case 5:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
          case 4:  v = (v<<8) + pData[0];  pData++;
          case 3:  v = (v<<8) + pData[0];  pData++;
          case 2:  v = (v<<8) + pData[0];  pData++;
        }
  
        if( eType==7 ){
          double r;
          memcpy(&r, &v, sizeof(r));
          sqlite3_result_double(pCtx, r);
        }else{
          sqlite3_result_int64(pCtx, (sqlite3_int64)v);
        }
        break;
      }
  
      default: {
        int n = ((eType-12) / 2);
        if( eType % 2 ){
          sqlite3_result_text(pCtx, (const char*)pData, n, SQLITE_TRANSIENT);
        }else{
          sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
        }
      }
    }
  }
}


/*
** Move an sqlite_dbdata or sqlite_dbptr cursor to the next entry.
*/
static int dbdataNext(sqlite3_vtab_cursor *pCursor){
  DbdataCursor *pCsr = (DbdataCursor*)pCursor;
  DbdataTable *pTab = (DbdataTable*)pCursor->pVtab;
................................................................................
        break;
      case DBDATA_COLUMN_VALUE: {
        if( pCsr->iField<0 ){
          sqlite3_result_int64(ctx, pCsr->iIntkey);
        }else{
          sqlite3_int64 iType;
          dbdataGetVarint(pCsr->pHdrPtr, &iType);
          dbdataValue(
              ctx, iType, pCsr->pPtr, &pCsr->pRec[pCsr->nRec] - pCsr->pPtr
          );
        }
        break;
      }
    }
  }
  return SQLITE_OK;
}