From: dan Date: Mon, 15 Jan 2018 15:49:46 +0000 (+0000) Subject: Fix a zipfile problem with extracting zero length files compressed using X-Git-Tag: version-3.22.0~32 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=89fa74694149ca5c4f57338f6f161737f991bedc;p=thirdparty%2Fsqlite.git Fix a zipfile problem with extracting zero length files compressed using deflate. FossilOrigin-Name: cf64087224aff1a2fe169d23996d9e5ed8d86459c655eb5d0bace0466a557ec6 --- diff --git a/ext/misc/zipfile.c b/ext/misc/zipfile.c index 63828e3c09..27f55f6c14 100644 --- a/ext/misc/zipfile.c +++ b/ext/misc/zipfile.c @@ -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 */ diff --git a/manifest b/manifest index 687bdf64d0..f7654f5e02 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index 3e03feb0d3..19ee4478a0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8151913a3987f4dd2d6efee046727f5fa9b6f11d5d3867ea8f512c03a212ac2b \ No newline at end of file +cf64087224aff1a2fe169d23996d9e5ed8d86459c655eb5d0bace0466a557ec6 \ No newline at end of file