50 auto fileType = (
entry.externalFileAttributes >> 28) & 0xf;
51 entry.isSymbolicLink = (fileType == 0xA);
58 auto year = (
int) (1980 + (date >> 9));
59 auto month = (
int) (((date >> 5) & 15) - 1);
60 auto day = (
int) (date & 31);
61 auto hours = (
int) time >> 11;
62 auto minutes = (
int) ((time >> 5) & 63);
63 auto seconds = (
int) ((time & 31) << 1);
65 return { year,
month, day, hours, minutes, seconds };
78 in.setPosition (
in.getTotalLength());
79 auto pos =
in.getPosition();
80 auto lowestPos =
jmax ((
int64) 0, pos - 1048576);
83 while (pos > lowestPos)
85 in.setPosition (pos - 22);
86 pos =
in.getPosition();
87 memcpy (buffer + 22, buffer, 4);
89 if (
in.read (buffer, 22) != 22)
92 for (
int i = 0;
i < 22; ++
i)
96 in.setPosition (pos +
i);
103 in.setPosition (offset);
108 if (
in.readInt() != 0x02014b50)
110 in.setPosition (offset - 4);
112 if (
in.readInt() == 0x02014b50)
127 jassert (root ==
f ||
f.isAChildOf (root));
129 for (
auto p =
f;
p != root;
p =
p.getParentDirectory())
131 if (
p.isSymbolicLink())
148 streamToDelete.reset (file.inputSource->createInputStream());
149 inputStream = streamToDelete.get();
154 zf.streamCounter.numOpenStreams++;
165 headerSize = 30 + ByteOrder::littleEndianShort (buffer + 26)
166 + ByteOrder::littleEndianShort (buffer + 28);
174 file.streamCounter.numOpenStreams--;
183 int read (
void* buffer,
int howMany)
override
243 if (deleteStreamWhenDestroyed)
270ZipFile::OpenStreamCounter::~OpenStreamCounter()
289 if (
auto* zei =
entries[index])
290 return &(zei->entry);
299 auto& entryFilename =
entries.getUnchecked (
i)->entry.filename;
301 if (ignoreCase ? entryFilename.equalsIgnoreCase (fileName)
302 : entryFilename == fileName)
318 if (
auto* zei =
entries[index])
322 if (zei->isCompressed)
326 zei->entry.uncompressedSize);
339 if (&
entries.getUnchecked (
i)->entry == &entry)
354 std::unique_ptr<InputStream> toDelete;
368 if (centralDirectoryPos >= 0 && centralDirectoryPos < in->getTotalLength())
370 auto size = (size_t) (
in->getTotalLength() - centralDirectoryPos);
372 in->setPosition (centralDirectoryPos);
375 if (
in->readIntoMemoryBlock (headerData, (ssize_t)
size) ==
size)
379 for (
int i = 0;
i < numEntries; ++
i)
384 auto* buffer =
static_cast<const char*
> (headerData.
getData()) + pos;
387 if (pos + 46 + fileNameLen >
size)
392 pos += 46u + fileNameLen
402 const bool shouldOverwriteFiles)
425 auto* zei =
entries.getUnchecked (index);
428 auto entryPath = zei->entry.filename;
430 auto entryPath = zei->entry.filename.replaceCharacter (
'\\',
'/');
433 if (entryPath.isEmpty())
436 auto targetFile = targetDirectory.
getChildFile (entryPath);
438 if (! targetFile.isAChildOf (targetDirectory))
439 return Result::fail (
"Entry " + entryPath +
" is outside the target directory");
441 if (entryPath.endsWithChar (
'/') || entryPath.endsWithChar (
'\\'))
442 return targetFile.createDirectory();
447 return Result::fail (
"Failed to open the zip file for reading");
449 if (targetFile.exists())
454 if (! targetFile.deleteFile())
455 return Result::fail (
"Failed to write to target file: " + targetFile.getFullPathName());
459 return Result::fail (
"Parent directory leads through symlink for target file: " + targetFile.getFullPathName());
461 if (! targetFile.getParentDirectory().createDirectory())
462 return Result::fail (
"Failed to create target folder: " + targetFile.getParentDirectory().getFullPathName());
464 if (zei->entry.isSymbolicLink)
466 String originalFilePath (
in->readEntireStreamAsString()
470 return Result::fail (
"Failed to create symbolic link: " + originalFilePath);
476 if (
out.failedToOpen())
477 return Result::fail (
"Failed to write to target file: " + targetFile.getFullPathName());
482 targetFile.setCreationTime (zei->entry.fileTime);
483 targetFile.setLastModificationTime (zei->entry.fileTime);
484 targetFile.setLastAccessTime (zei->entry.fileTime);
510 compressedData << relativePath;
563 target.
writeShort ((
short) (
t.getSeconds() + (
t.getMinutes() << 5) + (
t.getHours() << 11)));
564 target.
writeShort ((
short) (
t.getDayOfMonth() + ((
t.getMonth() + 1) << 5) + ((
t.getYear() - 1980) << 9)));
579 const int bufferSize = 4096;
582 while (!
stream->isExhausted())
584 auto bytesRead =
stream->read (buffer, bufferSize);
589 checksum = zlibNamespace::crc32 (
checksum, buffer, (
unsigned int) bytesRead);
590 target.
write (buffer, (
size_t) bytesRead);
622 file.getLastModificationTime()));
629 items.add (
new Item ({}, stream, compression, path, time));
636 for (
int i = 0;
i <
items.size(); ++
i)
638 if (progress !=
nullptr)
639 *progress = (
i + 0.5) /
items.size();
641 if (!
items.getUnchecked (
i)->writeData (target, fileStart))
647 for (
auto* item :
items)
648 if (! item->writeDirectoryEntry (target))
658 target.
writeInt ((
int) (directoryEnd - directoryStart));
659 target.
writeInt ((
int) (directoryStart - fileStart));
662 if (progress !=
nullptr)
684 for (
auto& entryName : entryNames)
700 void runZipSlipTest()
702 const std::map<String, bool> testCases = { {
"a",
true },
710 {
"../../g/h",
false },
713 {
"m/n/../../",
false },
714 {
"o/p/../../../",
false } };
716 StringArray entryNames;
718 for (
const auto& testCase : testCases)
719 entryNames.
add (testCase.first);
721 TemporaryFile tmpDir;
722 tmpDir.getFile().createDirectory();
723 auto data = createZipMemoryBlock (entryNames);
724 MemoryInputStream mi (
data,
false);
727 for (
int i = 0;
i < zip.getNumEntries(); ++
i)
729 const auto result = zip.uncompressEntry (
i, tmpDir.getFile());
730 const auto caseIt = testCases.find (zip.getEntry (
i)->filename);
732 if (caseIt != testCases.end())
734 expect (
result.wasOk() == caseIt->second,
735 zip.getEntry (
i)->filename +
" was unexpectedly " + (
result.wasOk() ?
"OK" :
"not OK"));
744 void runTest()
override
748 StringArray entryNames {
"first",
"second",
"third" };
749 auto data = createZipMemoryBlock (entryNames);
750 MemoryInputStream mi (
data,
false);
753 expectEquals (zip.getNumEntries(), entryNames.
size());
755 for (
auto& entryName : entryNames)
757 auto* entry = zip.getEntry (entryName);
758 std::unique_ptr<InputStream> input (zip.createStreamForEntry (*entry));
759 expectEquals (input->readEntireStreamAsString(), entryName);
762 beginTest (
"ZipSlip");
767static ZIPTests zipTests;
Type jmax(const Type a, const Type b)
Definition MathsFunctions.h:48
#define noexcept
Definition DistrhoDefines.h:72
static uint32 littleEndianInt(const void *bytes) noexcept
Definition ByteOrder.h:236
static uint16 littleEndianShort(const void *bytes) noexcept
Definition ByteOrder.h:238
Definition MemoryBlock.h:39
Definition MemoryOutputStream.h:42
static Result ok() noexcept
Definition Result.h:68
static Result fail(const std::string &errorMessage) noexcept
Definition Result.cpp:58
bool add(const String &stringToAdd)
Definition StringArray.cpp:108
int size() const noexcept
Definition StringArray.h:97
static String fromUTF8(const char *utf8buffer, int bufferSizeBytes=-1)
Definition String.cpp:1961
static constexpr uint32 littleEndianInt(const void *bytes) noexcept
Definition juce_ByteOrder.h:203
Definition juce_File.h:45
File getChildFile(StringRef relativeOrAbsolutePath) const
Definition juce_File.cpp:412
bool createSymbolicLink(const File &linkFileToCreate, bool overwriteExisting) const
Definition juce_File.cpp:995
File getParentDirectory() const
Definition juce_File.cpp:358
static juce_wchar getSeparatorChar()
Definition juce_posix_SharedCode.h:113
Definition juce_FileOutputStream.h:35
Definition juce_GZIPCompressorOutputStream.h:39
@ windowBitsRaw
Definition juce_GZIPCompressorOutputStream.h:94
Definition juce_HashMap.h:104
ValueType & getReference(KeyTypeParameter keyToLookFor)
Definition juce_HashMap.h:185
Definition juce_HeapBlock.h:87
Definition juce_MemoryBlock.h:33
void * getData() noexcept
Definition juce_MemoryBlock.h:91
Definition juce_MemoryOutputStream.h:36
size_t getDataSize() const noexcept
Definition juce_MemoryOutputStream.h:80
Definition juce_OutputStream.h:38
virtual bool write(const void *dataToWrite, size_t numberOfBytes)=0
virtual int64 getPosition()=0
virtual bool writeShort(short value)
Definition juce_OutputStream.cpp:97
virtual bool writeInt(int value)
Definition juce_OutputStream.cpp:109
Definition juce_Result.h:57
Definition juce_StringArray.h:35
Definition juce_String.h:53
bool isEmpty() const noexcept
Definition juce_String.h:310
bool isNotEmpty() const noexcept
Definition juce_String.h:316
Definition juce_Time.h:37
static Time JUCE_CALLTYPE getCurrentTime() noexcept
Definition juce_Time.cpp:233
Definition juce_UnitTest.h:70
Definition juce_ZipFile.h:209
Builder()
Definition juce_ZipFile.cpp:615
void addEntry(InputStream *streamToRead, int compressionLevel, const String &storedPathName, Time fileModificationTime)
Definition juce_ZipFile.cpp:625
bool writeToStream(OutputStream &target, double *progress) const
Definition juce_ZipFile.cpp:632
void addFile(const File &fileToAdd, int compressionLevel, const String &storedPathName=String())
Definition juce_ZipFile.cpp:618
OwnedArray< Item > items
Definition juce_ZipFile.h:252
~Builder()
Definition juce_ZipFile.cpp:616
Result uncompressTo(const File &targetDirectory, bool shouldOverwriteFiles=true)
Definition juce_ZipFile.cpp:401
InputStream * createStreamForEntry(int index)
Definition juce_ZipFile.cpp:314
const ZipEntry * getEntry(int index) const noexcept
Definition juce_ZipFile.cpp:287
~ZipFile()
Definition juce_ZipFile.cpp:264
int getNumEntries() const noexcept
Definition juce_ZipFile.cpp:282
std::unique_ptr< InputSource > inputSource
Definition juce_ZipFile.h:266
InputStream * inputStream
Definition juce_ZipFile.h:264
OwnedArray< ZipEntryHolder > entries
Definition juce_ZipFile.h:262
void init()
Definition juce_ZipFile.cpp:352
ZipFile(const File &file)
Definition juce_ZipFile.cpp:254
OverwriteFiles
Definition juce_ZipFile.h:182
@ no
Definition juce_ZipFile.h:182
@ yes
Definition juce_ZipFile.h:182
Result uncompressEntry(int index, const File &targetDirectory, bool shouldOverwriteFiles=true)
Definition juce_ZipFile.cpp:415
int getIndexOfFileName(const String &fileName, bool ignoreCase=false) const noexcept
Definition juce_ZipFile.cpp:295
void sortEntriesByFilename()
Definition juce_ZipFile.cpp:345
std::unique_ptr< InputStream > streamToDelete
Definition juce_ZipFile.h:265
FollowSymlinks
Definition juce_ZipFile.h:183
@ no
Definition juce_ZipFile.h:183
struct huft * t
Definition inflate.c:943
register unsigned i
Definition inflate.c:1575
unsigned s
Definition inflate.c:1555
unsigned f
Definition inflate.c:1572
JSAMPIMAGE data
Definition jpeglib.h:945
float in
Definition lilv_test.c:1460
float out
Definition lilv_test.c:1461
unsigned char uint8_t
Definition mid.cpp:98
Definition juce_UnitTestCategories.h:27
Definition carla_juce.cpp:31
static int64 findCentralDirectoryFileHeader(InputStream &input, int &numEntries)
Definition juce_ZipFile.cpp:74
CriticalSection::ScopedLockType ScopedLock
Definition juce_CriticalSection.h:186
unsigned short uint16
Definition juce_MathsFunctions.h:41
constexpr Type jmin(Type a, Type b)
Definition juce_MathsFunctions.h:106
unsigned int uint32
Definition juce_MathsFunctions.h:45
uint32 readUnalignedLittleEndianInt(const void *buffer)
Definition juce_ZipFile.cpp:32
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
Definition juce_MathsFunctions.h:262
static bool hasSymbolicPart(const File &root, const File &f)
Definition juce_ZipFile.cpp:125
long long int64
Definition juce_MathsFunctions.h:54
Type readUnaligned(const void *srcPtr) noexcept
Definition juce_Memory.h:65
uint16 readUnalignedLittleEndianShort(const void *buffer)
Definition juce_ZipFile.cpp:26
Definition juce_ZipFile.cpp:492
bool writeDirectoryEntry(OutputStream &target)
Definition juce_ZipFile.cpp:536
int64 uncompressedSize
Definition juce_ZipFile.cpp:556
int compressionLevel
Definition juce_ZipFile.cpp:557
Item(const File &f, InputStream *s, int compression, const String &storedPath, Time time)
Definition juce_ZipFile.cpp:493
bool symbolicLink
Definition juce_ZipFile.cpp:559
std::unique_ptr< InputStream > stream
Definition juce_ZipFile.cpp:553
void writeFlagsAndSizes(OutputStream &target) const
Definition juce_ZipFile.cpp:598
Time fileTime
Definition juce_ZipFile.cpp:555
int64 headerStart
Definition juce_ZipFile.cpp:556
String storedPathname
Definition juce_ZipFile.cpp:554
static void writeTimeAndDate(OutputStream &target, Time t)
Definition juce_ZipFile.cpp:561
const File file
Definition juce_ZipFile.cpp:552
unsigned long checksum
Definition juce_ZipFile.cpp:558
bool writeSource(OutputStream &target)
Definition juce_ZipFile.cpp:567
int64 compressedSize
Definition juce_ZipFile.cpp:556
bool writeData(OutputStream &target, const int64 overallStartPosition)
Definition juce_ZipFile.cpp:499
Definition juce_ZipFile.cpp:39
static Time parseFileTime(uint32 time, uint32 date) noexcept
Definition juce_ZipFile.cpp:56
bool isCompressed
Definition juce_ZipFile.cpp:70
int64 streamOffset
Definition juce_ZipFile.cpp:69
ZipEntryHolder(const char *buffer, int fileNameLen)
Definition juce_ZipFile.cpp:40
int64 compressedSize
Definition juce_ZipFile.cpp:69
ZipEntry entry
Definition juce_ZipFile.cpp:68
Definition juce_ZipFile.h:73
uch * p
Definition crypt.c:594
memcpy(hh, h, RAND_HEAD_LEN)
if(GLOBAL(newzip))
Definition crypt.c:475
int result
Definition process.c:1455
typedef int(UZ_EXP MsgFn)()
struct zdirent * file
Definition win32.c:1500
mo
Definition zipinfo.c:2287
static ZCONST char Far month[12][4]
Definition zipinfo.c:2243
#define const
Definition zconf.h:137