/ Check-in [2c8769c6]
Login

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

Overview
Comment:Early detection of implausibly sized records to avoid unnecessary large memory allocations.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 2c8769c69f301307db6663adb8b7c0b89f5959516bf6110cb8ff4b21bd903f70
User & Date: drh 2019-02-04 21:10:24
Context
2019-02-05
08:55
Update test file "resetdb.test" so that it works with the "prepare" permutation. check-in: 95d33812 user: dan tags: trunk
2019-02-04
21:10
Early detection of implausibly sized records to avoid unnecessary large memory allocations. check-in: 2c8769c6 user: drh tags: trunk
19:52
Mention the new -memtrace command-line option in the -help output of the CLI. check-in: ada91aef user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

  4514   4514   */
  4515   4515   u32 sqlite3BtreePayloadSize(BtCursor *pCur){
  4516   4516     assert( cursorHoldsMutex(pCur) );
  4517   4517     assert( pCur->eState==CURSOR_VALID );
  4518   4518     getCellInfo(pCur);
  4519   4519     return pCur->info.nPayload;
  4520   4520   }
         4521  +
         4522  +/*
         4523  +** Return an upper bound on the size of any record for the table
         4524  +** that the cursor is pointing into.
         4525  +**
         4526  +** This is an optimization.  Everything will still work if this
         4527  +** routine always returns 2147483647 (which is the largest record
         4528  +** that SQLite can handle) or more.  But returning a smaller value might
         4529  +** prevent large memory allocations when trying to interpret a
         4530  +** corrupt datrabase.
         4531  +**
         4532  +** The current implementation merely returns the size of the underlying
         4533  +** database file.
         4534  +*/
         4535  +sqlite3_int64 sqlite3BtreeMaxRecordSize(BtCursor *pCur){
         4536  +  assert( cursorHoldsMutex(pCur) );
         4537  +  assert( pCur->eState==CURSOR_VALID );
         4538  +  return pCur->pBt->pageSize * (sqlite3_int64)pCur->pBt->nPage;
         4539  +}
  4521   4540   
  4522   4541   /*
  4523   4542   ** Given the page number of an overflow page in the database (parameter
  4524   4543   ** ovfl), this function finds the page number of the next page in the 
  4525   4544   ** linked list of overflow pages. If possible, it uses the auto-vacuum
  4526   4545   ** pointer-map data instead of reading the content of page ovfl to do so. 
  4527   4546   **

Changes to src/btree.h.

   311    311   i64 sqlite3BtreeIntegerKey(BtCursor*);
   312    312   #ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
   313    313   i64 sqlite3BtreeOffset(BtCursor*);
   314    314   #endif
   315    315   int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*);
   316    316   const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt);
   317    317   u32 sqlite3BtreePayloadSize(BtCursor*);
          318  +sqlite3_int64 sqlite3BtreeMaxRecordSize(BtCursor*);
   318    319   
   319    320   char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
   320    321   struct Pager *sqlite3BtreePager(Btree*);
   321    322   i64 sqlite3BtreeRowCountEst(BtCursor*);
   322    323   
   323    324   #ifndef SQLITE_OMIT_INCRBLOB
   324    325   int sqlite3BtreePayloadChecked(BtCursor*, u32 offset, u32 amt, void*);

Changes to src/vdbemem.c.

  1120   1120     BtCursor *pCur,   /* Cursor pointing at record to retrieve. */
  1121   1121     u32 offset,       /* Offset from the start of data to return bytes from. */
  1122   1122     u32 amt,          /* Number of bytes to return. */
  1123   1123     Mem *pMem         /* OUT: Return data in this Mem structure. */
  1124   1124   ){
  1125   1125     int rc;
  1126   1126     pMem->flags = MEM_Null;
         1127  +  if( sqlite3BtreeMaxRecordSize(pCur)<offset+amt ){
         1128  +    return SQLITE_CORRUPT_BKPT;
         1129  +  }
  1127   1130     if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+1)) ){
  1128   1131       rc = sqlite3BtreePayload(pCur, offset, amt, pMem->z);
  1129   1132       if( rc==SQLITE_OK ){
  1130   1133         pMem->z[amt] = 0;   /* Overrun area used when reading malformed records */
  1131   1134         pMem->flags = MEM_Blob;
  1132   1135         pMem->n = (int)amt;
  1133   1136       }else{