/ Check-in [f634a7e3]
Login

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

Overview
Comment:Improved error messages from the zipfile extension.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256:f634a7e386918b829389f20c330d312315fdd61125cd2c5f66cf17a5d74bce49
User & Date: drh 2018-03-10 13:21:41
Context
2018-03-10
14:17
Add support for INSERT OR REPLACE and INSERT OR IGNORE on the zipfile extension. check-in: 8ad35d48 user: drh tags: trunk
13:21
Improved error messages from the zipfile extension. check-in: f634a7e3 user: drh tags: trunk
12:53
Avoid harmless left-shifts of negative numbers in the zipfile extension when building ZIP archives of files with pre-DOS dates. check-in: 16bba865 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/misc/zipfile.c.

   469    469     return SQLITE_OK;
   470    470   }
   471    471   
   472    472   /*
   473    473   ** Set the error message for the virtual table associated with cursor
   474    474   ** pCsr to the results of vprintf(zFmt, ...).
   475    475   */
   476         -static void zipfileSetErrmsg(ZipfileCsr *pCsr, const char *zFmt, ...){
          476  +static void zipfileTableErr(ZipfileTab *pTab, const char *zFmt, ...){
          477  +  va_list ap;
          478  +  va_start(ap, zFmt);
          479  +  sqlite3_free(pTab->base.zErrMsg);
          480  +  pTab->base.zErrMsg = sqlite3_vmprintf(zFmt, ap);
          481  +  va_end(ap);
          482  +}
          483  +static void zipfileCursorErr(ZipfileCsr *pCsr, const char *zFmt, ...){
   477    484     va_list ap;
   478    485     va_start(ap, zFmt);
          486  +  sqlite3_free(pCsr->base.pVtab->zErrMsg);
   479    487     pCsr->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
   480    488     va_end(ap);
   481    489   }
   482    490   
   483    491   /*
   484    492   ** Read nRead bytes of data from offset iOff of file pFile into buffer
   485    493   ** aRead[]. Return SQLITE_OK if successful, or an SQLite error code
................................................................................
  1234   1242     int bInMemory = 0;              /* True for an in-memory zipfile */
  1235   1243   
  1236   1244     zipfileResetCursor(pCsr);
  1237   1245   
  1238   1246     if( pTab->zFile ){
  1239   1247       zFile = pTab->zFile;
  1240   1248     }else if( idxNum==0 ){
  1241         -    zipfileSetErrmsg(pCsr, "zipfile() function requires an argument");
         1249  +    zipfileCursorErr(pCsr, "zipfile() function requires an argument");
  1242   1250       return SQLITE_ERROR;
  1243   1251     }else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
  1244   1252       const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]);
  1245   1253       int nBlob = sqlite3_value_bytes(argv[0]);
  1246   1254       assert( pTab->pFirstEntry==0 );
  1247   1255       rc = zipfileLoadDirectory(pTab, aBlob, nBlob);
  1248   1256       pCsr->pFreeEntry = pTab->pFirstEntry;
