/ Check-in [ea7dfde7]
Login

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

Overview
Comment:Avoid allocating large objects on the stack in the incremental BLOB I/O interface. (CVS 6703)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:ea7dfde700fb57ed0ecb5000a55abbf45aa1e09d
User & Date: drh 2009-06-01 19:53:31
Context
2009-06-02
15:21
Add the vdbe-compress.tcl script which automatically refactors the sqlite3VdbeExec() routine to use less stack space. Use this script when constructing the amalgamation. (CVS 6704) check-in: 7f433918 user: drh tags: trunk
2009-06-01
19:53
Avoid allocating large objects on the stack in the incremental BLOB I/O interface. (CVS 6703) check-in: ea7dfde7 user: drh tags: trunk
18:18
Malloc for space to hold the Parse object in sqlite3_prepare() and friends. Or, if compiled with SQLITE_USE_ALLOCA, obtain space for the object from alloca(). (CVS 6702) check-in: c7c0c58e user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/vdbeblob.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   **
    13     13   ** This file contains code used to implement incremental BLOB I/O.
    14     14   **
    15         -** $Id: vdbeblob.c,v 1.32 2009/05/09 15:17:47 drh Exp $
           15  +** $Id: vdbeblob.c,v 1.33 2009/06/01 19:53:31 drh Exp $
    16     16   */
    17     17   
    18     18   #include "sqliteInt.h"
    19     19   #include "vdbeInt.h"
    20     20   
    21     21   #ifndef SQLITE_OMIT_INCRBLOB
    22     22   
