/ Check-in [a6cb4002]
Login

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

Overview
Comment:Take care not to leave a zombie attached database if the attachment fails due to an encoding mismatch. Update attach logic to always use dynamically allocated error message strings. (CVS 6573)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:a6cb4002ada311b56fa2b7430b98b9a0fa698a01
User & Date: drh 2009-04-30 05:19:04
Context
2009-04-30
05:40
Fix a memory leak introduced in the previous check-in. (CVS 6574) check-in: f082bf36 user: drh tags: trunk
05:19
Take care not to leave a zombie attached database if the attachment fails due to an encoding mismatch. Update attach logic to always use dynamically allocated error message strings. (CVS 6573) check-in: a6cb4002 user: drh tags: trunk
01:22
Remove always-true tests from attach.c. In btree.c, always test the return from sqlite3PagerSetPagesize() since it might return SQLITE_NOMEM. (CVS 6572) check-in: 8bf60b24 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Show Whitespace Changes Patch

Changes to src/attach.c.

     7      7   **    May you do good and not evil.
     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   ** This file contains code used to implement the ATTACH and DETACH commands.
    13     13   **
    14         -** $Id: attach.c,v 1.85 2009/04/30 01:22:41 drh Exp $
           14  +** $Id: attach.c,v 1.86 2009/04/30 05:19:04 drh Exp $
    15     15   */
    16     16   #include "sqliteInt.h"
    17     17   
    18     18   #ifndef SQLITE_OMIT_ATTACH
    19     19   /*
    20     20   ** Resolve an expression that was part of an ATTACH or DETACH statement. This
    21     21   ** is slightly different from resolving a normal SQL expression, because simple
................................................................................
    70     70     int i;
    71     71     int rc = 0;
    72     72     sqlite3 *db = sqlite3_context_db_handle(context);
    73     73     const char *zName;
    74     74     const char *zFile;
    75     75     Db *aNew;
    76     76     char *zErrDyn = 0;
    77         -  char zErr[128];
    78     77   
    79     78     UNUSED_PARAMETER(NotUsed);
    80     79   
    81     80     zFile = (const char *)sqlite3_value_text(argv[0]);
    82     81     zName = (const char *)sqlite3_value_text(argv[1]);
    83     82     if( zFile==0 ) zFile = "";
    84     83     if( zName==0 ) zName = "";
................................................................................
    86     85     /* Check for the following errors:
    87     86     **
    88     87     **     * Too many attached databases,
    89     88     **     * Transaction currently open
    90     89     **     * Specified database name already being used.
    91     90     */
    92     91     if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){
    93         -    sqlite3_snprintf(
    94         -      sizeof(zErr), zErr, "too many attached databases - max %d", 
           92  +    zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d", 
    95     93         db->aLimit[SQLITE_LIMIT_ATTACHED]
    96     94       );
    97     95       goto attach_error;
    98     96     }
    99     97     if( !db->autoCommit ){
   100         -    sqlite3_snprintf(sizeof(zErr), zErr,
   101         -                     "cannot ATTACH database within transaction");
           98  +    zErrDyn = sqlite3MPrintf(db, "cannot ATTACH database within transaction");
   102     99       goto attach_error;
   103    100     }
   104    101     for(i=0; i<db->nDb; i++){
   105    102       char *z = db->aDb[i].zName;
   106    103       assert( z && zName );
   107    104       if( sqlite3StrICmp(z, zName)==0 ){
   108         -      sqlite3_snprintf(sizeof(zErr), zErr, 
   109         -                       "database %s is already in use", zName);
          105  +      zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName);
   110    106         goto attach_error;
   111    107       }
   112    108     }
   113    109   
   114    110     /* Allocate the new entry in the db->aDb[] array and initialise the schema
   115    111     ** hash tables.
   116    112     */
