mirror of
https://github.com/Cisco-Talos/clamav.git
synced 2025-10-19 10:23:17 +00:00
Update to UnRAR v6.2.12
This commit is contained in:
parent
8548ca5c9e
commit
9ab25fe05a
12 changed files with 152 additions and 122 deletions
|
@ -991,7 +991,7 @@ void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,const BaseBlock *bb)
|
|||
if ((Flags & MHEXTRA_METADATA_NAME)!=0)
|
||||
{
|
||||
uint64 NameSize=Raw->GetV();
|
||||
if (NameSize<0x10000) // Prevent excessive allocation.
|
||||
if (NameSize>0 && NameSize<0x10000) // Prevent excessive allocation.
|
||||
{
|
||||
std::vector<char> NameU((size_t)NameSize); // UTF-8 name.
|
||||
Raw->GetB(&NameU[0],(size_t)NameSize);
|
||||
|
|
|
@ -133,7 +133,15 @@ void CryptData::SetKey50(bool Encrypt,SecPassword *Password,const wchar *PwdW,
|
|||
byte *PswCheck)
|
||||
{
|
||||
if (Lg2Cnt>CRYPT5_KDF_LG2_COUNT_MAX)
|
||||
{
|
||||
// Initialize these fields to prevent uninitialized data access warnings
|
||||
// by analyzing tools when accessing returned data.
|
||||
if (HashKey!=nullptr)
|
||||
memset(HashKey,0,SHA256_DIGEST_SIZE);
|
||||
if (PswCheck!=nullptr)
|
||||
memset(PswCheck,0,SIZE_PSWCHECK);
|
||||
return;
|
||||
}
|
||||
|
||||
byte Key[32],PswCheckValue[SHA256_DIGEST_SIZE],HashKeyValue[SHA256_DIGEST_SIZE];
|
||||
bool Found=false;
|
||||
|
|
|
@ -242,10 +242,10 @@ int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *D)
|
|||
else
|
||||
return Code;
|
||||
}
|
||||
wcsncpy(D->ArcNameW,Data->Arc.FileName,ASIZE(D->ArcNameW));
|
||||
wcsncpyz(D->ArcNameW,Data->Arc.FileName,ASIZE(D->ArcNameW));
|
||||
WideToChar(D->ArcNameW,D->ArcName,ASIZE(D->ArcName));
|
||||
|
||||
wcsncpy(D->FileNameW,hd->FileName,ASIZE(D->FileNameW));
|
||||
wcsncpyz(D->FileNameW,hd->FileName,ASIZE(D->FileNameW));
|
||||
WideToChar(D->FileNameW,D->FileName,ASIZE(D->FileName));
|
||||
#ifdef _WIN_ALL
|
||||
CharToOemA(D->FileName,D->FileName);
|
||||
|
@ -329,7 +329,7 @@ int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestNa
|
|||
{
|
||||
Data->Cmd.DllError=0;
|
||||
if (Data->OpenMode==RAR_OM_LIST || Data->OpenMode==RAR_OM_LIST_INCSPLIT ||
|
||||
Operation==RAR_SKIP) // && !Data->Arc.Solid)
|
||||
Operation==RAR_SKIP && !Data->Arc.Solid)
|
||||
{
|
||||
if (Data->Arc.Volume && Data->Arc.GetHeaderType()==HEAD_FILE &&
|
||||
Data->Arc.FileHead.SplitAfter)
|
||||
|
@ -377,7 +377,7 @@ int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestNa
|
|||
|
||||
if (DestPathW!=NULL)
|
||||
{
|
||||
wcsncpy(Data->Cmd.ExtrPath,DestPathW,ASIZE(Data->Cmd.ExtrPath));
|
||||
wcsncpyz(Data->Cmd.ExtrPath,DestPathW,ASIZE(Data->Cmd.ExtrPath));
|
||||
AddEndSlash(Data->Cmd.ExtrPath,ASIZE(Data->Cmd.ExtrPath));
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
#include <commctrl.h>
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 6, 23, 100, 944
|
||||
PRODUCTVERSION 6, 23, 100, 944
|
||||
FILEVERSION 6, 24, 100, 1007
|
||||
PRODUCTVERSION 6, 24, 100, 1007
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_APP
|
||||
{
|
||||
|
@ -14,8 +14,8 @@ FILETYPE VFT_APP
|
|||
VALUE "CompanyName", "Alexander Roshal\0"
|
||||
VALUE "ProductName", "RAR decompression library\0"
|
||||
VALUE "FileDescription", "RAR decompression library\0"
|
||||
VALUE "FileVersion", "6.23.0\0"
|
||||
VALUE "ProductVersion", "6.23.0\0"
|
||||
VALUE "FileVersion", "6.24.0\0"
|
||||
VALUE "ProductVersion", "6.24.0\0"
|
||||
VALUE "LegalCopyright", "Copyright © Alexander Roshal 1993-2023\0"
|
||||
VALUE "OriginalFilename", "Unrar.dll\0"
|
||||
}
|
||||
|
|
|
@ -80,10 +80,13 @@ static int CalcAllowedDepth(const wchar *Name)
|
|||
bool Dot2=Name[1]=='.' && Name[2]=='.' && (IsPathDiv(Name[3]) || Name[3]==0);
|
||||
if (!Dot && !Dot2)
|
||||
AllowedDepth++;
|
||||
else
|
||||
if (Dot2)
|
||||
AllowedDepth--;
|
||||
}
|
||||
Name++;
|
||||
}
|
||||
return AllowedDepth;
|
||||
return AllowedDepth < 0 ? 0 : AllowedDepth;
|
||||
}
|
||||
|
||||
|
||||
|
@ -106,68 +109,6 @@ static bool LinkInPath(const wchar *Name)
|
|||
}
|
||||
|
||||
|
||||
// Delete symbolic links in file path, if any, and replace them by directories.
|
||||
// Prevents extracting files outside of destination folder with symlink chains.
|
||||
bool LinksToDirs(const wchar *SrcName,const wchar *SkipPart,std::wstring &LastChecked)
|
||||
{
|
||||
// Unlike Unix, Windows doesn't expand lnk1 in symlink targets like
|
||||
// "lnk1/../dir", but converts the path to "dir". In Unix we need to call
|
||||
// this function to prevent placing unpacked files outside of destination
|
||||
// folder if previously we unpacked "dir/lnk1" -> "..",
|
||||
// "dir/lnk2" -> "lnk1/.." and "dir/lnk2/anypath/poc.txt".
|
||||
// We may still need this function to prevent abusing symlink chains
|
||||
// in link source path if we remove detection of such chains
|
||||
// in IsRelativeSymlinkSafe. This function seems to make other symlink
|
||||
// related safety checks redundant, but for now we prefer to keep them too.
|
||||
//
|
||||
// 2022.12.01: the performance impact is minimized after adding the check
|
||||
// against the previous path and enabling this verification only after
|
||||
// extracting a symlink with ".." in target. So we enabled it for Windows
|
||||
// as well for extra safety.
|
||||
//#ifdef _UNIX
|
||||
wchar Path[NM];
|
||||
if (wcslen(SrcName)>=ASIZE(Path))
|
||||
return false; // It should not be that long, skip.
|
||||
wcsncpyz(Path,SrcName,ASIZE(Path));
|
||||
|
||||
size_t SkipLength=wcslen(SkipPart);
|
||||
|
||||
if (SkipLength>0 && wcsncmp(Path,SkipPart,SkipLength)!=0)
|
||||
SkipLength=0; // Parameter validation, not really needed now.
|
||||
|
||||
// Do not check parts already checked in previous path to improve performance.
|
||||
for (uint I=0;Path[I]!=0 && I<LastChecked.size() && Path[I]==LastChecked[I];I++)
|
||||
if (IsPathDiv(Path[I]) && I>SkipLength)
|
||||
SkipLength=I;
|
||||
|
||||
wchar *Name=Path;
|
||||
if (SkipLength>0)
|
||||
{
|
||||
// Avoid converting symlinks in destination path part specified by user.
|
||||
Name+=SkipLength;
|
||||
while (IsPathDiv(*Name))
|
||||
Name++;
|
||||
}
|
||||
|
||||
for (wchar *s=Path+wcslen(Path)-1;s>Name;s--)
|
||||
if (IsPathDiv(*s))
|
||||
{
|
||||
*s=0;
|
||||
FindData FD;
|
||||
if (FindFile::FastFind(Path,&FD,true) && FD.IsLink)
|
||||
#ifdef _WIN_ALL
|
||||
if (!DelDir(Path))
|
||||
#else
|
||||
if (!DelFile(Path))
|
||||
#endif
|
||||
return false; // Couldn't delete the symlink to replace it with directory.
|
||||
}
|
||||
LastChecked=SrcName;
|
||||
//#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IsRelativeSymlinkSafe(CommandData *Cmd,const wchar *SrcName,const wchar *PrepSrcName,const wchar *TargetName)
|
||||
{
|
||||
// Catch root dir based /path/file paths also as stuff like \\?\.
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#ifndef _RAR_EXTINFO_
|
||||
#define _RAR_EXTINFO_
|
||||
|
||||
bool LinksToDirs(const wchar *SrcName,const wchar *SkipPart,std::wstring &LastChecked);
|
||||
bool IsRelativeSymlinkSafe(CommandData *Cmd,const wchar *SrcName,const wchar *PrepSrcName,const wchar *TargetName);
|
||||
bool ExtractSymlink(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc,const wchar *LinkName,bool &UpLink);
|
||||
#ifdef _UNIX
|
||||
|
|
|
@ -14,20 +14,16 @@ CmdExtract::CmdExtract(CommandData *Cmd)
|
|||
TotalFileCount=0;
|
||||
|
||||
// Common for all archives involved. Set here instead of DoExtract()
|
||||
// to use in unrar.dll too. Allows to avoid LinksToDirs() calls
|
||||
// and save CPU time in no symlinks including ".." in target were extracted.
|
||||
#if defined(_WIN_ALL)
|
||||
// We can't expand symlink path components in another symlink target
|
||||
// in Windows. We can't create symlinks in Android now. Even though we do not
|
||||
// really need LinksToDirs() calls in these systems, we still call it
|
||||
// for extra safety, but only if symlink with ".." in target was extracted.
|
||||
ConvertSymlinkPaths=false;
|
||||
#else
|
||||
// to use in unrar.dll too.
|
||||
// We enable it by default in Unix to care about the case when several
|
||||
// archives are unpacked to same directory with several independent RAR runs.
|
||||
// Worst case performance penalty for a lot of small files seems to be ~3%.
|
||||
// 2023.09.15: Windows performance impact seems to be negligible,
|
||||
// less than 0.5% when extracting mix of small files and folders.
|
||||
// So for extra security we enabled it for Windows too, even though
|
||||
// unlike Unix, Windows doesn't expand lnk1 in symlink targets like
|
||||
// "lnk1/../dir", but converts such path to "dir".
|
||||
ConvertSymlinkPaths=true;
|
||||
#endif
|
||||
|
||||
Unp=new Unpack(&DataIO);
|
||||
#ifdef RAR_SMP
|
||||
|
@ -82,7 +78,7 @@ void CmdExtract::DoExtract()
|
|||
{
|
||||
if (Cmd->ManualPassword)
|
||||
Cmd->Password.Clean(); // Clean user entered password before processing next archive.
|
||||
|
||||
|
||||
ReconstructDone=false; // Must be reset here, not in ExtractArchiveInit().
|
||||
UseExactVolName=false; // Must be reset here, not in ExtractArchiveInit().
|
||||
while (true)
|
||||
|
@ -98,7 +94,7 @@ void CmdExtract::DoExtract()
|
|||
if (Cmd->ManualPassword)
|
||||
Cmd->Password.Clean();
|
||||
|
||||
if (TotalFileCount==0 && Cmd->Command[0]!='I' &&
|
||||
if (TotalFileCount==0 && Cmd->Command[0]!='I' &&
|
||||
ErrHandler.GetErrorCode()!=RARX_BADPWD) // Not in case of wrong archive password.
|
||||
{
|
||||
if (!PasswordCancelled)
|
||||
|
@ -240,7 +236,7 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive()
|
|||
return EXTRACT_ARC_REPEAT;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Calculate the total size of all accessible volumes.
|
||||
// This size is necessary to display the correct total progress indicator.
|
||||
|
||||
|
@ -249,7 +245,7 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive()
|
|||
|
||||
while (true)
|
||||
{
|
||||
// First volume is already added to DataIO.TotalArcSize
|
||||
// First volume is already added to DataIO.TotalArcSize
|
||||
// in initial TotalArcSize calculation in DoExtract.
|
||||
// So we skip it and start from second volume.
|
||||
NextVolumeName(NextName,ASIZE(NextName),!Arc.NewNumbering);
|
||||
|
@ -494,7 +490,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
|||
if (wcscmp(ArcFileName,RefList[I].RefName)==0)
|
||||
{
|
||||
ExtractRef *MatchedRef=&RefList[I];
|
||||
|
||||
|
||||
if (!Cmd->Test) // While harmless, it is useless for 't'.
|
||||
{
|
||||
// If reference source isn't selected, but target is selected,
|
||||
|
@ -513,13 +509,13 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
|||
RefTarget=true; // Need it even for 't' to test the reference source.
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (Arc.FileHead.Encrypted && Cmd->SkipEncrypted)
|
||||
if (Arc.Solid)
|
||||
return false; // Abort the entire extraction for solid archive.
|
||||
else
|
||||
MatchFound=false; // Skip only the current file for non-solid archive.
|
||||
|
||||
|
||||
if (MatchFound || RefTarget || (SkipSolid=Arc.Solid)!=0)
|
||||
{
|
||||
// First common call of uiStartFileExtract. It is done before overwrite
|
||||
|
@ -541,10 +537,10 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
|||
{
|
||||
if (FD.mtime >= Arc.FileHead.mtime)
|
||||
{
|
||||
// If directory already exists and its modification time is newer
|
||||
// than start of extraction, it is likely it was created
|
||||
// when creating a path to one of already extracted items.
|
||||
// In such case we'll better update its time even if archived
|
||||
// If directory already exists and its modification time is newer
|
||||
// than start of extraction, it is likely it was created
|
||||
// when creating a path to one of already extracted items.
|
||||
// In such case we'll better update its time even if archived
|
||||
// directory is older.
|
||||
|
||||
if (!FD.IsDir || FD.mtime<StartTime)
|
||||
|
@ -646,6 +642,10 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
|||
wcsncpyz(DestFileName,Cmd->DllDestName,ASIZE(DestFileName));
|
||||
#endif
|
||||
|
||||
if (ExtrFile && Command!='P' && !Cmd->Test && !Cmd->AbsoluteLinks &&
|
||||
ConvertSymlinkPaths)
|
||||
ExtrFile=LinksToDirs(DestFileName,Cmd->ExtrPath,LastCheckedSymlink);
|
||||
|
||||
File CurFile;
|
||||
|
||||
bool LinkEntry=Arc.FileHead.RedirType!=FSREDIR_NONE;
|
||||
|
@ -684,7 +684,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
|||
ExtrFile=true;
|
||||
|
||||
// We changed SkipSolid, so we need to call uiStartFileExtract
|
||||
// with "Skip" parameter to change the operation status
|
||||
// with "Skip" parameter to change the operation status
|
||||
// from "extracting" to "skipping". For example, it can be necessary
|
||||
// if user answered "No" to overwrite prompt when unpacking
|
||||
// a solid archive.
|
||||
|
@ -775,7 +775,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
|||
if (Type==FSREDIR_HARDLINK || Type==FSREDIR_FILECOPY)
|
||||
{
|
||||
wchar RedirName[NM];
|
||||
|
||||
|
||||
// 2022.11.15: Might be needed when unpacking WinRAR 5.0 links with
|
||||
// Unix RAR. WinRAR 5.0 used \ path separators here, when beginning
|
||||
// from 5.10 even Windows version uses / internally and converts
|
||||
|
@ -806,7 +806,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
|||
// Unix symlink can have its own owner data.
|
||||
if (LinkSuccess)
|
||||
SetFileHeaderExtra(Cmd,Arc,DestFileName);
|
||||
|
||||
|
||||
ConvertSymlinkPaths|=LinkSuccess && UpLink;
|
||||
|
||||
// We do not actually need to reset the cache here if we cache
|
||||
|
@ -826,7 +826,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
|||
uiMsg(UIERROR_UNKNOWNEXTRA,Arc.FileName,ArcFileName);
|
||||
LinkSuccess=false;
|
||||
}
|
||||
|
||||
|
||||
if (!LinkSuccess || Arc.Format==RARFMT15 && !FileCreateMode)
|
||||
{
|
||||
// RAR 5.x links have a valid data checksum even in case of
|
||||
|
@ -874,9 +874,9 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
|||
else
|
||||
if (Arc.FileHead.Method!=0 && Arc.FileHead.UnpSize>0 && ValidCRC)
|
||||
AnySolidDataUnpackedWell=true;
|
||||
|
||||
|
||||
bool BrokenFile=false;
|
||||
|
||||
|
||||
// Checksum is not calculated in skip solid mode for performance reason.
|
||||
if (!SkipSolid && ShowChecksum)
|
||||
{
|
||||
|
@ -888,7 +888,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (Arc.FileHead.Encrypted && (!Arc.FileHead.UsePswCheck ||
|
||||
if (Arc.FileHead.Encrypted && (!Arc.FileHead.UsePswCheck ||
|
||||
Arc.BrokenHeader) && !AnySolidDataUnpackedWell)
|
||||
uiMsg(UIERROR_CHECKSUMENC,Arc.FileName,ArcFileName);
|
||||
else
|
||||
|
@ -909,7 +909,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
|||
// We check SkipSolid to remove percent for skipped solid files only.
|
||||
// We must not apply these \b to links with ShowChecksum==false
|
||||
// and their possible error messages.
|
||||
if (SkipSolid)
|
||||
if (SkipSolid)
|
||||
mprintf(L"\b\b\b\b\b ");
|
||||
}
|
||||
|
||||
|
@ -922,7 +922,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
|||
bool SetAttrOnly=LinkEntry && Arc.FileHead.RedirType==FSREDIR_HARDLINK && LinkSuccess;
|
||||
|
||||
if (!TestMode && (Command=='X' || Command=='E') &&
|
||||
(!LinkEntry || SetAttrOnly || Arc.FileHead.RedirType==FSREDIR_FILECOPY && LinkSuccess) &&
|
||||
(!LinkEntry || SetAttrOnly || Arc.FileHead.RedirType==FSREDIR_FILECOPY && LinkSuccess) &&
|
||||
(!BrokenFile || Cmd->KeepBroken))
|
||||
{
|
||||
// Below we use DestFileName instead of CurFile.FileName,
|
||||
|
@ -949,7 +949,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
|||
Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime,
|
||||
Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime);
|
||||
}
|
||||
|
||||
|
||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||
if (Cmd->SetCompressedAttr &&
|
||||
(Arc.FileHead.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0)
|
||||
|
@ -1094,7 +1094,7 @@ void CmdExtract::ExtrPrepareName(Archive &Arc,const wchar *ArcFileName,wchar *De
|
|||
wcsncpyz(DestName,ArcFileName,DestSize);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
wcsncpyz(DestName,Cmd->ExtrPath,DestSize);
|
||||
|
||||
if (*Cmd->ExtrPath!=0)
|
||||
|
@ -1141,7 +1141,7 @@ void CmdExtract::ExtrPrepareName(Archive &Arc,const wchar *ArcFileName,wchar *De
|
|||
{
|
||||
size_t NameLength=wcslen(ArcFileName);
|
||||
if (NameLength>=ArcPathLength && wcsnicompc(ArcPath,ArcFileName,ArcPathLength)==0 &&
|
||||
(IsPathDiv(ArcPath[ArcPathLength-1]) ||
|
||||
(IsPathDiv(ArcPath[ArcPathLength-1]) ||
|
||||
IsPathDiv(ArcFileName[ArcPathLength]) || ArcFileName[ArcPathLength]==0))
|
||||
{
|
||||
ArcFileName+=Min(ArcPathLength,NameLength);
|
||||
|
@ -1460,12 +1460,12 @@ bool CmdExtract::CheckUnpVer(Archive &Arc,const wchar *ArcFileName)
|
|||
// Find non-matched reference sources in solid and non-solid archives.
|
||||
// Detect the optimal start position for semi-solid archives
|
||||
// and optimal start volume for independent solid volumes.
|
||||
//
|
||||
//
|
||||
// Alternatively we could collect references while extracting an archive
|
||||
// and perform the second extraction pass for references only.
|
||||
// But it would be slower for solid archives than scaning headers
|
||||
// in first pass and extracting everything in second, as implemented now.
|
||||
//
|
||||
//
|
||||
void CmdExtract::AnalyzeArchive(const wchar *ArcName,bool Volume,bool NewNumbering)
|
||||
{
|
||||
FreeAnalyzeData(); // If processing non-first archive in multiple archives set.
|
||||
|
@ -1481,13 +1481,13 @@ void CmdExtract::AnalyzeArchive(const wchar *ArcName,bool Volume,bool NewNumberi
|
|||
GetFirstVolIfFullSet(ArcName,NewNumbering,NextName,ASIZE(NextName));
|
||||
else
|
||||
wcsncpyz(NextName,ArcName,ASIZE(NextName));
|
||||
|
||||
|
||||
bool MatchFound=false;
|
||||
bool PrevMatched=false;
|
||||
bool OpenNext=false;
|
||||
|
||||
bool FirstVolume=true;
|
||||
|
||||
|
||||
// We shall set FirstFile once for all volumes and not for each volume.
|
||||
// So we do not reuse the outdated Analyze->StartPos from previous volume
|
||||
// if extracted file resides completely in the beginning of current one.
|
||||
|
@ -1542,7 +1542,7 @@ void CmdExtract::AnalyzeArchive(const wchar *ArcName,bool Volume,bool NewNumberi
|
|||
wcsncpyz(Analyze->StartName,NextName,ASIZE(Analyze->StartName));
|
||||
|
||||
// We shall set FirstFile once for all volumes for this code
|
||||
// to work properly. Alternatively we could append
|
||||
// to work properly. Alternatively we could append
|
||||
// "|| Analyze->StartPos!=0" to the condition, so we do not reuse
|
||||
// the outdated Analyze->StartPos value from previous volume.
|
||||
if (!FirstFile)
|
||||
|
|
|
@ -542,3 +542,65 @@ void ResetFileCache(const wchar *Name)
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
// Delete symbolic links in file path, if any, and replace them by directories.
|
||||
// Prevents extracting files outside of destination folder with symlink chains.
|
||||
bool LinksToDirs(const wchar *SrcName,const wchar *SkipPart,std::wstring &LastChecked)
|
||||
{
|
||||
// Unlike Unix, Windows doesn't expand lnk1 in symlink targets like
|
||||
// "lnk1/../dir", but converts the path to "dir". In Unix we need to call
|
||||
// this function to prevent placing unpacked files outside of destination
|
||||
// folder if previously we unpacked "dir/lnk1" -> "..",
|
||||
// "dir/lnk2" -> "lnk1/.." and "dir/lnk2/anypath/poc.txt".
|
||||
// We may still need this function to prevent abusing symlink chains
|
||||
// in link source path if we remove detection of such chains
|
||||
// in IsRelativeSymlinkSafe. This function seems to make other symlink
|
||||
// related safety checks redundant, but for now we prefer to keep them too.
|
||||
//
|
||||
// 2022.12.01: the performance impact is minimized after adding the check
|
||||
// against the previous path and enabling this verification only after
|
||||
// extracting a symlink with ".." in target. So we enabled it for Windows
|
||||
// as well for extra safety.
|
||||
//#ifdef _UNIX
|
||||
wchar Path[NM];
|
||||
if (wcslen(SrcName)>=ASIZE(Path))
|
||||
return false; // It should not be that long, skip.
|
||||
wcsncpyz(Path,SrcName,ASIZE(Path));
|
||||
|
||||
size_t SkipLength=wcslen(SkipPart);
|
||||
|
||||
if (SkipLength>0 && wcsncmp(Path,SkipPart,SkipLength)!=0)
|
||||
SkipLength=0; // Parameter validation, not really needed now.
|
||||
|
||||
// Do not check parts already checked in previous path to improve performance.
|
||||
for (uint I=0;Path[I]!=0 && I<LastChecked.size() && Path[I]==LastChecked[I];I++)
|
||||
if (IsPathDiv(Path[I]) && I>SkipLength)
|
||||
SkipLength=I;
|
||||
|
||||
wchar *Name=Path;
|
||||
if (SkipLength>0)
|
||||
{
|
||||
// Avoid converting symlinks in destination path part specified by user.
|
||||
Name+=SkipLength;
|
||||
while (IsPathDiv(*Name))
|
||||
Name++;
|
||||
}
|
||||
|
||||
for (wchar *s=Path+wcslen(Path)-1;s>Name;s--)
|
||||
if (IsPathDiv(*s))
|
||||
{
|
||||
*s=0;
|
||||
FindData FD;
|
||||
if (FindFile::FastFind(Path,&FD,true) && FD.IsLink)
|
||||
#ifdef _WIN_ALL
|
||||
if (!DelDir(Path))
|
||||
#else
|
||||
if (!DelFile(Path))
|
||||
#endif
|
||||
return false; // Couldn't delete the symlink to replace it with directory.
|
||||
}
|
||||
LastChecked=SrcName;
|
||||
//#endif
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -46,4 +46,6 @@ void ResetFileCache(const wchar *Name);
|
|||
|
||||
|
||||
|
||||
bool LinksToDirs(const wchar *SrcName,const wchar *SkipPart,std::wstring &LastChecked);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -91,12 +91,6 @@ void Unpack::Init(size_t WinSize,bool Solid)
|
|||
if ((WinSize>>16)>0x10000) // Window size must not exceed 4 GB.
|
||||
return;
|
||||
|
||||
// Unrar does not support window size greather than 1GB at this time.
|
||||
// Any request for a window larger than 1GB should be ignored.
|
||||
const size_t MaxAllocSize=0x40000000;
|
||||
if (WinSize>MaxAllocSize)
|
||||
WinSize=MaxAllocSize;
|
||||
|
||||
// Archiving code guarantees that window size does not grow in the same
|
||||
// solid stream. So if we are here, we are either creating a new window
|
||||
// or increasing the size of non-solid window. So we could safely reject
|
||||
|
@ -271,7 +265,7 @@ void Unpack::MakeDecodeTables(byte *LengthTable,DecodeTable *Dec,uint Size)
|
|||
Dec->DecodeLen[I]=(uint)LeftAligned;
|
||||
|
||||
// Every item of this array contains the sum of all preceding items.
|
||||
// So it contains the start position in code list for every bit length.
|
||||
// So it contains the start position in code list for every bit length.
|
||||
Dec->DecodePos[I]=Dec->DecodePos[I-1]+LengthCount[I-1];
|
||||
}
|
||||
|
||||
|
@ -334,7 +328,7 @@ void Unpack::MakeDecodeTables(byte *LengthTable,DecodeTable *Dec,uint Size)
|
|||
uint BitField=Code<<(16-Dec->QuickBits);
|
||||
|
||||
// Prepare the table for quick decoding of bit lengths.
|
||||
|
||||
|
||||
// Find the upper limit for current bit field and adjust the bit length
|
||||
// accordingly if necessary.
|
||||
while (CurBitLength<ASIZE(Dec->DecodeLen) && BitField>=Dec->DecodeLen[CurBitLength])
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#define RARVER_MAJOR 6
|
||||
#define RARVER_MINOR 23
|
||||
#define RARVER_MINOR 24
|
||||
#define RARVER_BETA 0
|
||||
#define RARVER_DAY 1
|
||||
#define RARVER_MONTH 8
|
||||
#define RARVER_DAY 3
|
||||
#define RARVER_MONTH 10
|
||||
#define RARVER_YEAR 2023
|
||||
|
|
|
@ -1,5 +1,23 @@
|
|||
|
||||
|
||||
#ifdef _WIN_ALL
|
||||
// StreamName must include the leading ':'.
|
||||
static bool IsNtfsReservedStream(const wchar *StreamName)
|
||||
{
|
||||
const wchar *Reserved[]{
|
||||
L"::$ATTRIBUTE_LIST",L"::$BITMAP",L"::$DATA",L"::$EA",L"::$EA_INFORMATION",
|
||||
L"::$FILE_NAME",L"::$INDEX_ALLOCATION",L":$I30:$INDEX_ALLOCATION",
|
||||
L"::$INDEX_ROOT",L"::$LOGGED_UTILITY_STREAM",L":$EFS:$LOGGED_UTILITY_STREAM",
|
||||
L":$TXF_DATA:$LOGGED_UTILITY_STREAM",L"::$OBJECT_ID",L"::$REPARSE_POINT"
|
||||
};
|
||||
for (const wchar *Name : Reserved)
|
||||
if (wcsicomp(StreamName,Name)==0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(SFX_MODULE) && defined(_WIN_ALL)
|
||||
void ExtractStreams20(Archive &Arc,const wchar *FileName)
|
||||
{
|
||||
|
@ -40,6 +58,9 @@ void ExtractStreams20(Archive &Arc,const wchar *FileName)
|
|||
ConvertPath(StoredName+1,StoredName+1,ASIZE(StoredName)-1);
|
||||
|
||||
|
||||
if (IsNtfsReservedStream(StoredName))
|
||||
return;
|
||||
|
||||
wcsncatz(StreamName,StoredName,ASIZE(StreamName));
|
||||
|
||||
FindData fd;
|
||||
|
@ -113,6 +134,9 @@ void ExtractStreams(Archive &Arc,const wchar *FileName,bool TestMode)
|
|||
wcsncatz(FullName,StreamName,ASIZE(FullName));
|
||||
|
||||
|
||||
if (IsNtfsReservedStream(StreamName))
|
||||
return;
|
||||
|
||||
FindData fd;
|
||||
bool HostFound=FindFile::FastFind(FileName,&fd);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue