Skip to content

Commit

Permalink
Update unrar to v6.24 (2023-10-03)
Browse files Browse the repository at this point in the history
  • Loading branch information
mtgto committed Oct 16, 2023
1 parent 3c86ff6 commit 2c711ff
Show file tree
Hide file tree
Showing 11 changed files with 117 additions and 81 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# CHANGELOG

## v0.3.15 (2023-10-16)

- Update unrar to v6.24 (2023-10-03)

## v0.3.14 (2023-08-04)

- Update unrar to v6.23 (2023-08-01)
Expand Down
2 changes: 1 addition & 1 deletion Sources/Cunrar/arcread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
8 changes: 8 additions & 0 deletions Sources/Cunrar/crypt5.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 3 additions & 3 deletions Sources/Cunrar/dll.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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));
}

Expand Down
67 changes: 4 additions & 63 deletions Sources/Cunrar/extinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}


Expand All @@ -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 \\?\.
Expand Down
1 change: 0 additions & 1 deletion Sources/Cunrar/extinfo.hpp
Original file line number Diff line number Diff line change
@@ -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
Expand Down
16 changes: 6 additions & 10 deletions Sources/Cunrar/extract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
62 changes: 62 additions & 0 deletions Sources/Cunrar/filefn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
2 changes: 2 additions & 0 deletions Sources/Cunrar/filefn.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,6 @@ void ResetFileCache(const wchar *Name);



bool LinksToDirs(const wchar *SrcName,const wchar *SkipPart,std::wstring &LastChecked);

#endif
6 changes: 3 additions & 3 deletions Sources/Cunrar/version.hpp
Original file line number Diff line number Diff line change
@@ -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
24 changes: 24 additions & 0 deletions Sources/Cunrar/win32stm.cpp
Original file line number Diff line number Diff line change
@@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down

0 comments on commit 2c711ff

Please sign in to comment.