]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix a zipfile problem with extracting zero length files compressed using
authordan <dan@noemail.net>
Mon, 15 Jan 2018 15:49:46 +0000 (15:49 +0000)
committerdan <dan@noemail.net>
Mon, 15 Jan 2018 15:49:46 +0000 (15:49 +0000)
deflate.

FossilOrigin-Name: cf64087224aff1a2fe169d23996d9e5ed8d86459c655eb5d0bace0466a557ec6

ext/misc/zipfile.c
manifest
manifest.uuid

index 63828e3c090747345c70e95df574930f21505f56..27f55f6c14735630ea6c34ff2a426acb75b89470 100644 (file)
@@ -64,7 +64,7 @@ static const char ZIPFILE_SCHEMA[] =
     "rawdata,"           /* 4: Raw data */
     "data,"              /* 5: Uncompressed data */
     "method,"            /* 6: Compression method (integer) */
-    "file HIDDEN"        /* 7: Name of zip file */
+    "z HIDDEN"           /* 7: Name of zip file */
   ") WITHOUT ROWID;";
 
 #define ZIPFILE_F_COLUMN_IDX 7    /* Index of column "file" in the above */
@@ -235,6 +235,7 @@ struct ZipfileEntry {
 typedef struct ZipfileCsr ZipfileCsr;
 struct ZipfileCsr {
   sqlite3_vtab_cursor base;  /* Base class - must be first */
+  i64 iId;                   /* Cursor ID */
   int bEof;                  /* True when at EOF */
 
   /* Used outside of write transactions */
@@ -264,8 +265,10 @@ struct ZipfileTab {
   char *zFile;               /* Zip file this table accesses (may be NULL) */
   u8 *aBuffer;               /* Temporary buffer used for various tasks */
 
-  /* The following are used by write transactions only */
   ZipfileCsr *pCsrList;      /* List of cursors */
+  i64 iNextCsrid;
+
+  /* The following are used by write transactions only */
   ZipfileEntry *pFirstEntry; /* Linked list of all files (if pWriteFd!=0) */
   ZipfileEntry *pLastEntry;  /* Last element in pFirstEntry list */
   FILE *pWriteFd;            /* File handle open on zip archive */
@@ -344,6 +347,7 @@ static int zipfileDisconnect(sqlite3_vtab *pVtab){
 ** Constructor for a new ZipfileCsr object.
 */
 static int zipfileOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCsr){
+  ZipfileTab *pTab = (ZipfileTab*)p;
   ZipfileCsr *pCsr;
   pCsr = sqlite3_malloc(sizeof(*pCsr));
   *ppCsr = (sqlite3_vtab_cursor*)pCsr;
@@ -351,6 +355,9 @@ static int zipfileOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCsr){
     return SQLITE_NOMEM;
   }
   memset(pCsr, 0, sizeof(*pCsr));
+  pCsr->iId = ++pTab->iNextCsrid;
+  pCsr->pCsrNext = pTab->pCsrList;
+  pTab->pCsrList = pCsr;
   return SQLITE_OK;
 }
 
@@ -359,14 +366,6 @@ static int zipfileOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCsr){
 ** by zipfileOpen().
 */
 static void zipfileResetCursor(ZipfileCsr *pCsr){
-  ZipfileTab *pTab = (ZipfileTab*)(pCsr->base.pVtab);
-  ZipfileCsr **pp;
-
-  /* Remove this cursor from the ZipfileTab.pCsrList list. */
-  for(pp=&pTab->pCsrList; *pp; pp=&((*pp)->pCsrNext)){
-    if( *pp==pCsr ) *pp = pCsr->pCsrNext;
-  }
-
   sqlite3_free(pCsr->cds.zFile);
   pCsr->cds.zFile = 0;
   pCsr->bEof = 0;
@@ -381,7 +380,18 @@ static void zipfileResetCursor(ZipfileCsr *pCsr){
 */
 static int zipfileClose(sqlite3_vtab_cursor *cur){
   ZipfileCsr *pCsr = (ZipfileCsr*)cur;
+  ZipfileTab *pTab = (ZipfileTab*)(pCsr->base.pVtab);
+  ZipfileCsr **pp;
   zipfileResetCursor(pCsr);
+
+  /* Remove this cursor from the ZipfileTab.pCsrList list. */
+  for(pp=&pTab->pCsrList; *pp; pp=&((*pp)->pCsrNext)){
+    if( *pp==pCsr ){ 
+      *pp = pCsr->pCsrNext;
+      break;
+    }
+  }
+
   sqlite3_free(pCsr);
   return SQLITE_OK;
 }
@@ -823,7 +833,8 @@ static int zipfileColumn(
     case 5: { /* data */
       if( i==4 || pCsr->cds.iCompression==0 || pCsr->cds.iCompression==8 ){
         int sz = pCsr->cds.szCompressed;
-        if( sz>0 ){
+        int szFinal = pCsr->cds.szUncompressed;
+        if( szFinal>0 ){
           u8 *aBuf = sqlite3_malloc(sz);
           if( aBuf==0 ){
             rc = SQLITE_NOMEM;
@@ -835,12 +846,20 @@ static int zipfileColumn(
           }
           if( rc==SQLITE_OK ){
             if( i==5 && pCsr->cds.iCompression ){
-              zipfileInflate(ctx, aBuf, sz, pCsr->cds.szUncompressed);
+              zipfileInflate(ctx, aBuf, sz, szFinal);
             }else{
               sqlite3_result_blob(ctx, aBuf, sz, SQLITE_TRANSIENT);
             }
             sqlite3_free(aBuf);
           }
+        }else{
+          /* Figure out if this is a directory or a zero-sized file. Consider
+          ** it to be a directory either if the mode suggests so, or if
+          ** the final character in the name is '/'.  */
+          u32 mode = pCsr->cds.iExternalAttr >> 16;
+          if( !(mode & S_IFDIR) && pCsr->cds.zFile[pCsr->cds.nFile-1]!='/' ){
+            sqlite3_result_blob(ctx, "", 0, SQLITE_STATIC);
+          }
         }
       }
       break;
@@ -848,6 +867,9 @@ static int zipfileColumn(
     case 6:   /* method */
       sqlite3_result_int(ctx, pCsr->cds.iCompression);
       break;
+    case 7:   /* z */
+      sqlite3_result_int64(ctx, pCsr->iId);
+      break;
   }
 
   return SQLITE_OK;
@@ -1553,6 +1575,84 @@ static int zipfileRollback(sqlite3_vtab *pVtab){
   return zipfileCommit(pVtab);
 }
 
+static ZipfileCsr *zipfileFindCursor(ZipfileTab *pTab, i64 iId){
+  ZipfileCsr *pCsr;
+  for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){
+    if( iId==pCsr->iId ) break;
+  }
+  return pCsr;
+}
+
+static void zipfileFunctionCds(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  ZipfileCsr *pCsr;
+  ZipfileTab *pTab = (ZipfileTab*)sqlite3_user_data(context);
+  assert( argc>0 );
+
+  pCsr = zipfileFindCursor(pTab, sqlite3_value_int64(argv[0]));
+  if( pCsr ){
+    ZipfileCDS *p = &pCsr->cds;
+    char *zRes = sqlite3_mprintf("{"
+        "\"version-made-by\" : %u, "
+        "\"version-to-extract\" : %u, "
+        "\"flags\" : %u, "
+        "\"compression\" : %u, "
+        "\"time\" : %u, "
+        "\"date\" : %u, "
+        "\"crc32\" : %u, "
+        "\"compressed-size\" : %u, "
+        "\"uncompressed-size\" : %u, "
+        "\"file-name-length\" : %u, "
+        "\"extra-field-length\" : %u, "
+        "\"file-comment-length\" : %u, "
+        "\"disk-number-start\" : %u, "
+        "\"internal-attr\" : %u, "
+        "\"external-attr\" : %u, "
+        "\"offset\" : %u }",
+        (u32)p->iVersionMadeBy, (u32)p->iVersionExtract,
+        (u32)p->flags, (u32)p->iCompression,
+        (u32)p->mTime, (u32)p->mDate,
+        (u32)p->crc32, (u32)p->szCompressed,
+        (u32)p->szUncompressed, (u32)p->nFile,
+        (u32)p->nExtra, (u32)p->nComment,
+        (u32)p->iDiskStart, (u32)p->iInternalAttr,
+        (u32)p->iExternalAttr, (u32)p->iOffset
+    );
+
+    if( zRes==0 ){
+      sqlite3_result_error_nomem(context);
+    }else{
+      sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
+      sqlite3_free(zRes);
+    }
+  }
+}
+
+
+/*
+** xFindFunction method.
+*/
+static int zipfileFindFunction(
+  sqlite3_vtab *pVtab,            /* Virtual table handle */
+  int nArg,                       /* Number of SQL function arguments */
+  const char *zName,              /* Name of SQL function */
+  void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */
+  void **ppArg                    /* OUT: User data for *pxFunc */
+){
+  if( nArg>0 ){
+    if( sqlite3_stricmp("zipfile_cds", zName)==0 ){
+      *pxFunc = zipfileFunctionCds;
+      *ppArg = (void*)pVtab;
+      return 1;
+    }
+  }
+
+  return 0;
+}
+
 /*
 ** Register the "zipfile" virtual table.
 */
@@ -1576,11 +1676,14 @@ static int zipfileRegister(sqlite3 *db){
     0,                         /* xSync */
     zipfileCommit,             /* xCommit */
     zipfileRollback,           /* xRollback */
-    0,                         /* xFindMethod */
+    zipfileFindFunction,       /* xFindMethod */
     0,                         /* xRename */
   };
 
   int rc = sqlite3_create_module(db, "zipfile"  , &zipfileModule, 0);
+  if( rc==SQLITE_OK ){
+    rc = sqlite3_overload_function(db, "zipfile_cds", -1);
+  }
   return rc;
 }
 #else         /* SQLITE_OMIT_VIRTUALTABLE */
index 687bdf64d061a1aac046b12c22141a5770aef5e2..f7654f5e02014b5e691342d6a2c84063b6664e3f 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\san\serror\sin\sthe\ssetDeviceCharacteristics()\sprocedure\sfor\sthe\n(unsupported)\sQNX\scode\sin\sos_unix.c.
-D 2018-01-15T14:32:37.594
+C Fix\sa\szipfile\sproblem\swith\sextracting\szero\slength\sfiles\scompressed\susing\ndeflate.
+D 2018-01-15T15:49:46.517
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F Makefile.in 38f84f301cbef443b2d269f67a74b8cc536469831f70df7c3e912acc04932cc2
@@ -303,7 +303,7 @@ F ext/misc/vfsstat.c bf10ef0bc51e1ad6756629e1edb142f7a8db1178
 F ext/misc/vtablog.c 31d0d8f4406795679dcd3a67917c213d3a2a5fb3ea5de35f6e773491ed7e13c9
 F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
 F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
-F ext/misc/zipfile.c 7001d7ca733d34a8b4fbacf7f8d322f3b2bf402f41052a021b5eda8227f0f5d4
+F ext/misc/zipfile.c 46171a19439d0c76acf48770e736c281536f160d3a5a96a0511e34402e262fac
 F ext/rbu/rbu.c ea7d1b7eb44c123a2a619332e19fe5313500705c4a58aaa1887905c0d83ffc2e
 F ext/rbu/rbu1.test 43836fac8c7179a358eaf38a8a1ef3d6e6285842
 F ext/rbu/rbu10.test 1846519a438697f45e9dcb246908af81b551c29e1078d0304fae83f1fed7e9ee
@@ -1699,7 +1699,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P a4fa0581ba7cfd45fabe0198f55b3c2c8ee3ecfd2825aeed91116f44e77d760b
-R 755347b860dbdbaa8de782672cfa2550
-U drh
-Z bf44e658c85afb034dcb761e50e86217
+P 8151913a3987f4dd2d6efee046727f5fa9b6f11d5d3867ea8f512c03a212ac2b
+R d9864f9f3d3219c31b427d2f3aa9a193
+U dan
+Z 4b1456c73d542678caf828eee79b5bff
index 3e03feb0d3b6e08ce634b3c2db3675964d6b7f52..19ee4478a0fbd5a0fbf2a993c744a867355fed31 100644 (file)
@@ -1 +1 @@
-8151913a3987f4dd2d6efee046727f5fa9b6f11d5d3867ea8f512c03a212ac2b
\ No newline at end of file
+cf64087224aff1a2fe169d23996d9e5ed8d86459c655eb5d0bace0466a557ec6
\ No newline at end of file