/ Check-in [b0b7d036]
Login

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

Overview
Comment:Fix a problem in the zipfile module causing it to generate incorrect checksums. Remove the ability to insert compressed data into a zip archive.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256:b0b7d0363acf38c2178e2d3041d8ce2a0de061a51caa64670dbf539ee6d4356b
User & Date: dan 2018-01-15 19:00:35
Context
2018-01-16
02:38
Disable the ".archive" command tests in shell8.test if the CLI is compiled without ZLIB support. check-in: ce8bfe6c user: drh tags: trunk
2018-01-15
21:59
Merge the enhancements associated with the first 3.22.0 beta. check-in: c9d2ec51 user: drh tags: apple-osx
19:00
Fix a problem in the zipfile module causing it to generate incorrect checksums. Remove the ability to insert compressed data into a zip archive. check-in: b0b7d036 user: dan tags: trunk
15:49
Fix a zipfile problem with extracting zero length files compressed using deflate. check-in: cf640872 user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/misc/zipfile.c.

   801    801   static int zipfileColumn(
   802    802     sqlite3_vtab_cursor *cur,   /* The cursor */
   803    803     sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
   804    804     int i                       /* Which column to return */
   805    805   ){
   806    806     ZipfileCsr *pCsr = (ZipfileCsr*)cur;
   807    807     int rc = SQLITE_OK;
   808         -  if( i>=3 && sqlite3_vtab_nochange(ctx) ){
   809         -    return SQLITE_OK;
   810         -  }
   811    808     switch( i ){
   812    809       case 0:   /* name */
   813    810         sqlite3_result_text(ctx, pCsr->cds.zFile, -1, SQLITE_TRANSIENT);
   814    811         break;
   815    812       case 1:   /* mode */
   816    813         /* TODO: Whether or not the following is correct surely depends on
   817    814         ** the platform on which the archive was created.  */
................................................................................
   822    819           sqlite3_result_int64(ctx, pCsr->mTime);
   823    820         }else{
   824    821           sqlite3_result_int64(ctx, zipfileMtime(pCsr));
   825    822         }
   826    823         break;
   827    824       }
   828    825       case 3: { /* sz */
   829         -      sqlite3_result_int64(ctx, pCsr->cds.szUncompressed);
          826  +      if( sqlite3_vtab_nochange(ctx)==0 ){
          827  +        sqlite3_result_int64(ctx, pCsr->cds.szUncompressed);
          828  +      }
   830    829         break;
   831    830       }
   832    831       case 4:   /* rawdata */
          832  +      if( sqlite3_vtab_nochange(ctx) ) break;
   833    833       case 5: { /* data */
   834    834         if( i==4 || pCsr->cds.iCompression==0 || pCsr->cds.iCompression==8 ){
   835    835           int sz = pCsr->cds.szCompressed;
   836    836           int szFinal = pCsr->cds.szUncompressed;
   837    837           if( szFinal>0 ){
   838    838             u8 *aBuf = sqlite3_malloc(sz);
   839    839             if( aBuf==0 ){
................................................................................
   868    868         sqlite3_result_int(ctx, pCsr->cds.iCompression);
   869    869         break;
   870    870       case 7:   /* z */
   871    871         sqlite3_result_int64(ctx, pCsr->iId);
   872    872         break;
   873    873     }
   874    874   
   875         -  return SQLITE_OK;
          875  +  return rc;
   876    876   }
   877    877   
   878    878   /*
   879    879   ** Return the rowid for the current row.
   880    880   */
   881    881   static int zipfileRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
   882    882     assert( 0 );
................................................................................
   904    904     int nRead;                      /* Bytes to read from file */
   905    905     i64 iOff;                       /* Offset to read from */
   906    906     int rc;
   907    907   
   908    908     fseek(pFile, 0, SEEK_END);
   909    909     szFile = (i64)ftell(pFile);
   910    910     if( szFile==0 ){
   911         -    return SQLITE_EMPTY;
          911  +    memset(pEOCD, 0, sizeof(ZipfileEOCD));
          912  +    return SQLITE_OK;
   912    913     }
   913    914     nRead = (int)(MIN(szFile, ZIPFILE_BUFFER_SIZE));
   914    915     iOff = szFile - nRead;
   915    916   
   916    917     rc = zipfileReadData(pFile, aRead, nRead, iOff, &pTab->base.zErrMsg);
   917    918     if( rc==SQLITE_OK ){
   918    919       int i;
................................................................................
   982    983       pCsr->pFile = fopen(zFile, "rb");
   983    984       if( pCsr->pFile==0 ){
   984    985         zipfileSetErrmsg(pCsr, "cannot open file: %s", zFile);
   985    986         rc = SQLITE_ERROR;
   986    987       }else{
   987    988         rc = zipfileReadEOCD(pTab, pCsr->pFile, &pCsr->eocd);
   988    989         if( rc==SQLITE_OK ){
   989         -        pCsr->iNextOff = pCsr->eocd.iOffset;
   990         -        rc = zipfileNext(cur);
   991         -      }else if( rc==SQLITE_EMPTY ){
   992         -        rc = SQLITE_OK;
   993         -        pCsr->bEof = 1;
          990  +        if( pCsr->eocd.nEntry==0 ){
          991  +          pCsr->bEof = 1;
          992  +        }else{
          993  +          pCsr->iNextOff = pCsr->eocd.iOffset;
          994  +          rc = zipfileNext(cur);
          995  +        }
   994    996         }
   995    997       }
   996    998     }else{
   997    999       ZipfileEntry e;
   998   1000       memset(&e, 0, sizeof(e));
   999   1001       e.pNext = pTab->pFirstEntry;
  1000   1002       pCsr->pCurrent = &e;
................................................................................
  1063   1065   }
  1064   1066   
  1065   1067   static int zipfileLoadDirectory(ZipfileTab *pTab){
  1066   1068     ZipfileEOCD eocd;
  1067   1069     int rc;
  1068   1070   
  1069   1071     rc = zipfileReadEOCD(pTab, pTab->pWriteFd, &eocd);
  1070         -  if( rc==SQLITE_OK ){
         1072  +  if( rc==SQLITE_OK && eocd.nEntry>0 ){
  1071   1073       int i;
  1072   1074       int iOff = 0;
  1073   1075       u8 *aBuf = sqlite3_malloc(eocd.nSize);
  1074   1076       if( aBuf==0 ){
  1075   1077         rc = SQLITE_NOMEM;
  1076   1078       }else{
  1077   1079         rc = zipfileReadData(
................................................................................
  1108   1110           zipfileAddEntry(pTab, 0, pNew);
  1109   1111         }
  1110   1112   
  1111   1113         iOff += ZIPFILE_CDS_FIXED_SZ+nFile+nExtra+nComment;
  1112   1114       }
  1113   1115   
  1114   1116       sqlite3_free(aBuf);
  1115         -  }else if( rc==SQLITE_EMPTY ){
  1116         -    rc = SQLITE_OK;
  1117   1117     }
  1118   1118   
  1119   1119     return rc;
  1120   1120   }
  1121   1121   
  1122   1122   static ZipfileEntry *zipfileNewEntry(
  1123   1123     ZipfileCDS *pCds,               /* Values for fixed size part of CDS */
................................................................................
  1290   1290     int nData = 0;                  /* Size of pData buffer in bytes */
  1291   1291     int iMethod = 0;                /* Compression method for new entry */
  1292   1292     u8 *pFree = 0;                  /* Free this */
  1293   1293     char *zFree = 0;                /* Also free this */
  1294   1294     ZipfileCDS cds;                 /* New Central Directory Structure entry */
  1295   1295     ZipfileEntry *pOld = 0;
  1296   1296     int bIsDir = 0;
         1297  +  u32 iCrc32 = 0;
  1297   1298   
  1298   1299     assert( pTab->zFile );
  1299   1300     assert( pTab->pWriteFd );
  1300   1301   
  1301   1302     if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
  1302   1303       const char *zDelete = (const char*)sqlite3_value_text(apVal[0]);
  1303   1304       int nDelete = (int)strlen(zDelete);
................................................................................
  1308   1309           break;
  1309   1310         }
  1310   1311         assert( pOld->pNext );
  1311   1312       }
  1312   1313       if( nVal==1 ) return SQLITE_OK;
  1313   1314     }
  1314   1315   
  1315         -  if( sqlite3_value_nochange(apVal[5]) && sqlite3_value_nochange(apVal[6])
  1316         -   && sqlite3_value_nochange(apVal[7]) && sqlite3_value_nochange(apVal[8])
         1316  +  /* Check that "sz" and "rawdata" are both NULL: */
         1317  +  if( sqlite3_value_type(apVal[5])!=SQLITE_NULL
         1318  +   || sqlite3_value_type(apVal[6])!=SQLITE_NULL
  1317   1319     ){
  1318         -    /* Reuse the data from the existing entry. */
  1319         -    FILE *pFile = pTab->pWriteFd;
  1320         -    zipfileReadCDS(pOld->aCdsEntry, &cds);
         1320  +    rc = SQLITE_CONSTRAINT;
         1321  +  }
  1321   1322   
  1322         -    bIsDir = ((cds.iExternalAttr>>16) & S_IFDIR) ? 1 : 0;
  1323         -    sz = cds.szUncompressed;
  1324         -    iMethod = cds.iCompression;
  1325         -    if( sz>0 ){
  1326         -      char **pzErr = &pTab->base.zErrMsg;
  1327         -      ZipfileLFH lfh;
  1328         -      rc = zipfileReadLFH(pFile, cds.iOffset, pTab->aBuffer, &lfh, pzErr);
  1329         -      if( rc==SQLITE_OK ){
  1330         -        nData = lfh.szCompressed;
  1331         -        pData = pFree = sqlite3_malloc(nData);
  1332         -        if( pFree==NULL ){
  1333         -          rc = SQLITE_NOMEM;
  1334         -        }else{
  1335         -          i64 iRead = cds.iOffset + ZIPFILE_LFH_FIXED_SZ + lfh.nFile+lfh.nExtra;
  1336         -          rc = zipfileReadData(pFile, pFree, nData, iRead, pzErr);
  1337         -        }
  1338         -      }
  1339         -    }
  1340         -  }else{
  1341         -    int mNull;
  1342         -    mNull = (sqlite3_value_type(apVal[5])==SQLITE_NULL ? 0x0 : 0x8)  /* sz */
  1343         -      + (sqlite3_value_type(apVal[6])==SQLITE_NULL ? 0x0 : 0x4)  /* rawdata */
  1344         -      + (sqlite3_value_type(apVal[7])==SQLITE_NULL ? 0x0 : 0x2)  /* data */
  1345         -      + (sqlite3_value_type(apVal[8])==SQLITE_NULL ? 0x0 : 0x1); /* method */
  1346         -    if( mNull==0x00 ){     
  1347         -      /* All four are NULL - this must be a directory */
         1323  +  if( rc==SQLITE_OK ){
         1324  +    if( sqlite3_value_type(apVal[7])==SQLITE_NULL ){
         1325  +      /* data=NULL. A directory */
  1348   1326         bIsDir = 1;
  1349         -    }
  1350         -    else if( mNull==0x2 || mNull==0x3 ){
         1327  +    }else{
  1351   1328         /* Value specified for "data", and possibly "method". This must be
  1352   1329         ** a regular file or a symlink. */
  1353   1330         const u8 *aIn = sqlite3_value_blob(apVal[7]);
  1354   1331         int nIn = sqlite3_value_bytes(apVal[7]);
  1355   1332         int bAuto = sqlite3_value_type(apVal[8])==SQLITE_NULL;
  1356   1333   
  1357   1334         iMethod = sqlite3_value_int(apVal[8]);
................................................................................
  1366   1343           if( rc==SQLITE_OK ){
  1367   1344             if( iMethod || nCmp<nIn ){
  1368   1345               iMethod = 8;
  1369   1346               pData = pFree;
  1370   1347               nData = nCmp;
  1371   1348             }
  1372   1349           }
         1350  +        iCrc32 = crc32(0, aIn, nIn);
  1373   1351         }
  1374   1352       }
  1375         -    else if( mNull==0x0D ){
  1376         -      /* Values specified for "sz", "rawdata" and "method". In other words,
  1377         -      ** pre-compressed data is being inserted.  */
  1378         -      pData = sqlite3_value_blob(apVal[6]);
  1379         -      nData = sqlite3_value_bytes(apVal[6]);
  1380         -      sz = sqlite3_value_int(apVal[5]);
  1381         -      iMethod = sqlite3_value_int(apVal[8]);
  1382         -      if( iMethod<0 || iMethod>65535 ){
  1383         -        pTab->base.zErrMsg = sqlite3_mprintf(
  1384         -            "zipfile: invalid compression method: %d", iMethod
  1385         -            );
  1386         -        rc = SQLITE_ERROR;
  1387         -      }
  1388         -    }
  1389         -    else{
  1390         -      rc = SQLITE_CONSTRAINT;
  1391         -    }
  1392   1353     }
  1393   1354   
  1394   1355     if( rc==SQLITE_OK ){
  1395   1356       rc = zipfileGetMode(pTab, apVal[3], 
  1396   1357           (bIsDir ? (S_IFDIR + 0755) : (S_IFREG + 0644)), &mode
  1397   1358       );
  1398   1359       if( rc==SQLITE_OK && (bIsDir == ((mode & S_IFDIR)==0)) ){
................................................................................
  1441   1402       /* Create the new CDS record. */
  1442   1403       memset(&cds, 0, sizeof(cds));
  1443   1404       cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY;
  1444   1405       cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED;
  1445   1406       cds.flags = ZIPFILE_NEWENTRY_FLAGS;
  1446   1407       cds.iCompression = (u16)iMethod;
  1447   1408       zipfileMtimeToDos(&cds, (u32)mTime);
  1448         -    cds.crc32 = crc32(0, pData, nData);
         1409  +    cds.crc32 = iCrc32;
  1449   1410       cds.szCompressed = nData;
  1450   1411       cds.szUncompressed = (u32)sz;
  1451   1412       cds.iExternalAttr = (mode<<16);
  1452   1413       cds.iOffset = (u32)pTab->szCurrent;
  1453   1414       pNew = zipfileNewEntry(&cds, zPath, nPath, (u32)mTime);
  1454   1415       if( pNew==0 ){
  1455   1416         rc = SQLITE_NOMEM;

Changes to test/zipfile.test.

    32     32     2 mtime {} 0 {} 0 
    33     33     3 sz {} 0 {} 0 
    34     34     4 rawdata {} 0 {} 0
    35     35     5 data {} 0 {} 0
    36     36     6 method {} 0 {} 0
    37     37   }
    38     38   
    39         -do_execsql_test 1.1.1 {
           39  +do_catchsql_test 1.1.0.1 {
    40     40     INSERT INTO zz(name, mode, mtime, sz, rawdata, method) 
    41     41     VALUES('f.txt', '-rw-r--r--', 1000000000, 5, 'abcde', 0);
    42         -}
    43         -do_execsql_test 1.1.2 {
           42  +} {1 {constraint failed}}
           43  +do_catchsql_test 1.1.0.1 {
    44     44     INSERT INTO zz(name, mtime, sz, rawdata, method) 
    45     45     VALUES('g.txt', 1000000002, 5, '12345', 0);
           46  +} {1 {constraint failed}}
           47  +
           48  +do_execsql_test 1.1.1 {
           49  +  INSERT INTO zz(name, mode, mtime, data, method) 
           50  +  VALUES('f.txt', '-rw-r--r--', 1000000000, 'abcde', 0);
           51  +}
           52  +do_execsql_test 1.1.2 {
           53  +  INSERT INTO zz(name, mode, mtime, data, method) 
           54  +  VALUES('g.txt', NULL, 1000000002, '12345', 0);
    46     55   }
    47     56   
    48     57   do_execsql_test 1.2 {
    49     58     SELECT name, mtime, data FROM zipfile('test.zip')
    50     59   } {
    51     60     f.txt 1000000000 abcde 
    52     61     g.txt 1000000002 12345