................................................................................
  1252   1260     }else{
  1253   1261       zFile = (const char*)sqlite3_value_text(argv[0]);
  1254   1262     }
  1255   1263   
  1256   1264     if( 0==pTab->pWriteFd && 0==bInMemory ){
  1257   1265       pCsr->pFile = fopen(zFile, "rb");
  1258   1266       if( pCsr->pFile==0 ){
  1259         -      zipfileSetErrmsg(pCsr, "cannot open file: %s", zFile);
         1267  +      zipfileCursorErr(pCsr, "cannot open file: %s", zFile);
  1260   1268         rc = SQLITE_ERROR;
  1261   1269       }else{
  1262   1270         rc = zipfileReadEOCD(pTab, 0, 0, pCsr->pFile, &pCsr->eocd);
  1263   1271         if( rc==SQLITE_OK ){
  1264   1272           if( pCsr->eocd.nEntry==0 ){
  1265   1273             pCsr->bEof = 1;
  1266   1274           }else{
................................................................................
  1401   1409         if( z[i]==zTemplate[i] ) mode |= 1 << (9-i);
  1402   1410         else if( z[i]!='-' ) goto parse_error;
  1403   1411       }
  1404   1412     }
  1405   1413     if( ((mode & S_IFDIR)==0)==bIsDir ){
  1406   1414       /* The "mode" attribute is a directory, but data has been specified.
  1407   1415       ** Or vice-versa - no data but "mode" is a file or symlink.  */
         1416  +    *pzErr = sqlite3_mprintf("zipfile: mode does not match data");
  1408   1417       return SQLITE_CONSTRAINT;
  1409   1418     }
  1410   1419     *pMode = mode;
  1411   1420     return SQLITE_OK;
  1412   1421   
  1413   1422    parse_error:
  1414   1423     *pzErr = sqlite3_mprintf("zipfile: parse error in mode: %s", z);
................................................................................
  1531   1540         }
  1532   1541         assert( pOld->pNext );
  1533   1542       }
  1534   1543     }
  1535   1544   
  1536   1545     if( nVal>1 ){
  1537   1546       /* Check that "sz" and "rawdata" are both NULL: */
  1538         -    if( sqlite3_value_type(apVal[5])!=SQLITE_NULL
  1539         -     || sqlite3_value_type(apVal[6])!=SQLITE_NULL
  1540         -    ){
         1547  +    if( sqlite3_value_type(apVal[5])!=SQLITE_NULL ){
         1548  +      zipfileTableErr(pTab, "sz must be NULL");
         1549  +      rc = SQLITE_CONSTRAINT;
         1550  +    }
         1551  +    if( sqlite3_value_type(apVal[6])!=SQLITE_NULL ){
         1552  +      zipfileTableErr(pTab, "rawdata must be NULL"); 
  1541   1553         rc = SQLITE_CONSTRAINT;
  1542   1554       }
  1543   1555   
  1544   1556       if( rc==SQLITE_OK ){
  1545   1557         if( sqlite3_value_type(apVal[7])==SQLITE_NULL ){
  1546   1558           /* data=NULL. A directory */
  1547   1559           bIsDir = 1;
................................................................................
  1553   1565           int bAuto = sqlite3_value_type(apVal[8])==SQLITE_NULL;
  1554   1566   
  1555   1567           iMethod = sqlite3_value_int(apVal[8]);
  1556   1568           sz = nIn;
  1557   1569           pData = aIn;
  1558   1570           nData = nIn;
  1559   1571           if( iMethod!=0 && iMethod!=8 ){
         1572  +          zipfileTableErr(pTab, "unknown compression method: %d", iMethod);
  1560   1573             rc = SQLITE_CONSTRAINT;
  1561   1574           }else{
  1562   1575             if( bAuto || iMethod ){
  1563   1576               int nCmp;
  1564   1577               rc = zipfileDeflate(aIn, nIn, &pFree, &nCmp, &pTab->base.zErrMsg);
  1565   1578               if( rc==SQLITE_OK ){
  1566   1579                 if( iMethod || nCmp<nIn ){
................................................................................
  1599   1612       }
  1600   1613   
  1601   1614       /* Check that we're not inserting a duplicate entry */
  1602   1615       if( pOld==0 && rc==SQLITE_OK ){
  1603   1616         ZipfileEntry *p;
  1604   1617         for(p=pTab->pFirstEntry; p; p=p->pNext){
  1605   1618           if( zipfileComparePath(p->cds.zFile, zPath, nPath)==0 ){
         1619  +          zipfileTableErr(pTab, "duplicate name: \"%s\"", zPath);
  1606   1620             rc = SQLITE_CONSTRAINT;
  1607   1621             break;
  1608   1622           }
  1609   1623         }
  1610   1624       }
  1611   1625   
  1612   1626       if( rc==SQLITE_OK ){

Changes to test/zipfile.test.

   146    146     5 data {} 0 {} 0
   147    147     6 method {} 0 {} 0
   148    148   }
   149    149   
   150    150   do_catchsql_test 1.1.0.1 {
   151    151     INSERT INTO zz(name, mode, mtime, sz, rawdata, method) 
   152    152     VALUES('f.txt', '-rw-r--r--', 1000000000, 5, 'abcde', 0);
   153         -} {1 {constraint failed}}
          153  +} {1 {rawdata must be NULL}}
   154    154   do_catchsql_test 1.1.0.2 {
   155    155     INSERT INTO zz(name, mtime, sz, data, method) 
   156    156     VALUES('g.txt', 1000000002, 5, '12345', 0);
   157         -} {1 {constraint failed}}
          157  +} {1 {sz must be NULL}}
   158    158   do_catchsql_test 1.1.0.3 {
   159    159     INSERT INTO zz(name, mtime, rawdata, method) 
   160    160     VALUES('g.txt', 1000000002, '12345', 0);
   161         -} {1 {constraint failed}}
          161  +} {1 {rawdata must be NULL}}
   162    162   do_catchsql_test 1.1.0.4 {
   163    163     INSERT INTO zz(name, data, method) 
   164    164     VALUES('g.txt', '12345', 7);
   165         -} {1 {constraint failed}}
          165  +} {1 {unknown compression method: 7}}
   166    166   
   167    167   do_execsql_test 1.1.1 {
   168    168     INSERT INTO zz(name, mode, mtime, data, method) 
   169    169     VALUES('f.txt', '-rw-r--r--', 1000000000, 'abcde', 0);
   170    170   }
   171    171   do_execsql_test 1.1.2 {
   172    172     INSERT INTO zz(name, mode, mtime, data, method) 
................................................................................
   283    283     blue.txt/ 16877 1000000000 {} 0
   284    284     h.txt 33189 1000000004 aaaaaaaaaabbbbbbbbbb 8
   285    285     i.txt 33188 4 zxcvb 0
   286    286   }
   287    287   
   288    288   do_catchsql_test 1.6.7 {
   289    289     UPDATE zz SET data=NULL WHERE name='i.txt'
   290         -} {1 {constraint failed}}
          290  +} {1 {zipfile: mode does not match data}}
   291    291   do_execsql_test 1.6.8 {
   292    292     SELECT name, mode, mtime, data, method FROM zipfile('test.zip');
   293    293   } {
   294    294     blue.txt/ 16877 1000000000 {} 0
   295    295     h.txt 33189 1000000004 aaaaaaaaaabbbbbbbbbb 8
   296    296     i.txt 33188 4 zxcvb 0
   297    297   }
................................................................................
   394    394   foreach {tn fname} {
   395    395     1 dir1
   396    396     2 file1
   397    397     3 dir1/file2
   398    398   } {
   399    399     do_catchsql_test 3.1.$tn.0 {
   400    400       INSERT INTO x1(name, data) VALUES($fname, NULL);
   401         -  } {1 {constraint failed}}
          401  +  } [list 1 "duplicate name: \"$fname/\""]
   402    402     do_catchsql_test 3.1.$tn.1 {
   403    403       INSERT INTO x1(name, data) VALUES($fname || '/', NULL);
   404         -  } {1 {constraint failed}}
          404  +  } [list 1 "duplicate name: \"$fname/\""]
   405    405     do_catchsql_test 3.1.$tn.2 {
   406    406       INSERT INTO x1(name, data) VALUES($fname, 'abcd');
   407         -  } {1 {constraint failed}}
          407  +  } [list 1 "duplicate name: \"$fname\""]
   408    408   }
   409    409   
   410    410   do_catchsql_test 3.2 {
   411    411     SELECT rowid FROM x1
   412    412   } {1 {no such column: rowid}}
   413    413   
   414    414   #-------------------------------------------------------------------------
................................................................................
   633    633       VALUES('dir3//') UNION ALL
   634    634       VALUES('dir4///') UNION ALL
   635    635       VALUES('/') 
   636    636     )
   637    637     SELECT name FROM zipfile((SELECT zipfile(nm, NULL) FROM src))
   638    638   } {dir1/ dir2/ dir3/ dir4/ /}
   639    639   finish_test
   640         -