................................................................................
    79     79       {OP_ResultRow, 1, 0, 0},       /* 7  */
    80     80       {OP_Close, 0, 0, 0},           /* 8  */
    81     81       {OP_Halt, 0, 0, 0},            /* 9 */
    82     82     };
    83     83   
    84     84     Vdbe *v = 0;
    85     85     int rc = SQLITE_OK;
    86         -  char zErr[128];
           86  +  char *zErr = 0;
           87  +  Table *pTab;
           88  +  Parse *pParse;
    87     89   
    88     90     *ppBlob = 0;
    89         -  zErr[0] = 0;
    90     91     sqlite3_mutex_enter(db->mutex);
           92  +  pParse = sqlite3StackAllocRaw(db, sizeof(*pParse));
           93  +  if( pParse==0 ){
           94  +    rc = SQLITE_NOMEM;
           95  +    goto blob_open_out;
           96  +  }
    91     97     do {
    92         -    Parse sParse;
    93         -    Table *pTab;
    94         -
    95         -    memset(&sParse, 0, sizeof(Parse));
    96         -    sParse.db = db;
           98  +    memset(pParse, 0, sizeof(Parse));
           99  +    pParse->db = db;
    97    100   
    98    101       if( sqlite3SafetyOn(db) ){
          102  +      sqlite3DbFree(db, zErr);
          103  +      sqlite3StackFree(db, pParse);
    99    104         sqlite3_mutex_leave(db->mutex);
   100    105         return SQLITE_MISUSE;
   101    106       }
   102    107   
   103    108       sqlite3BtreeEnterAll(db);
   104         -    pTab = sqlite3LocateTable(&sParse, 0, zTable, zDb);
          109  +    pTab = sqlite3LocateTable(pParse, 0, zTable, zDb);
   105    110       if( pTab && IsVirtual(pTab) ){
   106    111         pTab = 0;
   107         -      sqlite3ErrorMsg(&sParse, "cannot open virtual table: %s", zTable);
          112  +      sqlite3ErrorMsg(pParse, "cannot open virtual table: %s", zTable);
   108    113       }
   109    114   #ifndef SQLITE_OMIT_VIEW
   110    115       if( pTab && pTab->pSelect ){
   111    116         pTab = 0;
   112         -      sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable);
          117  +      sqlite3ErrorMsg(pParse, "cannot open view: %s", zTable);
   113    118       }
   114    119   #endif
   115    120       if( !pTab ){
   116         -      if( sParse.zErrMsg ){
   117         -        sqlite3_snprintf(sizeof(zErr), zErr, "%s", sParse.zErrMsg);
          121  +      if( pParse->zErrMsg ){
          122  +        sqlite3DbFree(db, zErr);
          123  +        zErr = pParse->zErrMsg;
          124  +        pParse->zErrMsg = 0;
   118    125         }
   119         -      sqlite3DbFree(db, sParse.zErrMsg);
   120    126         rc = SQLITE_ERROR;
   121    127         (void)sqlite3SafetyOff(db);
   122    128         sqlite3BtreeLeaveAll(db);
   123    129         goto blob_open_out;
   124    130       }
   125    131   
   126    132       /* Now search pTab for the exact column. */
   127    133       for(iCol=0; iCol < pTab->nCol; iCol++) {
   128    134         if( sqlite3StrICmp(pTab->aCol[iCol].zName, zColumn)==0 ){
   129    135           break;
   130    136         }
   131    137       }
   132    138       if( iCol==pTab->nCol ){
   133         -      sqlite3_snprintf(sizeof(zErr), zErr, "no such column: \"%s\"", zColumn);
          139  +      sqlite3DbFree(db, zErr);
          140  +      zErr = sqlite3MPrintf(db, "no such column: \"%s\"", zColumn);
   134    141         rc = SQLITE_ERROR;
   135    142         (void)sqlite3SafetyOff(db);
   136    143         sqlite3BtreeLeaveAll(db);
   137    144         goto blob_open_out;
   138    145       }
   139    146   
   140    147       /* If the value is being opened for writing, check that the
................................................................................
   143    150       */
   144    151       if( flags ){
   145    152         Index *pIdx;
   146    153         for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
   147    154           int j;
   148    155           for(j=0; j<pIdx->nColumn; j++){
   149    156             if( pIdx->aiColumn[j]==iCol ){
   150         -            sqlite3_snprintf(sizeof(zErr), zErr,
          157  +            sqlite3DbFree(db, zErr);
          158  +            zErr = sqlite3MPrintf(db,
   151    159                                "cannot open indexed column for writing");
   152    160               rc = SQLITE_ERROR;
   153    161               (void)sqlite3SafetyOff(db);
   154    162               sqlite3BtreeLeaveAll(db);
   155    163               goto blob_open_out;
   156    164             }
   157    165           }
................................................................................
   203    211       }
   204    212   
   205    213       sqlite3_bind_int64((sqlite3_stmt *)v, 1, iRow);
   206    214       rc = sqlite3_step((sqlite3_stmt *)v);
   207    215       if( rc!=SQLITE_ROW ){
   208    216         nAttempt++;
   209    217         rc = sqlite3_finalize((sqlite3_stmt *)v);
   210         -      sqlite3_snprintf(sizeof(zErr), zErr, sqlite3_errmsg(db));
          218  +      sqlite3DbFree(db, zErr);
          219  +      zErr = sqlite3MPrintf(db, sqlite3_errmsg(db));
   211    220         v = 0;
   212    221       }
   213    222     } while( nAttempt<5 && rc==SQLITE_SCHEMA );
   214    223   
   215    224     if( rc==SQLITE_ROW ){
   216    225       /* The row-record has been opened successfully. Check that the
   217    226       ** column in question contains text or a blob. If it contains
   218    227       ** text, it is up to the caller to get the encoding right.
   219    228       */
   220    229       Incrblob *pBlob;
   221    230       u32 type = v->apCsr[0]->aType[iCol];
   222    231   
   223    232       if( type<12 ){
   224         -      sqlite3_snprintf(sizeof(zErr), zErr, "cannot open value of type %s",
          233  +      sqlite3DbFree(db, zErr);
          234  +      zErr = sqlite3MPrintf(db, "cannot open value of type %s",
   225    235             type==0?"null": type==7?"real": "integer"
   226    236         );
   227    237         rc = SQLITE_ERROR;
   228    238         goto blob_open_out;
   229    239       }
   230    240       pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob));
   231    241       if( db->mallocFailed ){
................................................................................
   240    250       pBlob->pStmt = (sqlite3_stmt *)v;
   241    251       pBlob->iOffset = v->apCsr[0]->aOffset[iCol];
   242    252       pBlob->nByte = sqlite3VdbeSerialTypeLen(type);
   243    253       pBlob->db = db;
   244    254       *ppBlob = (sqlite3_blob *)pBlob;
   245    255       rc = SQLITE_OK;
   246    256     }else if( rc==SQLITE_OK ){
   247         -    sqlite3_snprintf(sizeof(zErr), zErr, "no such rowid: %lld", iRow);
          257  +    sqlite3DbFree(db, zErr);
          258  +    zErr = sqlite3MPrintf(db, "no such rowid: %lld", iRow);
   248    259       rc = SQLITE_ERROR;
   249    260     }
   250    261   
   251    262   blob_open_out:
   252         -  zErr[sizeof(zErr)-1] = '\0';
   253    263     if( v && (rc!=SQLITE_OK || db->mallocFailed) ){
   254    264       sqlite3VdbeFinalize(v);
   255    265     }
   256         -  sqlite3Error(db, rc, (rc==SQLITE_OK?0:zErr));
          266  +  sqlite3Error(db, rc, zErr);
          267  +  sqlite3DbFree(db, zErr);
          268  +  sqlite3StackFree(db, pParse);
   257    269     rc = sqlite3ApiExit(db, rc);
   258    270     sqlite3_mutex_leave(db->mutex);
   259    271     return rc;
   260    272   }
   261    273   
   262    274   /*
   263    275   ** Close a blob handle that was previously created using