diff --git c/third_party/unrar/src/archive.cpp w/third_party/unrar/src/archive.cpp index 4fc2a893478d6..87c639c606e24 100644 --- c/third_party/unrar/src/archive.cpp +++ w/third_party/unrar/src/archive.cpp @@ -359,3 +359,4 @@ uint64 Archive::GetWinSize(uint64 Size,uint &Flags) Flags+=(uint)Fraction*FCI_DICT_FRACT0; return Pow2+Fraction*(Pow2/32); } + diff --git c/third_party/unrar/src/archive.hpp w/third_party/unrar/src/archive.hpp index db1cb533823bf..8dde040e02fa0 100644 --- c/third_party/unrar/src/archive.hpp +++ w/third_party/unrar/src/archive.hpp @@ -23,6 +23,10 @@ enum ADDSUBDATA_FLAGS // RAR5 headers must not exceed 2 MB. #define MAX_HEADER_SIZE_RAR5 0x200000 +#if defined(CHROMIUM_UNRAR) +#include "third_party/unrar/google/unrar_delegates.h" +#endif + class Archive:public File { private: @@ -58,6 +62,8 @@ class Archive:public File QuickOpen QOpen; bool ProhibitQOpen; #endif + + public: Archive(CommandData *InitCmd=nullptr); ~Archive(); @@ -87,6 +93,10 @@ class Archive:public File HEADER_TYPE GetHeaderType() {return CurHeaderType;} CommandData* GetCommandData() {return Cmd;} void SetSilentOpen(bool Mode) {SilentOpen=Mode;} +#if defined(CHROMIUM_UNRAR) + void SetWriterDelegate(third_party_unrar::RarWriterDelegate *Delegate) {m_writer_delegate=Delegate;} + third_party_unrar::RarWriterDelegate *m_writer_delegate = nullptr; +#endif #ifdef USE_QOPEN bool Open(const std::wstring &Name,uint Mode=FMF_READ) override; int Read(void *Data,size_t Size) override; diff --git c/third_party/unrar/src/arcread.cpp w/third_party/unrar/src/arcread.cpp index 7cfa30bf6f40b..204023fb52ed2 100644 --- c/third_party/unrar/src/arcread.cpp +++ w/third_party/unrar/src/arcread.cpp @@ -160,7 +160,11 @@ size_t Archive::ReadHeader15() UnexpEndArcMsg(); return 0; } - HeadersCrypt.SetCryptKeys(false,CRYPT_RAR30,&Cmd->Password,Salt,NULL,0,NULL,NULL); + if (!HeadersCrypt.SetCryptKeys(false,CRYPT_RAR30,&Cmd->Password,Salt,NULL,0,NULL,NULL)) + { + FailedHeaderDecryption=true; + return 0; + } Raw.SetCrypt(&HeadersCrypt); #endif } diff --git c/third_party/unrar/src/blake2s.hpp w/third_party/unrar/src/blake2s.hpp index 90b7885fde18a..4d30fe8685745 100644 --- c/third_party/unrar/src/blake2s.hpp +++ w/third_party/unrar/src/blake2s.hpp @@ -2,8 +2,13 @@ #ifndef _RAR_BLAKE2_ #define _RAR_BLAKE2_ +#if defined(CHROMIUM_UNRAR) +inline constexpr unsigned int BLAKE2_DIGEST_SIZE = 32u; +inline constexpr unsigned int BLAKE2_THREADS_NUMBER = 8u; +#else #define BLAKE2_DIGEST_SIZE 32 #define BLAKE2_THREADS_NUMBER 8 +#endif // defined(CHROMIUM_UNRAR) // Use constexpr instead of enums for -std=c++20 compatibility. constexpr size_t BLAKE2S_BLOCKBYTES = 64; diff --git c/third_party/unrar/src/crc.cpp w/third_party/unrar/src/crc.cpp index 61c616289ae47..f9a9d74f021c8 100644 --- c/third_party/unrar/src/crc.cpp +++ w/third_party/unrar/src/crc.cpp @@ -21,6 +21,7 @@ #endif static uint crc_tables[16][256]; // Tables for Slicing-by-16. +static bool is_initialized = false; #ifdef USE_NEON_CRC32 static bool CRC_Neon; @@ -74,10 +75,16 @@ static void InitTables() } -struct CallInitCRC {CallInitCRC() {InitTables();}} static CallInit32; - uint CRC32(uint StartCRC,const void *Addr,size_t Size) { +#if defined(CHROMIUM_UNRAR_FUZZER) + return -1; +#else + if (!is_initialized) { + is_initialized = true; + InitTables(); + } + byte *Data=(byte *)Addr; #ifdef USE_NEON_CRC32 @@ -147,6 +154,7 @@ uint CRC32(uint StartCRC,const void *Addr,size_t Size) StartCRC=crc_tables[0][(byte)(StartCRC^Data[0])]^(StartCRC>>8); return StartCRC; +#endif // defined(CHROMIUM_UNRAR_FUZZER) } diff --git c/third_party/unrar/src/crypt.cpp w/third_party/unrar/src/crypt.cpp index 9c754ffe404d8..dbc1fb0c3cef3 100644 --- c/third_party/unrar/src/crypt.cpp +++ w/third_party/unrar/src/crypt.cpp @@ -13,6 +13,9 @@ CryptData::CryptData() Method=CRYPT_NONE; KDF3CachePos=0; KDF5CachePos=0; +#if defined(CHROMIUM_UNRAR) + KDFCacheMisses=0; +#endif memset(CRCTab,0,sizeof(CRCTab)); } @@ -83,7 +86,7 @@ bool CryptData::SetCryptKeys(bool Encrypt,CRYPT_METHOD Method, break; #endif case CRYPT_RAR30: - SetKey30(Encrypt,Password,PwdW,Salt); + Success=SetKey30(Encrypt,Password,PwdW,Salt); break; case CRYPT_RAR50: Success=SetKey50(Encrypt,Password,PwdW,Salt,InitV,Lg2Cnt,HashKey,PswCheck); diff --git c/third_party/unrar/src/crypt.hpp w/third_party/unrar/src/crypt.hpp index 286c84807c3d5..cc5aa4d781a1f 100644 --- c/third_party/unrar/src/crypt.hpp +++ w/third_party/unrar/src/crypt.hpp @@ -17,9 +17,23 @@ enum CRYPT_METHOD { #define CRYPT_BLOCK_MASK (CRYPT_BLOCK_SIZE-1) // 0xf #define CRYPT5_KDF_LG2_COUNT 15 // LOG2 of PDKDF2 iteration count. + +#if defined(CHROMIUM_UNRAR_FUZZER) +#define CRYPT5_KDF_LG2_COUNT_MAX 18 // LOG2 of maximum accepted iteration count. +#else #define CRYPT5_KDF_LG2_COUNT_MAX 24 // LOG2 of maximum accepted iteration count. +#endif + +#if defined(CHROMIUM_UNRAR) +// Maximum number of distinct keys to derive per CryptData instance. Archives +// using more salts than this will have remaining encrypted data treated as +// undecryptable, while still allowing header metadata to be enumerated. +#define CRYPT_KDF_CACHE_MISS_MAX 16 +#endif + #define CRYPT_VERSION 0 // Supported encryption version. +static_assert(CRYPT5_KDF_LG2_COUNT <= CRYPT5_KDF_LG2_COUNT_MAX); class CryptData { @@ -79,7 +93,7 @@ class CryptData void EncryptBlock20(byte *Buf); void DecryptBlock20(byte *Buf); - void SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt); + bool SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt); bool SetKey50(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt,const byte *InitV,uint Lg2Cnt,byte *HashKey,byte *PswCheck); KDF3CacheItem KDF3Cache[4]; @@ -88,6 +102,10 @@ class CryptData KDF5CacheItem KDF5Cache[4]; uint KDF5CachePos; +#if defined(CHROMIUM_UNRAR) + uint KDFCacheMisses; +#endif + CRYPT_METHOD Method; Rijndael rin; diff --git c/third_party/unrar/src/crypt3.cpp w/third_party/unrar/src/crypt3.cpp index e6e3a82cbb23a..458cc33d7acf4 100644 --- c/third_party/unrar/src/crypt3.cpp +++ w/third_party/unrar/src/crypt3.cpp @@ -1,4 +1,4 @@ -void CryptData::SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt) +bool CryptData::SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt) { byte AESKey[16],AESInit[16]; @@ -17,6 +17,10 @@ void CryptData::SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,co if (!Cached) { +#if defined(CHROMIUM_UNRAR) + if (KDFCacheMisses++>=CRYPT_KDF_CACHE_MISS_MAX) + return false; +#endif byte RawPsw[2*MAXPASSWORD+SIZE_SALT30]; size_t PswLength=wcslen(PwdW); size_t RawLength=2*PswLength; @@ -65,5 +69,6 @@ void CryptData::SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,co rin.Init(Encrypt, AESKey, 128, AESInit); cleandata(AESKey,sizeof(AESKey)); cleandata(AESInit,sizeof(AESInit)); + return true; } diff --git c/third_party/unrar/src/crypt5.cpp w/third_party/unrar/src/crypt5.cpp index 2183c8f0814b5..ed2dfc966436a 100644 --- c/third_party/unrar/src/crypt5.cpp +++ w/third_party/unrar/src/crypt5.cpp @@ -155,6 +155,10 @@ bool CryptData::SetKey50(bool Encrypt,SecPassword *Password,const wchar *PwdW, if (!Found) { +#if defined(CHROMIUM_UNRAR) + if (KDFCacheMisses++>=CRYPT_KDF_CACHE_MISS_MAX) + return false; +#endif char PwdUtf[MAXPASSWORD*4]; WideToUtf(PwdW,PwdUtf,ASIZE(PwdUtf)); diff --git c/third_party/unrar/src/errhnd.cpp w/third_party/unrar/src/errhnd.cpp index b347678fe1903..0a363a79c74b8 100644 --- c/third_party/unrar/src/errhnd.cpp +++ w/third_party/unrar/src/errhnd.cpp @@ -1,10 +1,12 @@ +// NOTE(vakh): The process.h file needs to be included first because "rar.hpp" +// defines certain macros that cause symbol redefinition errors +#if defined(UNRAR_NO_EXCEPTIONS) +#include "base/notreached.h" +#include "base/process/process.h" +#endif // defined(UNRAR_NO_EXCEPTIONS) #include "rar.hpp" -ErrorHandler::ErrorHandler() -{ - Clean(); -} - +#include void ErrorHandler::Clean() { @@ -343,7 +345,11 @@ void ErrorHandler::Throw(RAR_EXIT Code) mprintf(L"\n%s\n",St(MProgAborted)); #endif SetErrorCode(Code); +#if defined(UNRAR_NO_EXCEPTIONS) + NOTREACHED() << "Failed with RAR_EXIT code: " << Code; +#else throw Code; +#endif // defined(UNRAR_NO_EXCEPTIONS) } diff --git c/third_party/unrar/src/errhnd.hpp w/third_party/unrar/src/errhnd.hpp index 065350f94af55..5c539faf0d82a 100644 --- c/third_party/unrar/src/errhnd.hpp +++ w/third_party/unrar/src/errhnd.hpp @@ -24,14 +24,13 @@ enum RAR_EXIT // RAR exit code. class ErrorHandler { private: - RAR_EXIT ExitCode; - uint ErrCount; - bool EnableBreak; - bool Silent; - bool DisableShutdown; // Shutdown is not suitable after last error. - bool ReadErrIgnoreAll; + RAR_EXIT ExitCode = RARX_SUCCESS; + uint ErrCount = 0; + bool EnableBreak = true; + bool Silent = false; + bool DisableShutdown = false; // Shutdown is not suitable after last error. + bool ReadErrIgnoreAll = false; public: - ErrorHandler(); void Clean(); void MemoryError(); void OpenError(const std::wstring &FileName); @@ -68,8 +67,8 @@ class ErrorHandler void SetDisableShutdown() {DisableShutdown=true;} bool IsShutdownEnabled() {return !DisableShutdown;} - bool UserBreak; // Ctrl+Break is pressed. - bool MainExit; // main() is completed. + bool UserBreak = false; // Ctrl+Break is pressed. + bool MainExit = false; // main() is completed. }; diff --git c/third_party/unrar/src/extract.cpp w/third_party/unrar/src/extract.cpp index 892ef0c8712e4..17ad224cc5fc9 100644 --- c/third_party/unrar/src/extract.cpp +++ w/third_party/unrar/src/extract.cpp @@ -902,6 +902,9 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) UnstoreFile(DataIO,Arc.FileHead.UnpSize); else { +#if defined (UNRAR_NO_EXCEPTIONS) + Unp->Init(Arc.FileHead.WinSize,Arc.FileHead.Solid); +#else try { Unp->Init(Arc.FileHead.WinSize,Arc.FileHead.Solid); @@ -912,6 +915,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) uiMsg(UIERROR_EXTRDICTOUTMEM,Arc.FileName,uint(Arc.FileHead.WinSize/0x40000000+(Arc.FileHead.WinSize%0x40000000!=0 ? 1 : 0))); throw; } +#endif // UNRAR_NO_EXCEPTIONS Unp->SetDestSize(Arc.FileHead.UnpSize); #ifndef SFX_MODULE diff --git c/third_party/unrar/src/extract.hpp w/third_party/unrar/src/extract.hpp index 18d8f8c9cb776..570475ec6560c 100644 --- c/third_party/unrar/src/extract.hpp +++ w/third_party/unrar/src/extract.hpp @@ -57,8 +57,8 @@ class CmdExtract unsigned long MatchedArgs; bool FirstFile; bool AllMatchesExact; - bool ReconstructDone; - bool UseExactVolName; + bool ReconstructDone=false; + bool UseExactVolName=false; // If any non-zero solid file was successfully unpacked before current. // If true and if current encrypted file is broken, obviously @@ -91,6 +91,11 @@ class CmdExtract void ExtractArchiveInit(Archive &Arc); bool ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat); static void UnstoreFile(ComprDataIO &DataIO,int64 DestUnpSize); + +#if defined(CHROMIUM_UNRAR) + int64 GetCurrentFileSize() { return DataIO.CurUnpWrite; } + bool IsMissingNextVolume() { return DataIO.NextVolumeMissing; } +#endif }; #endif diff --git c/third_party/unrar/src/file.cpp w/third_party/unrar/src/file.cpp index c6fab17328262..72e8cae42e441 100644 --- c/third_party/unrar/src/file.cpp +++ w/third_party/unrar/src/file.cpp @@ -19,6 +19,10 @@ File::File() ReadErrorMode=FREM_ASK; TruncatedAfterReadError=false; CurFilePos=0; + +#ifdef CHROMIUM_UNRAR + reader_delegate_ = nullptr; +#endif } @@ -52,6 +56,11 @@ bool File::Open(const std::wstring &Name,uint Mode) bool UpdateMode=(Mode & FMF_UPDATE)!=0; bool WriteMode=(Mode & FMF_WRITE)!=0; #ifdef _WIN_ALL +#if defined(CHROMIUM_UNRAR) + // Do not open a file handle since the sandbox doesn't allow it. Use the + // delegate provided by the caller. + return reader_delegate_; +#else uint Access=WriteMode ? GENERIC_WRITE:GENERIC_READ; if (UpdateMode) Access|=GENERIC_WRITE; @@ -97,7 +106,14 @@ bool File::Open(const std::wstring &Name,uint Mode) FILETIME ft={0xffffffff,0xffffffff}; // This value prevents atime modification. SetFileTime(hNewFile,NULL,&ft,NULL); } +#endif // defined(CHROMIUM_UNRAR) +#else + +#if defined(CHROMIUM_UNRAR) + // Do not open a file handle since the sandbox doesn't allow it. Use the + // delegate provided by the caller. + return reader_delegate_; #else int flags=UpdateMode ? O_RDWR:(WriteMode ? O_WRONLY:O_RDONLY); @@ -121,6 +137,7 @@ bool File::Open(const std::wstring &Name,uint Mode) WideToChar(Name,NameA); int handle=open(NameA.c_str(),flags); + #ifdef LOCK_EX #ifdef _OSF_SOURCE @@ -157,6 +174,7 @@ bool File::Open(const std::wstring &Name,uint Mode) TruncatedAfterReadError=false; } return Success; +#endif // defined(CHROMIUM_UNRAR) } @@ -180,6 +198,10 @@ bool File::WOpen(const std::wstring &Name) bool File::Create(const std::wstring &Name,uint Mode) { +#if defined(CHROMIUM_UNRAR) + // Since the Chromium sandbox does not allow the creation of files. + return true; +#else // 2025.09.03: Likely outdated info, see https://www.illumos.org/issues/2000 // OpenIndiana based NAS and CIFS shares fail to set the file time if file // was created in read+write mode and some data was written and not flushed @@ -218,6 +240,7 @@ bool File::Create(const std::wstring &Name,uint Mode) hFile=fopen(NameA.c_str(),WriteMode ? WRITEBINARY:CREATEBINARY); #endif #endif +#endif // defined(CHROMIUM_UNRAR) NewFile=true; HandleType=FILE_HANDLENORMAL; SkipClose=false; @@ -246,6 +269,9 @@ bool File::WCreate(const std::wstring &Name,uint Mode) bool File::Close() { +#if defined(CHROMIUM_UNRAR) + return reader_delegate_; +#endif bool Success=true; if (hFile!=FILE_BAD_HANDLE) @@ -401,7 +427,7 @@ int File::Read(void *Data,size_t Size) for (size_t I=0;IRead( + base::span((uint8_t*)Data, Size)); + return (ret < 0) ? -1 : (int)ret; + } +#endif #ifdef _WIN_ALL const size_t MaxDeviceRead=20000; const size_t MaxLockedRead=32768; @@ -526,6 +559,21 @@ void File::Seek(int64 Offset,int Method) bool File::RawSeek(int64 Offset,int Method) { +#if defined(CHROMIUM_UNRAR) + if (reader_delegate_) { + int64_t absolute_offset = Offset; + if (Method == SEEK_CUR) { + int64_t current = reader_delegate_->Tell(); + if (current == -1) return false; + absolute_offset += current; + } else if (Method == SEEK_END) { + int64_t len = reader_delegate_->GetLength(); + if (len == -1) return false; + absolute_offset += len; + } + return reader_delegate_->Seek(absolute_offset); + } +#endif if (hFile==FILE_BAD_HANDLE) return true; if (!IsSeekable()) // To extract archives from stdin with -si. @@ -535,7 +583,7 @@ bool File::RawSeek(int64 Offset,int Method) byte Buf[4096]; if (Method==SEEK_CUR || Method==SEEK_SET && Offset>=CurFilePos) { - uint64 SkipSize=Method==SEEK_CUR ? Offset:Offset-CurFilePos; + size_t SkipSize=Method==SEEK_CUR ? Offset:Offset-CurFilePos; while (SkipSize>0) // Reading to emulate seek forward. { int ReadSize=Read(Buf,(size_t)Min(SkipSize,ASIZE(Buf))); @@ -587,6 +635,9 @@ bool File::RawSeek(int64 Offset,int Method) int64 File::Tell() { +#if defined(CHROMIUM_UNRAR) + if (reader_delegate_) return reader_delegate_->Tell(); +#endif if (hFile==FILE_BAD_HANDLE) if (AllowExceptions) ErrHandler.SeekError(FileName); @@ -786,6 +837,9 @@ void File::GetOpenFileTime(RarTime *ftm,RarTime *ftc,RarTime *fta) int64 File::FileLength() { +#if defined(CHROMIUM_UNRAR) + if (reader_delegate_) return reader_delegate_->GetLength(); +#endif int64 SavePos=Tell(); Seek(0,SEEK_END); int64 Length=Tell(); @@ -796,6 +850,9 @@ int64 File::FileLength() bool File::IsDevice() { +#if defined(CHROMIUM_UNRAR) + return false; +#else if (hFile==FILE_BAD_HANDLE) return false; #ifdef _WIN_ALL @@ -804,6 +861,7 @@ bool File::IsDevice() #else return isatty(GetFD()); #endif +#endif // defined(CHROMIUM_UNRAR) } @@ -853,3 +911,9 @@ int64 File::Copy(File &Dest,int64 Length) return CopySize; } #endif + +#if defined(CHROMIUM_UNRAR) +void File::SetReaderDelegate(third_party_unrar::RarReaderDelegate* delegate) { + reader_delegate_ = delegate; +} +#endif // defined(CHROMIUM_UNRAR) diff --git c/third_party/unrar/src/file.hpp w/third_party/unrar/src/file.hpp index 67c1754987f63..033bbf51ac6c7 100644 --- c/third_party/unrar/src/file.hpp +++ w/third_party/unrar/src/file.hpp @@ -51,6 +51,10 @@ enum FILE_READ_ERROR_MODE { }; +#if defined(CHROMIUM_UNRAR) +#include "third_party/unrar/google/unrar_delegates.h" +#endif + class File { private: @@ -85,6 +89,11 @@ class File std::wstring FileName; FILE_ERRORTYPE ErrorType; + +#if defined(CHROMIUM_UNRAR) + third_party_unrar::RarReaderDelegate* reader_delegate_; +#endif // defined(CHROMIUM_UNRAR) + public: File(); virtual ~File(); @@ -119,7 +128,11 @@ class File static void StatToRarTime(struct stat &st,RarTime *ftm,RarTime *ftc,RarTime *fta); #endif void GetOpenFileTime(RarTime *ftm,RarTime *ftc=NULL,RarTime *fta=NULL); +#if defined(CHROMIUM_UNRAR) + virtual bool IsOpened() {return hFile!=FILE_BAD_HANDLE || reader_delegate_;} // 'virtual' for MultiFile class. +#else virtual bool IsOpened() {return hFile!=FILE_BAD_HANDLE;} // 'virtual' for MultiFile class. +#endif virtual int64 FileLength(); // 'virtual' for MultiFile class. void SetHandleType(FILE_HANDLETYPE Type) {HandleType=Type;} void SetLineInputMode(bool Mode) {LineInput=Mode;} @@ -135,6 +148,14 @@ class File void SetExceptions(bool Allow) {AllowExceptions=Allow;} void SetPreserveAtime(bool Preserve) {PreserveAtime=Preserve;} bool IsTruncatedAfterReadError() {return TruncatedAfterReadError;} + +#if defined(CHROMIUM_UNRAR) + // Since unrar runs in a sandbox, it doesn't have the permission to open + // files on the filesystem. Instead, the caller opens the file and passes + // the file delegate to unrar. This delegate is then used to read the file. + void SetReaderDelegate(third_party_unrar::RarReaderDelegate* delegate); +#endif // defined(CHROMIUM_UNRAR) + #ifdef _UNIX int GetFD() { diff --git c/third_party/unrar/src/filefn.cpp w/third_party/unrar/src/filefn.cpp index 1f34d266fabc5..06560edd9959d 100644 --- c/third_party/unrar/src/filefn.cpp +++ w/third_party/unrar/src/filefn.cpp @@ -303,6 +303,9 @@ uint GetFileAttr(const std::wstring &Name) bool SetFileAttr(const std::wstring &Name,uint Attr) { +#if defined(CHROMIUM_UNRAR) + return true; +#else #ifdef _WIN_ALL bool Success=SetFileAttributes(Name.c_str(),Attr)!=0; if (!Success) @@ -319,6 +322,7 @@ bool SetFileAttr(const std::wstring &Name,uint Attr) #else return false; #endif +#endif } diff --git c/third_party/unrar/src/hash.hpp w/third_party/unrar/src/hash.hpp index 99488e6a0d3c2..15cb226d90652 100644 --- c/third_party/unrar/src/hash.hpp +++ w/third_party/unrar/src/hash.hpp @@ -48,9 +48,9 @@ class DataHash uint gfExpCRC(uint N); // Speed gain seems to vanish above 8 CRC32 threads. - static const uint CRC32_POOL_THREADS=8; + static constexpr uint CRC32_POOL_THREADS=8u; // Thread pool must allow at least BLAKE2_THREADS_NUMBER threads. - static const uint HASH_POOL_THREADS=Max(BLAKE2_THREADS_NUMBER,CRC32_POOL_THREADS); + static constexpr uint HASH_POOL_THREADS=Max(BLAKE2_THREADS_NUMBER,CRC32_POOL_THREADS); HASH_TYPE HashType; uint CurCRC32; diff --git c/third_party/unrar/src/isnt.cpp w/third_party/unrar/src/isnt.cpp index d62e861b51af3..520d773daf392 100644 --- c/third_party/unrar/src/isnt.cpp +++ w/third_party/unrar/src/isnt.cpp @@ -1,5 +1,11 @@ #include "rar.hpp" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +// GetVersionEx() is deprecated, and the suggested replacement are +// the IsWindows*OrGreater() functions in VersionHelpers.h. We can't +// use that because there is no IsWindows11OrGreater() function yet. + DWORD WinNT() { static int dwPlatformId=-1; @@ -27,7 +33,7 @@ DWORD WinNT() #if 0 // Replace it with documented Windows 11 check when available. #include -#include +#include #pragma comment(lib, "wbemuuid.lib") static bool WMI_IsWindows10() @@ -109,3 +115,5 @@ bool IsWindows11OrGreater() } return IsWin11; } + +#pragma clang diagnostic pop diff --git c/third_party/unrar/src/list.cpp w/third_party/unrar/src/list.cpp index a9af7777e9b4e..627d156ff24db 100644 --- c/third_party/unrar/src/list.cpp +++ w/third_party/unrar/src/list.cpp @@ -308,7 +308,7 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo } else { - size_t DataSize=(size_t)Min(hd.PackSize,MAXPATHSIZE); + size_t DataSize=(size_t)Min(size_t{hd.PackSize},MAXPATHSIZE); std::vector Buf(DataSize+1); Arc.Read(Buf.data(),DataSize); Buf[DataSize] = 0; diff --git c/third_party/unrar/src/model.cpp w/third_party/unrar/src/model.cpp index 69d9267f7c428..e3ef5b7a8c90d 100644 --- c/third_party/unrar/src/model.cpp +++ w/third_party/unrar/src/model.cpp @@ -43,13 +43,27 @@ void ModelPPM::RestartModelRare() InitRL=-(MaxOrder < 12 ? MaxOrder:12)-1; MinContext = MaxContext = (RARPPM_CONTEXT*) SubAlloc.AllocContext(); if (MinContext == NULL) + { +#if defined(UNRAR_NO_EXCEPTIONS) + base::TerminateBecauseOutOfMemory(0); +#else throw std::bad_alloc(); +#endif // defined(UNRAR_NO_EXCEPTIONS) + } + MinContext->Suffix=NULL; OrderFall=MaxOrder; MinContext->U.SummFreq=(MinContext->NumStats=256)+1; FoundState=MinContext->U.Stats=(RARPPM_STATE*)SubAlloc.AllocUnits(256/2); if (FoundState == NULL) + { +#if defined(UNRAR_NO_EXCEPTIONS) + base::TerminateBecauseOutOfMemory(0); +#else throw std::bad_alloc(); +#endif // defined(UNRAR_NO_EXCEPTIONS) + } + for (RunLength=InitRL, PrevSuccess=i=0;i < 256;i++) { MinContext->U.Stats[i].Symbol=i; diff --git c/third_party/unrar/src/os.hpp w/third_party/unrar/src/os.hpp index f94b5b3a3bf2a..6c82949f7a53d 100644 --- c/third_party/unrar/src/os.hpp +++ w/third_party/unrar/src/os.hpp @@ -31,6 +31,7 @@ #define STRICT 1 #endif +#if !defined(CHROMIUM_UNRAR) // 'ifndef' check here is needed for unrar.dll header to avoid macro // re-definition warnings in third party projects. #ifndef UNICODE @@ -40,12 +41,15 @@ #define WINVER _WIN32_WINNT_WINXP #define _WIN32_WINNT _WIN32_WINNT_WINXP +#endif // !defined(CHROMIUM_UNRAR) -#if !defined(ZIPSFX) +#if !defined(ZIPSFX) && !defined(CHROMIUM_UNRAR) #define RAR_SMP #endif +#if !defined(CHROMIUM_UNRAR) #define WIN32_LEAN_AND_MEAN +#endif // CHROMIUM_UNRAR #include #include @@ -54,7 +58,9 @@ #include #pragma comment(lib, "PowrProf.lib") #include +#if !defined(CHROMIUM_UNRAR) #pragma comment(lib, "Psapi.lib") // For GetProcessMemoryInfo(). +#endif // !defined(CHROMIUM_UNRAR) #include #include #include @@ -67,7 +73,7 @@ // For WMI requests. #include -#include +#include #pragma comment(lib, "wbemuuid.lib") @@ -77,11 +83,13 @@ #include #include +#if !defined(CHROMIUM_UNRAR) // Use SSE only for x86/x64, not ARM Windows. #if defined(_M_IX86) || defined(_M_X64) #define USE_SSE #define SSE_ALIGNMENT 16 #endif +#endif // CHROMIUM_UNRAR #include #include @@ -151,6 +159,7 @@ #include #include +#if !defined(CHROMIUM_UNRAR) #ifdef __GNUC__ #if defined(__i386__) || defined(__x86_64__) #include @@ -159,6 +168,7 @@ #define SSE_ALIGNMENT 16 #endif #endif +#endif // CHROMIUM_UNRAR #if defined(__aarch64__) && (defined(__ARM_FEATURE_CRYPTO) || defined(__ARM_FEATURE_CRC32)) #include @@ -267,9 +277,16 @@ #endif #endif +// Disable this optimization in Chromium. Although the underlying architecture +// may allow unaligned access, C and C++ themselves do not allow this. Rather, +// unaligned loads should be written with either memcpy, or by endian-agnostic +// reassembling of values with shifts and ORs. Modern compilers recognize these +// patterns and generate the unaligned load anyway. +#if !defined(CHROMIUM_UNRAR) #if !defined(BIG_ENDIAN) && defined(_WIN_ALL) || defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) // Allow unaligned integer access, increases speed in some operations. #define ALLOW_MISALIGNED #endif +#endif #endif // _RAR_OS_ diff --git c/third_party/unrar/src/qopen.cpp w/third_party/unrar/src/qopen.cpp index e4ae8a9d1e782..73fb36dfd5aea 100644 --- c/third_party/unrar/src/qopen.cpp +++ w/third_party/unrar/src/qopen.cpp @@ -207,7 +207,7 @@ uint QuickOpen::ReadBuffer() { int64 SavePos=Arc->Tell(); Arc->File::Seek(RawDataStart+RawDataPos,SEEK_SET); - size_t SizeToRead=(size_t)Min(RawDataSize-RawDataPos,MaxBufSize-ReadBufSize); + size_t SizeToRead=(size_t)Min(size_t{RawDataSize-RawDataPos},MaxBufSize-ReadBufSize); if (Arc->SubHead.Encrypted) SizeToRead &= ~CRYPT_BLOCK_MASK; int ReadSize=0; diff --git c/third_party/unrar/src/rardefs.hpp w/third_party/unrar/src/rardefs.hpp index 378ccc7fbad2c..7f07c57371723 100644 --- c/third_party/unrar/src/rardefs.hpp +++ w/third_party/unrar/src/rardefs.hpp @@ -1,12 +1,38 @@ #ifndef _RAR_DEFS_ #define _RAR_DEFS_ +// These interfere textually with the numerics headers in +// `partition_alloc_base`, which are evaluated early through the +// inclusion of `base/containers/span.h`. +// +// When building for Chromium, include the necessary headers for the +// `std::` spellings of these. +#if defined(CHROMIUM_UNRAR) + +#include + +template +constexpr T Max (const T& a, const T& b) { + return std::max(a, b); +} + +template +constexpr T Min (const T& a, const T& b) { + return std::min(a, b); +} + +// `Abs()` appears unused. + +#else + #define Min(x,y) (((x)<(y)) ? (x):(y)) #define Max(x,y) (((x)>(y)) ? (x):(y)) // Universal replacement of abs function. #define Abs(x) (((x)<0) ? -(x):(x)) +#endif // defined(CHROMIUM_UNRAR) + #define ASIZE(x) (sizeof(x)/sizeof(x[0])) // MAXPASSWORD and MAXPASSWORD_RAR are expected to be multiple of @@ -19,7 +45,11 @@ // Set some arbitrary sensible limit to maximum path length to prevent // the excessive memory allocation for dynamically allocated strings. +#if defined(CHROMIUM_UNRAR) +inline constexpr size_t MAXPATHSIZE = 0x10000u; +#else #define MAXPATHSIZE 0x10000 +#endif // defined(CHROMIUM_UNRAR) #define MAXSFXSIZE 0x400000 @@ -37,7 +67,12 @@ #define PACK_MAX_DICT 0x1000000000ULL // 64 GB. // Maximum dictionary allowed by decompression. +#if defined(CHROMIUM_UNRAR_FUZZER) +// Try to avoid OOMs in fuzzer runs by limiting unpack size. +#define UNPACK_MAX_DICT 0x40000000ULL // 1 GiB. +#else #define UNPACK_MAX_DICT 0x1000000000ULL // 64 GB. +#endif #ifndef SFX_MODULE diff --git c/third_party/unrar/src/rdwrfn.cpp w/third_party/unrar/src/rdwrfn.cpp index a49a8bcedfcb8..f19ccef19afe9 100644 --- c/third_party/unrar/src/rdwrfn.cpp +++ w/third_party/unrar/src/rdwrfn.cpp @@ -153,6 +153,15 @@ int ComprDataIO::UnpRead(byte *Addr,size_t Count) void ComprDataIO::UnpWrite(byte *Addr,size_t Count) { +#if defined(CHROMIUM_UNRAR) + Archive *SrcArc=static_cast(SrcFile); + if (SrcArc->m_writer_delegate!=nullptr) + { + if (!SrcArc->m_writer_delegate->Write( + base::span(Addr, Count))) + ErrHandler.Exit(RARX_USERBREAK); + } +#endif #ifdef RARDLL CommandData *Cmd=((Archive *)SrcFile)->GetCommandData(); diff --git c/third_party/unrar/src/recvol5.cpp w/third_party/unrar/src/recvol5.cpp index e094b17119369..eb36229630c19 100644 --- c/third_party/unrar/src/recvol5.cpp +++ w/third_party/unrar/src/recvol5.cpp @@ -397,7 +397,7 @@ bool RecVolumes5::Restore(CommandData *Cmd,const std::wstring &Name,bool Silent) // We can have volumes of different size. Let's use data chunk // for largest volume size. - uint DataToProcess=(uint)Min(RecBufferSize,MaxVolSize-ProcessedSize); + uint DataToProcess=(uint)Min(uint{RecBufferSize},uint{MaxVolSize-ProcessedSize}); ProcessRS(Cmd,I,B,DataToProcess,false); } if (MaxRead==0) @@ -407,7 +407,7 @@ bool RecVolumes5::Restore(CommandData *Cmd,const std::wstring &Name,bool Silent) if (!ValidFlags[I]) { RecVolItem *Item=&RecItems[I]; - size_t WriteSize=(size_t)Min(MaxRead,Item->FileSize); + size_t WriteSize=(size_t)Min(size_t{MaxRead},size_t{Item->FileSize}); Item->f->Write(Buf+(J++)*RecBufferSize,WriteSize); Item->FileSize-=WriteSize; } diff --git c/third_party/unrar/src/secpassword.cpp w/third_party/unrar/src/secpassword.cpp index 8d8f298609a76..a32ea40e3ac25 100644 --- c/third_party/unrar/src/secpassword.cpp +++ w/third_party/unrar/src/secpassword.cpp @@ -1,6 +1,6 @@ #include "rar.hpp" -#if defined(_WIN_ALL) +#if defined(_WIN_ALL) && !defined(CHROMIUM_UNRAR) typedef BOOL (WINAPI *CRYPTPROTECTMEMORY)(LPVOID pData,DWORD cbData,DWORD dwFlags); typedef BOOL (WINAPI *CRYPTUNPROTECTMEMORY)(LPVOID pData,DWORD cbData,DWORD dwFlags); @@ -177,7 +177,7 @@ void SecHideData(void *Data,size_t DataSize,bool Encode,bool CrossProcess) { // CryptProtectMemory is not available in UWP and CryptProtectData // increases data size not allowing in place conversion. -#if defined(_WIN_ALL) +#if defined(_WIN_ALL) && !defined(CHROMIUM_UNRAR) // Try to utilize the secure Crypt[Un]ProtectMemory if possible. if (GlobalCryptLoader.pCryptProtectMemory==NULL) GlobalCryptLoader.Load(); diff --git c/third_party/unrar/src/strfn.cpp w/third_party/unrar/src/strfn.cpp index ed8f91fe2c04c..2f21dfdc5bc10 100644 --- c/third_party/unrar/src/strfn.cpp +++ w/third_party/unrar/src/strfn.cpp @@ -61,6 +61,27 @@ void ArcCharToWide(const char *Src,std::wstring &Dest,ACTW_ENCODING Encoding) UtfToWide(Src,Dest); else { +#if defined(CHROMIUM_UNRAR) + if (Encoding == ACTW_OEM) { + // OemToCharBuffA, called by IntToExt, is implemented by user32.dll which + // is not available in win32k lockdown sandbox. We can map from the OEM + // codepage using CP_OEMCP and MultiByteToWideChar from kernel32.dll + // instead, as we're also attempting to map to wide chars. + const size_t SrcLength = strlen(Src) + 1; + const int size = + MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED | MB_USEGLYPHCHARS, Src, + SrcLength, nullptr, 0); + if (size <= 0) { + Dest.clear(); + } else { + Dest.resize(size); + (void)::MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED | MB_USEGLYPHCHARS, + Src, SrcLength, &Dest[0], size); + } + } else { + CharToWide(Src, Dest); + } +#else std::string NameA; if (Encoding==ACTW_OEM) { @@ -68,6 +89,7 @@ void ArcCharToWide(const char *Src,std::wstring &Dest,ACTW_ENCODING Encoding) Src=NameA.data(); } CharToWide(Src,Dest); +#endif // defined(CHROMIUM_UNRAR) } #else // RAR for Unix. if (Encoding==ACTW_UTF8) @@ -407,7 +429,7 @@ void fmtitoa(int64 n,wchar *Str,size_t MaxSize) static wchar ThSep=0; // Thousands separator. #ifdef _WIN_ALL wchar Info[10]; - if (!ThSep!=0 && GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_STHOUSAND,Info,ASIZE(Info))>0) + if ((!ThSep)!=0 && GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_STHOUSAND,Info,ASIZE(Info))>0) ThSep=*Info; #elif defined(_UNIX) ThSep=*localeconv()->thousands_sep; diff --git c/third_party/unrar/src/unicode.cpp w/third_party/unrar/src/unicode.cpp index a9d103dbf3cd8..52c8720d1a85e 100644 --- c/third_party/unrar/src/unicode.cpp +++ w/third_party/unrar/src/unicode.cpp @@ -164,7 +164,7 @@ bool WideToCharMap(const wchar *Src,char *Dest,size_t DestSize,bool &Success) memset(Dest,0,DestSize); Success=true; - uint SrcPos=0,DestPos=0; + size_t SrcPos=0,DestPos=0; while (Src[SrcPos]!=0 && DestPos(ch & 0xffff); + // kernel32!LCMapStringEx instead of user32.dll!CharUpper due to win32k + // lockdown sandbox in chromium, user32.dll can't be loaded. + (void)LCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_UPPERCASE, + &ch_as_wide_char, 1, &ch_as_wide_char, 1, NULL, NULL, 0); + return int(ch_as_wide_char); +#else // CharUpper is more reliable than towupper in Windows, which seems to be // C locale dependent even in Unicode version. For example, towupper failed // to convert lowercase Russian characters. Use 0xffff mask to prevent crash // if value larger than 0xffff is passed to this function. return (int)(INT_PTR)CharUpper((wchar *)(INT_PTR)(ch&0xffff)); +#endif // defined(CHROMIUM_UNRAR) #else return towupper(ch); #endif @@ -843,10 +870,19 @@ int toupperw(int ch) int tolowerw(int ch) { #if defined(_WIN_ALL) +#if defined(CHROMIUM_UNRAR) + wchar_t ch_as_wide_char = static_cast(ch & 0xffff); + // kernel32!LCMapStringEx instead of user32.dll!CharLower due to win32k + // lockdown sandbox in chromium, user32.dll can't be loaded. + (void)LCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_LOWERCASE, + &ch_as_wide_char, 1, &ch_as_wide_char, 1, NULL, NULL, 0); + return int(ch_as_wide_char); +#else // CharLower is more reliable than towlower in Windows. // See comment for towupper above. Use 0xffff mask to prevent crash // if value larger than 0xffff is passed to this function. return (int)(INT_PTR)CharLower((wchar *)(INT_PTR)(ch&0xffff)); +#endif // defined(CHROMIUM_UNRAR) #else return towlower(ch); #endif @@ -883,7 +919,6 @@ int64 atoilw(const std::wstring &s) #ifdef DBCS_SUPPORTED -SupportDBCS gdbcs; SupportDBCS::SupportDBCS() { @@ -900,6 +935,11 @@ void SupportDBCS::Init() IsLeadByte[I]=IsDBCSLeadByte(I)!=0; } +// static +SupportDBCS& SupportDBCS::GetInstance() { + static SupportDBCS supportDBCS; + return supportDBCS; +} char* SupportDBCS::charnext(const char *s) { diff --git c/third_party/unrar/src/unicode.hpp w/third_party/unrar/src/unicode.hpp index 2d867b3aefef0..81cf99e380896 100644 --- c/third_party/unrar/src/unicode.hpp +++ w/third_party/unrar/src/unicode.hpp @@ -46,14 +46,14 @@ class SupportDBCS SupportDBCS(); void Init(); char* charnext(const char *s); + static SupportDBCS& GetInstance(); bool IsLeadByte[256]; bool DBCSMode; }; -extern SupportDBCS gdbcs; -inline char* charnext(const char *s) {return (char *)(gdbcs.DBCSMode ? gdbcs.charnext(s):s+1);} -inline bool IsDBCSMode() {return gdbcs.DBCSMode;} +inline char* charnext(const char *s) {return (char *)(SupportDBCS::GetInstance().DBCSMode ? SupportDBCS::GetInstance().charnext(s):s+1);} +inline bool IsDBCSMode() {return SupportDBCS::GetInstance().DBCSMode;} #else #define charnext(s) ((s)+1) diff --git c/third_party/unrar/src/unpack.cpp w/third_party/unrar/src/unpack.cpp index a5950ea1ac4e2..cdb89239f7a90 100644 --- c/third_party/unrar/src/unpack.cpp +++ w/third_party/unrar/src/unpack.cpp @@ -1,3 +1,9 @@ +// NOTE(vakh): The process.h file needs to be included first because "rar.hpp" +// defines certain macros that cause symbol redefinition errors +#if defined(UNRAR_NO_EXCEPTIONS) +#include "base/process/memory.h" +#endif // defined(UNRAR_NO_EXCEPTIONS) + #include "rar.hpp" #include "coder.cpp" @@ -15,6 +21,12 @@ #include "unpack50.cpp" #include "unpack50frag.cpp" +#if defined(UNRAR_NO_EXCEPTIONS) +#define UNRAR_FATAL_BAD_ALLOC(size) base::TerminateBecauseOutOfMemory(size) +#else +#define UNRAR_FATAL_BAD_ALLOC(size) throw std::bad_alloc() +#endif + Unpack::Unpack(ComprDataIO *DataIO) :Inp(true),VMCodeInp(true) { @@ -66,7 +78,7 @@ void Unpack::SetThreads(uint Threads) { // More than 8 threads are unlikely to provide noticeable gain // for unpacking, but would use the additional memory. - MaxUserThreads=Min(Threads,8); + MaxUserThreads=Min(Threads,8u); UnpThreadPool=new ThreadPool(MaxUserThreads); } #endif @@ -87,7 +99,7 @@ void Unpack::Init(uint64 WinSize,bool Solid) WinSize=MinAllocSize; if (WinSize>Min(0x10000000000ULL,UNPACK_MAX_DICT)) // Window size must not exceed 1 TB. - throw std::bad_alloc(); + UNRAR_FATAL_BAD_ALLOC(WinSize); // 32-bit build can't unpack dictionaries exceeding 32-bit even in theory. // Also we've not verified if WrapUp and WrapDown work properly in 32-bit @@ -95,7 +107,7 @@ void Unpack::Init(uint64 WinSize,bool Solid) // distances. Since such version is unlikely to allocate >2GB anyway, // we prohibit >2GB dictionaries for 32-bit build here. if (WinSize>0x80000000 && sizeof(size_t)<=4) - throw std::bad_alloc(); + UNRAR_FATAL_BAD_ALLOC(WinSize); // Solid block shall use the same window size for all files. // But if Window isn't initialized when Solid is set, it means that @@ -120,23 +132,27 @@ void Unpack::Init(uint64 WinSize,bool Solid) // or increasing the size of non-solid window. So we could safely reject // current window data without copying them to a new window. if (Solid && (Window!=NULL || Fragmented && WinSize>FragWindow.GetWinSize())) - throw std::bad_alloc(); + UNRAR_FATAL_BAD_ALLOC(WinSize); Alloc.delete_l(Window); // delete Window; Window=nullptr; +#if !defined(UNRAR_NO_EXCEPTIONS) try { +#endif // UNRAR_NO_EXCEPTIONS if (!Fragmented) Window=Alloc.new_l((size_t)WinSize,false); // Window=new byte[(size_t)WinSize]; +#if !defined(UNRAR_NO_EXCEPTIONS) } catch (std::bad_alloc) // Use the fragmented window in this case. { } +#endif // UNRAR_NO_EXCEPTIONS if (Window==nullptr) if (WinSize<0x1000000 || sizeof(size_t)>4) - throw std::bad_alloc(); // Exclude RAR4, small dictionaries and 64-bit. + UNRAR_FATAL_BAD_ALLOC(WinSize); else { if (WinSize>FragWindow.GetWinSize()) @@ -219,7 +235,7 @@ void Unpack::UnpInitData(bool Solid) UnpPtr=WrPtr=0; PrevPtr=0; FirstWinDone=false; - WriteBorder=Min(MaxWinSize,UNPACK_MAX_WRITE); + WriteBorder=Min(MaxWinSize,size_t{UNPACK_MAX_WRITE}); } // Filters never share several solid files, so we can safely reset them // even in solid archive. diff --git c/third_party/unrar/src/unpack30.cpp w/third_party/unrar/src/unpack30.cpp index 1fb0615a6be10..684e6a82b6e62 100644 --- c/third_party/unrar/src/unpack30.cpp +++ w/third_party/unrar/src/unpack30.cpp @@ -364,7 +364,7 @@ bool Unpack::ReadVMCodePPM() bool Unpack::AddVMCode(uint FirstByte,byte *Code,uint CodeSize) { VMCodeInp.InitBitInput(); - memcpy(VMCodeInp.InBuf,Code,Min(BitInput::MAX_SIZE,CodeSize)); + memcpy(VMCodeInp.InBuf,Code,Min(uint{BitInput::MAX_SIZE},CodeSize)); VM.Init(); uint FiltPos; diff --git c/third_party/unrar/src/unpack50.cpp w/third_party/unrar/src/unpack50.cpp index 137ce8fa98800..75ccb40fa62b5 100644 --- c/third_party/unrar/src/unpack50.cpp +++ w/third_party/unrar/src/unpack50.cpp @@ -409,7 +409,7 @@ void Unpack::UnpWriteBuf() // We prefer to write data in blocks not exceeding UNPACK_MAX_WRITE // instead of potentially huge MaxWinSize blocks. It also allows us // to keep the size of Filters array reasonable. - WriteBorder=WrapUp(UnpPtr+Min(MaxWinSize,UNPACK_MAX_WRITE)); + WriteBorder=WrapUp(UnpPtr+Min(MaxWinSize,size_t{UNPACK_MAX_WRITE})); // Choose the nearest among WriteBorder and WrPtr actual written border. // If border is equal to UnpPtr, it means that we have MaxWinSize data ahead. diff --git c/third_party/unrar/src/unpack50frag.cpp w/third_party/unrar/src/unpack50frag.cpp index 9208405e04eb6..1e559d158821b 100644 --- c/third_party/unrar/src/unpack50frag.cpp +++ w/third_party/unrar/src/unpack50frag.cpp @@ -1,3 +1,11 @@ +#include "base/process/memory.h" + +#if defined(UNRAR_NO_EXCEPTIONS) +#define UNRAR_FATAL_BAD_ALLOC(size) base::TerminateBecauseOutOfMemory(size) +#else +#define UNRAR_FATAL_BAD_ALLOC(size) throw std::bad_alloc() +#endif + FragmentedWindow::FragmentedWindow() { memset(Mem,0,sizeof(Mem)); @@ -38,7 +46,7 @@ void FragmentedWindow::Init(size_t WinSize) // than current, so we do not need blocks if they are smaller than // "size left / attempts left". Also we do not waste time to blocks // smaller than some arbitrary constant. - size_t MinSize=Max(Size/(ASIZE(Mem)-BlockNum), 0x400000); + size_t MinSize=Max(Size/(ASIZE(Mem)-BlockNum), size_t{0x400000}); byte *NewMem=NULL; while (Size>=MinSize) @@ -49,7 +57,7 @@ void FragmentedWindow::Init(size_t WinSize) Size-=Size/32; } if (NewMem==NULL) - throw std::bad_alloc(); + UNRAR_FATAL_BAD_ALLOC(Size); // Clean the window to generate the same output when unpacking corrupt // RAR files, which may access to unused areas of sliding dictionary. @@ -61,7 +69,8 @@ void FragmentedWindow::Init(size_t WinSize) BlockNum++; } if (TotalSize