@@ -54,27 +54,23 @@ namespace QuickView {
5454 void (*progressCb)(float progress, void * userData),
5555 void* userData
5656 ) {
57- char logBuf[512 ];
58- sprintf_s (logBuf, " [QVX-Extract] ExtractZipToDirectory: opening '%ls' -> '%ls'\n " , zipPath.c_str (), destDir.c_str ());
59- OutputDebugStringA (logBuf);
60-
6157 ZipArchive zip (zipPath);
6258 if (!zip.IsValid ()) {
63- sprintf_s (logBuf, " [QVX-Extract] Failed: zip.IsValid() is false for '%ls'\n " , zipPath.c_str ());
64- OutputDebugStringA (logBuf);
6559 return false ;
6660 }
6761
62+ constexpr size_t kMaxEntries = 4096 ;
63+ constexpr uint64_t kMaxEntryBytes = 512ull * 1024 * 1024 ;
64+ constexpr uint64_t kMaxTotalBytes = 1024ull * 1024 * 1024 ;
6865 size_t totalEntries = zip.GetEntryCount ();
69- sprintf_s (logBuf, " [QVX-Extract] Zip has %zu entries\n " , totalEntries);
70- OutputDebugStringA (logBuf);
71-
66+ if (totalEntries > kMaxEntries ) return false ;
7267 if (totalEntries == 0 ) return true ;
7368
7469 EnsureParentDirectory (destDir + L" \\ dummy.tmp" );
7570
7671 ::std::vector<uint8_t > buffer;
7772
73+ uint64_t totalUncompressed = 0 ;
7874 for (size_t i = 0 ; i < totalEntries; ++i) {
7975 ::std::wstring relName = zip.GetEntryName (i);
8076 if (relName.empty ()) continue ;
@@ -84,7 +80,8 @@ namespace QuickView {
8480 }
8581
8682 // Security: Prevent Directory Traversal
87- if (relName.find (L" ..\\ " ) != ::std::wstring::npos || relName.find (L" \\ .." ) != ::std::wstring::npos) {
83+ if (relName.front () == L' \\ ' || relName.find (L' :' ) != ::std::wstring::npos ||
84+ relName.find (L" ..\\ " ) != ::std::wstring::npos || relName == L" .." || relName.find (L" \\ .." ) != ::std::wstring::npos) {
8885 continue ;
8986 }
9087
@@ -96,17 +93,15 @@ namespace QuickView {
9693 EnsureParentDirectory (outPath);
9794
9895 const ArchiveEntry& entry = zip.GetEntry (i);
99- sprintf_s (logBuf, " [QVX-Extract] Entry [%zu]: '%ls', uncompSize=%u, method=%u \n " , i, relName. c_str (), entry.uncompSize , entry. method ) ;
100- OutputDebugStringA (logBuf) ;
96+ if (entry. uncompSize > kMaxEntryBytes || totalUncompressed > kMaxTotalBytes - entry.uncompSize ) return false ;
97+ totalUncompressed += entry. uncompSize ;
10198
10299 if (buffer.size () < entry.uncompSize ) {
103100 buffer.resize (entry.uncompSize );
104101 }
105102
106103 size_t extractedSize = zip.ExtractEntry (i, buffer.data (), buffer.size ());
107104 if (extractedSize != entry.uncompSize ) {
108- sprintf_s (logBuf, " [QVX-Extract] ExtractEntry failed for '%ls' (got %zu, expected %u)\n " , relName.c_str (), extractedSize, entry.uncompSize );
109- OutputDebugStringA (logBuf);
110105 return false ;
111106 }
112107
@@ -116,8 +111,6 @@ namespace QuickView {
116111 DeleteFileW (outPath.c_str ());
117112 hFile = CreateFileW (outPath.c_str (), GENERIC_WRITE , FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE , nullptr , CREATE_ALWAYS , FILE_ATTRIBUTE_NORMAL , nullptr );
118113 if (hFile == INVALID_HANDLE_VALUE ) {
119- sprintf_s (logBuf, " [QVX-Extract] CreateFileW failed for '%ls' (err=%lu)\n " , outPath.c_str (), GetLastError ());
120- OutputDebugStringA (logBuf);
121114 return false ;
122115 }
123116 }
@@ -130,8 +123,6 @@ namespace QuickView {
130123 CloseHandle (hFile);
131124
132125 if (!writeOk || written != entry.uncompSize ) {
133- sprintf_s (logBuf, " [QVX-Extract] WriteFile failed for '%ls' (written=%lu, expected=%u, err=%lu)\n " , outPath.c_str (), written, entry.uncompSize , GetLastError ());
134- OutputDebugStringA (logBuf);
135126 DeleteFileW (outPath.c_str ());
136127 return false ;
137128 }
@@ -142,8 +133,6 @@ namespace QuickView {
142133 }
143134 }
144135
145- sprintf_s (logBuf, " [QVX-Extract] ExtractZipToDirectory completed successfully for '%ls'\n " , zipPath.c_str ());
146- OutputDebugStringA (logBuf);
147136 return true ;
148137 }
149138
0 commit comments