................................................................................
   135    131                              &aNew->pBt);
   136    132     if( rc==SQLITE_OK ){
   137    133       Pager *pPager;
   138    134       aNew->pSchema = sqlite3SchemaGet(db, aNew->pBt);
   139    135       if( !aNew->pSchema ){
   140    136         rc = SQLITE_NOMEM;
   141    137       }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){
   142         -      sqlite3_snprintf(sizeof(zErr), zErr, 
          138  +      zErrDyn = sqlite3MPrintf(db, 
   143    139           "attached databases must use the same text encoding as main database");
   144         -      goto attach_error;
          140  +      rc = SQLITE_ERROR;
   145    141       }
   146    142       pPager = sqlite3BtreePager(aNew->pBt);
   147    143       sqlite3PagerLockingMode(pPager, db->dfltLockMode);
   148    144       sqlite3PagerJournalMode(pPager, db->dfltJournalMode);
   149    145     }
   150    146     aNew->zName = sqlite3DbStrDup(db, zName);
   151    147     aNew->safety_level = 3;
................................................................................
   200    196         db->aDb[iDb].pBt = 0;
   201    197         db->aDb[iDb].pSchema = 0;
   202    198       }
   203    199       sqlite3ResetInternalSchema(db, 0);
   204    200       db->nDb = iDb;
   205    201       if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
   206    202         db->mallocFailed = 1;
   207         -      sqlite3_snprintf(sizeof(zErr),zErr, "out of memory");
   208         -    }else{
   209         -      sqlite3_snprintf(sizeof(zErr),zErr, "unable to open database: %s", zFile);
          203  +      zErrDyn = sqlite3MPrintf(db, "out of memory");
          204  +    }else if( zErrDyn==0 ){
          205  +      zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile);
   210    206       }
   211    207       goto attach_error;
   212    208     }
   213    209     
   214    210     return;
   215    211   
   216    212   attach_error:
   217    213     /* Return an error if we get here */
   218    214     if( zErrDyn ){
   219    215       sqlite3_result_error(context, zErrDyn, -1);
   220    216       sqlite3DbFree(db, zErrDyn);
   221         -  }else{
   222         -    zErr[sizeof(zErr)-1] = 0;
   223         -    sqlite3_result_error(context, zErr, -1);
   224    217     }
   225    218     if( rc ) sqlite3_result_error_code(context, rc);
   226    219   }
   227    220   
   228    221   /*
   229    222   ** An SQL user-function registered to do the work of an DETACH statement. The
   230    223   ** three arguments to the function come directly from a detach statement:
................................................................................
   408    401     Parse *pParse,      /* Error messages will be written here */
   409    402     int iDb,            /* This is the database that must be used */
   410    403     const char *zType,  /* "view", "trigger", or "index" */
   411    404     const Token *pName  /* Name of the view, trigger, or index */
   412    405   ){
   413    406     sqlite3 *db;
   414    407   
   415         -  if( iDb<0 || iDb==1 ) return 0;
          408  +  if( NEVER(iDb<0) || iDb==1 ) return 0;
   416    409     db = pParse->db;
   417    410     assert( db->nDb>iDb );
   418    411     pFix->pParse = pParse;
   419    412     pFix->zDb = db->aDb[iDb].zName;
   420    413     pFix->zType = zType;
   421    414     pFix->pName = pName;
   422    415     return 1;
................................................................................
   440    433     DbFixer *pFix,       /* Context of the fixation */
   441    434     SrcList *pList       /* The Source list to check and modify */
   442    435   ){
   443    436     int i;
   444    437     const char *zDb;
   445    438     struct SrcList_item *pItem;
   446    439   
   447         -  if( pList==0 ) return 0;
          440  +  if( NEVER(pList==0) ) return 0;
   448    441     zDb = pFix->zDb;
   449    442     for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
   450    443       if( pItem->zDatabase==0 ){
   451    444         pItem->zDatabase = sqlite3DbStrDup(pFix->pParse->db, zDb);
   452    445       }else if( sqlite3StrICmp(pItem->zDatabase,zDb)!=0 ){
   453    446         sqlite3ErrorMsg(pFix->pParse,
   454    447            "%s %T cannot reference objects in database %s",